Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package wofi for openSUSE:Factory checked in 
at 2024-02-12 18:53:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/wofi (Old)
 and      /work/SRC/openSUSE:Factory/.wofi.new.1815 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "wofi"

Mon Feb 12 18:53:03 2024 rev:6 rq:1146099 version:1.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/wofi/wofi.changes        2022-11-29 
13:23:36.158059701 +0100
+++ /work/SRC/openSUSE:Factory/.wofi.new.1815/wofi.changes      2024-02-12 
18:55:26.985518590 +0100
@@ -1,0 +2,27 @@
+Thu Feb  8 18:22:13 UTC 2024 - Jan Baier <jba...@suse.com>
+
+- update to 1.4:
+  * Added the config option drun-disable_prime to disable prime GPU offloading
+  * Updated meson command in readme
+  * Added wezterm to the default terminal list and moved termite to the end of 
the sane terminal section since it's now deprecated
+  * Updated the man pages with the new terminal order
+  * Refactor key mapping modifier logic
+  * Add return codes for custom keys
+  * on_exit_set_custom_key_return_code() now flushes stdio, this fixes #197
+  * Fixed #193. drun mode now respects Hidden
+  * Add `#expander` selector so expanded actions can be themed
+  * Rename `#expander` to `#expander-box`
+  * Added documentation for key_custom_n
+  * Fixed bug reported in https://github.com/swaywm/sway/issues/7915
+  * Fixed malloc for pre_display_exec
+  * Forgot to cleanup zombie processes
+  * Fixed closing the file handle when pre_display_exec=true
+  * Added pre_display_exec which allows pre_display_cmd to be directly 
executed with fork/exec instead of through the shell
+  * Fixed segfault when running non shell safe inputs with --pre-display-cmd 
and --allow-images
+  * Added the drun-print_desktop_file option
+  * Fixed weird tabbing behavior
+  * Fixed indentation
+  * Make sure that the first calculation of percent size is done when the 
window is visible
+  * Add documentation for `#expander-box`
+
+-------------------------------------------------------------------

Old:
----
  v1.3.tar.gz

New:
----
  v1.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ wofi.spec ++++++
--- /var/tmp/diff_new_pack.O3KfVQ/_old  2024-02-12 18:55:27.429534624 +0100
+++ /var/tmp/diff_new_pack.O3KfVQ/_new  2024-02-12 18:55:27.433534769 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package wofi
 #
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2024 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           wofi
-Version:        1.3
+Version:        1.4
 Release:        0
 Summary:        Launcher for wlroots compositors
 License:        GPL-3.0-only

++++++ v1.3.tar.gz -> v1.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/.hg_archival.txt 
new/wofi-v1.4/.hg_archival.txt
--- old/wofi-v1.3/.hg_archival.txt      2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/.hg_archival.txt      2024-02-05 00:26:21.000000000 +0100
@@ -1,4 +1,4 @@
 repo: 1c71dcd9c6a6dd54601820ce069e7c3ed7e946ca
-node: 1c32143a8460e01559e141c291500a6f4ddcf18c
+node: eab2b31e805564012e4f71920a8f87ba5f9f798c
 branch: default
-tag: v1.3
+tag: v1.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/.hgtags new/wofi-v1.4/.hgtags
--- old/wofi-v1.3/.hgtags       2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/.hgtags       2024-02-05 00:26:21.000000000 +0100
@@ -7,3 +7,4 @@
 b352d73b652aadd3b9da064267d6f3fa26007c25 v1.2.2
 e208549963dcd4ae89a18290aa598814c0b8eeb7 v1.2.3
 84e91980936bf85a854cee6881398cff9d27fce4 v1.2.4
+1c32143a8460e01559e141c291500a6f4ddcf18c v1.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/README.md new/wofi-v1.4/README.md
--- old/wofi-v1.3/README.md     2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/README.md     2024-02-05 00:26:21.000000000 +0100
@@ -5,12 +5,12 @@
 ## Dependencies
        libwayland-dev
        libgtk-3-dev
-       pkg-config
+       pkgconf
        meson
 ## Building
        hg clone https://hg.sr.ht/~scoopta/wofi
        cd wofi
-       meson build
+       meson setup build
        ninja -C build
 ## Installing
        sudo ninja -C build install
@@ -31,21 +31,8 @@
        dbus-daemon --session --address=unix:path=$XDG_RUNTIME_DIR/bus
 
 ## Packages
-Debian sid has a package in the official repos 
https://packages.debian.org/sid/wofi
+[![Packaging 
status](https://repology.org/badge/vertical-allrepos/wofi.svg)](https://repology.org/project/wofi/versions)
 
-Ubuntu focal has a package in universe https://packages.ubuntu.com/focal/wofi
-
-Arch has an AUR package for the current tip 
https://aur.archlinux.org/packages/wofi-hg/ and an official package for the 
current stable https://www.archlinux.org/packages/community/x86_64/wofi/
-
-NixOS has a packge in unstable 
https://nixos.org/nixos/packages.html?attr=wofi&channel=nixos-unstable&query=wofi
-
-Void Linux also has a package
-
-Fedora has an official package https://src.fedoraproject.org/rpms/wofi as well 
as one in COPR https://copr.fedorainfracloud.org/coprs/wef/wofi/
-
-FreeBSD has an official package 
https://www.freebsd.org/cgi/ports.cgi?query=wofi&stype=all&sektion=x11
-
-Gentoo has a portage overlay 
https://gpo.zugaina.org/Overlays/guru/gui-apps/wofi
 ## Documentation
 The official documentation is provided by the man pages in this repository, 
sample styling can be found here https://cloudninja.pw/docs/wofi.html
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/man/wofi-api.3 new/wofi-v1.4/man/wofi-api.3
--- old/wofi-v1.3/man/wofi-api.3        2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/man/wofi-api.3        2024-02-05 00:26:21.000000000 +0100
@@ -106,7 +106,7 @@
 
 .TP
 .B void wofi_term_run(const char* cmd)
-Runs the provided cmd in a terminal emulator. The following order is used for 
picking a terminal emulator: The user specified terminal, kitty, termite, 
alacritty, foot, gnome\-terminal, weston\-terminal. If none of these can be 
found execution will fail.
+Runs the provided cmd in a terminal emulator. The following order is used for 
picking a terminal emulator: The user specified terminal, kitty, alacritty, 
wezterm, foot, termite, gnome\-terminal, weston\-terminal. If none of these can 
be found execution will fail.
 
 .B const char* cmd
 \- The command to run, this is invoked by doing \fBterm \-\- cmd\fR.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/man/wofi-keys.7 
new/wofi-v1.4/man/wofi-keys.7
--- old/wofi-v1.3/man/wofi-keys.7       2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/man/wofi-keys.7       2024-02-05 00:26:21.000000000 +0100
@@ -3,7 +3,7 @@
 wofi \- Key names for custom binds
 
 .SH DESCRIPTION
-This is a list of the key names that can be used for custom binding, these are 
taken from gdk/gdkkeysyms.h. Certain keys cannot have the shift modifier 
attached as holding shift while using these keys causes a completely different 
key press to be registered. For example Shift_L\-j is invalid as holding shift 
while pressing j changes the key into J so J should be registered as the key 
instead of Shift_L\-j. This is the case with all alphanumeric chars as well as 
Tab which turns into ISO_Left_Tab.
+This is a list of the key names that can be used for custom binding. These are 
taken from gdk/gdkkeysyms.h with exception to modifiers. Certain keys cannot 
have the shift modifier attached as holding shift while using these keys causes 
a completely different key press to be registered. For example Shift\-j is 
invalid as holding shift while pressing j changes the key into J so Shift-J 
should be registered as the key instead of Shift\-j. This is the case with all 
alphanumeric chars as well as Tab which turns into ISO_Left_Tab.
 
 .SH KEY NAMES
 .B BackSpace
@@ -4543,3 +4543,10 @@
 .B LogWindowTree
 .br
 .B LogGrabInfo
+
+.SH MODIFIER NAMES
+.B Shift
+.br
+.B Ctrl
+.br
+.B Alt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/man/wofi.1 new/wofi-v1.4/man/wofi.1
--- old/wofi-v1.3/man/wofi.1    2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/man/wofi.1    2024-02-05 00:26:21.000000000 +0100
@@ -63,7 +63,7 @@
 Specifies the cache file to load/store cache, default is 
$XDG_CACHE_HOME/wofi\-<mode name> where <mode name> is the name of the mode, if 
$XDG_CACHE_HOME is not specified ~/.cache is used.
 .TP
 .B \-t, \-\-term=\fITERM\fR
-Specifies the term to use when running a program in a terminal. This overrides 
the default terminal run order which is kitty, termite, alacritty, foot, 
gnome\-terminal, weston\-terminal in that order.
+Specifies the term to use when running a program in a terminal. This overrides 
the default terminal run order which is kitty, alacritty, wezterm, foot, 
termite, gnome\-terminal, weston\-terminal in that order.
 .TP
 .B \-P, \-\-password \fR[character]
 Runs wofi in password mode with an optional password character to use. If no 
character is specified * is used by default.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/man/wofi.5 new/wofi-v1.4/man/wofi.5
--- old/wofi-v1.3/man/wofi.5    2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/man/wofi.5    2024-02-05 00:26:21.000000000 +0100
@@ -65,7 +65,7 @@
 Specifies the cache file to load/store cache, default is 
$XDG_CACHE_HOME/wofi\-<mode name> where <mode name> is the name of the mode, if 
$XDG_CACHE_HOME is not specified ~/.cache is used.
 .TP
 .B term=\fITERM\fR
-Specifies the term to use when running a program in a terminal. This overrides 
the default terminal run order which is kitty, termite, alacritty, foot, 
gnome\-terminal, weston\-terminal in that order.
+Specifies the term to use when running a program in a terminal. This overrides 
the default terminal run order which is kitty, alacritty, wezterm, foot, 
termite, gnome\-terminal, weston\-terminal in that order.
 .TP
 .B password=\fICHARACTER\fR
 Runs wofi in password mode using the specified character, default is false.
@@ -167,7 +167,10 @@
 Specifies the key to use in order to hide/show the search bar. There is no 
default. See \fBwofi\-keys\fR(7) for the key codes.
 .TP
 .B key_copy=\fIKEY\fR
-Specifies the key to use in order to copy the action text for the current 
entry. The default is Control_L-c. See \fBwofi\-keys\fR(7) for the key codes.
+Specifies the key to use in order to copy the action text for the current 
entry. The default is Ctrl-c. See \fBwofi\-keys\fR(7) for the key codes.
+.TP
+.B key_custom_(n)=\fIKEY\fR
+Allows for configuring custom exit codes. For example setting 
key_custom_0=Ctrl-0 will make it so if you press Ctrl-0 wofi will set its exit 
status to 10. This will not cause wofi to exit, it will only set its exit code 
for when it does. 20 of these keys are configurable numbered 0-19. The exit 
status used is 10+n where n is the number attached to key_custom_n. There are 
no defaults for these. See \fBwofi\-keys\fR(7) for the key codes.
 .TP
 .B line_wrap=\fIMODE\fR
 Specifies the line wrap mode to use. The options are off, word, char, and 
word_char. Default is off.
@@ -189,6 +192,9 @@
 .TP
 .B single_click=\fIBOOL\fR
 Specifies whether or not actions should be executed on a single click or a 
double click. Default is false.
+.TP
+.B pre_display_exec=\fIBOOL\fR
+This modifies the behavior of pre_display_cmd and causes the command in 
question to be directly executed via fork/exec rather than through the shell.
 
 .SH CSS SELECTORS
 Any GTK widget can be selected by using the name of its CSS node, these 
however might change with updates and are not guaranteed to stay constant. Wofi 
also provides certain widgets with names and classes which can be referenced 
from CSS to give access to the most important widgets easily. \fBwofi\fR(7) 
contains the current widget layout used by wofi so if you want to get into CSS 
directly using GTK widget names look there for info.
@@ -237,6 +243,10 @@
 .B #entry
 .br
 The name of all entries.
+.TP
+.B #expander-box
+.br
+The name of all boxes shown when expanding entries with multiple actions
 
 .SH COLORS
 The colors file should be formatted as new line separated hex values. These 
values should be in the standard HTML format and begin with a hash. These 
colors will be loaded however wofi doesn't know what color should be used for 
what so you must reference them from your CSS.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/man/wofi.7 new/wofi-v1.4/man/wofi.7
--- old/wofi-v1.3/man/wofi.7    2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/man/wofi.7    2024-02-05 00:26:21.000000000 +0100
@@ -53,6 +53,12 @@
 .TP
 .B display_generic=\fIBOOL\fR
 If true then generic names will be displayed in () next to the application 
name, default is false.
+.TP
+.B disable_prime=\fIBOOL\fR
+If true then wofi will ignore the PrefersNonDefaultGPU desktop variable, 
specifically this prevents wofi from setting DRI_PRIME, default is false.
+.TP
+.B print_desktop_file=\fIBOOL\fR
+If true the path to the desktop file and the name of the corresponding 
action(if present) will be printed to stdout instead of invoking it, default is 
false.
 
 .SH DRUN
 When images are enabled drun mode will pull icon themes however being a GTK 
app it's possible you'll need to run gtk\-update\-icon\-cache to get them to 
apply.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/meson.build new/wofi-v1.4/meson.build
--- old/wofi-v1.3/meson.build   2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/meson.build   2024-02-05 00:26:21.000000000 +0100
@@ -1,4 +1,4 @@
-project('wofi', 'c', version : 'v1.3', default_options : ['c_std=c99', 
'buildtype=release', 'warning_level=2'])
+project('wofi', 'c', version : 'v1.4', default_options : ['c_std=c99', 
'buildtype=release', 'warning_level=2'])
 cc = meson.get_compiler('c')
 
 pkgcfg = import('pkgconfig')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/modes/drun.c new/wofi-v1.4/modes/drun.c
--- old/wofi-v1.3/modes/drun.c  2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/modes/drun.c  2024-02-05 00:26:21.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2019-2022 Scoopta
+ *  Copyright (C) 2019-2023 Scoopta
  *  This file is part of Wofi
  *  Wofi is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -29,7 +29,7 @@
 #include <gtk/gtk.h>
 #include <gio/gdesktopappinfo.h>
 
-static const char* arg_names[] = {"print_command", "display_generic"};
+static const char* arg_names[] = {"print_command", "display_generic", 
"disable_prime", "print_desktop_file"};
 
 static struct mode* mode;
 
@@ -43,6 +43,8 @@
 
 static bool print_command;
 static bool display_generic;
+static bool disable_prime;
+static bool print_desktop_file;
 
 static char* get_search_text(char* file) {
        GDesktopAppInfo* info = g_desktop_app_info_new_from_filename(file);
@@ -75,7 +77,8 @@
 
 static bool populate_widget(char* file, char* action, struct widget_builder* 
builder) {
        GDesktopAppInfo* info = g_desktop_app_info_new_from_filename(file);
-       if(info == NULL || !g_app_info_should_show(G_APP_INFO(info))) {
+       if(info == NULL || !g_app_info_should_show(G_APP_INFO(info)) ||
+                       g_desktop_app_info_get_is_hidden(info)) {
                return false;
        }
        const char* name;
@@ -335,6 +338,8 @@
 
        print_command = strcmp(config_get(config, "print_command", "false"), 
"true") == 0;
        display_generic = strcmp(config_get(config, "display_generic", 
"false"), "true") == 0;
+       disable_prime = strcmp(config_get(config, "disable_prime", "false"), 
"true") == 0;
+       print_desktop_file = strcmp(config_get(config, "print_desktop_file", 
"false"), "true") == 0;
 
        entries = map_init();
        struct wl_list* cache = wofi_read_cache(mode);
@@ -407,7 +412,7 @@
 
 static void set_dri_prime(GDesktopAppInfo* info) {
        bool dri_prime = g_desktop_app_info_get_boolean(info, 
"PrefersNonDefaultGPU");
-       if(dri_prime) {
+       if(dri_prime && !disable_prime) {
                setenv("DRI_PRIME", "1", true);
        }
 }
@@ -445,6 +450,9 @@
                        printf("%s\n", cmd);
                        free(cmd);
                        exit(0);
+               } else if(print_desktop_file) {
+                       printf("%s\n", cmd);
+                       exit(0);
                } else {
                        set_dri_prime(info);
                        if(uses_dbus(info)) {
@@ -465,6 +473,9 @@
                        printf("%s\n", cmd);
                        free(cmd);
                        fprintf(stderr, "Printing the command line for an 
action is not supported\n");
+               } else if(print_desktop_file) {
+                       printf("%s %s\n", cmd, action);
+                       exit(0);
                } else {
                        set_dri_prime(info);
                        g_desktop_app_info_launch_action(info, action, NULL);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wofi-v1.3/src/wofi.c new/wofi-v1.4/src/wofi.c
--- old/wofi-v1.3/src/wofi.c    2022-10-07 04:35:13.000000000 +0200
+++ new/wofi-v1.4/src/wofi.c    2024-02-05 00:26:21.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2019-2022 Scoopta
+ *  Copyright (C) 2019-2024 Scoopta
  *  This file is part of Wofi
  *  Wofi is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -42,8 +42,10 @@
 #include <gdk/gdkwayland.h>
 
 #define PROTO_VERSION(v1, v2) (v1 < v2 ? v1 : v2)
+#define _UNUSED(x) (void)(x)
+#define CUSTOM_KEY_NUMBER 20
 
-static const char* terminals[] = {"kitty", "termite", "alacritty", "foot", 
"gnome-terminal", "weston-terminal"};
+static const char* terminals[] = {"kitty", "alacritty", "wezterm", "foot", 
"termite", "gnome-terminal", "weston-terminal"};
 
 enum location {
        LOCATION_CENTER,
@@ -105,9 +107,14 @@
 static bool has_joined_mode = false;
 static char* copy_exec = NULL;
 static char* pre_display_cmd = NULL;
+static bool pre_display_exec = false;
 static bool single_click = false;
+static GdkModifierType shift_mask = GDK_SHIFT_MASK;
+static GdkModifierType ctrl_mask = GDK_CONTROL_MASK;
+static GdkModifierType alt_mask = GDK_MOD1_MASK;
 
 static struct map* keys;
+static struct map* mods;
 
 static struct wl_display* wl = NULL;
 static struct wl_surface* wl_surface;
@@ -127,6 +134,8 @@
        void (*action)(void);
 };
 
+static int custom_key_return_code = EXIT_SUCCESS;
+
 static void nop() {}
 
 static void add_interface(void* data, struct wl_registry* registry, uint32_t 
name, const char* interface, uint32_t version) {
@@ -260,6 +269,9 @@
        map_put(mode_map, "img-base64-noscale", "true");
        map_put(mode_map, "text", "true");
 
+       if(text == NULL) {
+               return NULL;
+       }
        char* original = strdup(text);
        char* mode1 = NULL;
        char* mode2 = NULL;
@@ -404,29 +416,87 @@
                char line[128]; // you'd think this caps the line's length to 
128, but it's just a buffer which due to the nature of fgets() splits on lines
                size_t size = 0;
                // first, prepare cmd_labeltext to be each entry's actual 
comamand to run, aka replacing 'cat %s' to be 'cat filename'
-               if ((asprintf(&cmd_labeltext, pre_display_cmd, nodetext)) == 
-1) {
+               if(asprintf(&cmd_labeltext, pre_display_cmd, nodetext) == -1) {
                        fprintf(stderr, "error parsing pre_display_cmd to 
run\n");
                        exit(EXIT_FAILURE);
                }
                // then, run the command
-               fp_labeltext = popen(cmd_labeltext, "r");
-               if (fp_labeltext == NULL) {
+               if(pre_display_exec) {
+                       int fds[2];
+                       if(pipe(fds) == -1) {
+                               perror("pipe broken");
+                               exit(1);
+                       }
+                       if(fork() == 0) {
+                               close(fds[0]);
+                               dup2(fds[1], STDOUT_FILENO);
+
+                               char* cmd = strdup(pre_display_cmd);
+                               char* space = strchr(cmd, ' ');
+                               if(space != NULL) {
+                                       *space = 0;
+                               }
+
+
+                               size_t space_count = 0;
+                               char* tmp_space = space;
+                               for(; (tmp_space = strchr(tmp_space + 1, ' ')) 
!= NULL; ++space_count);
+
+                               char** args = malloc((sizeof(char*) * 
(space_count + 2)));
+                               args[0] = cmd;
+                               args[1] = space + 1;
+                               args[space_count + 2] = NULL;
+
+                               //> 0 is used because args[0] is the command
+                               for(size_t count = space_count; count > 0; 
--count) {
+                                       char* arg = strrchr(space + 1, ' ');
+                                       args[count + 1] = arg + 1;
+                                       *arg = 0;
+                               }
+
+                               for(size_t count = 1; count <= space_count + 1; 
++count) {
+                                       if(strstr(args[count], "%s") != NULL) {
+                                               if(asprintf(&args[count], 
args[count], nodetext) == -1) {
+                                                       fprintf(stderr, "error 
parsing pre_display_cmd to run\n");
+                                                       exit(EXIT_FAILURE);
+                                               }
+                                       }
+                               }
+
+                               execvp(cmd, args);
+                               free(cmd);
+                               free(args);
+                               fprintf(stderr, "error executing '%s'\n", 
cmd_labeltext);
+                               exit(1);
+                       }
+                       close(fds[1]);
+
+                       fp_labeltext = fdopen(fds[0], "r");
+               } else {
+                       fp_labeltext = popen(cmd_labeltext, "r");
+               }
+               if(fp_labeltext == NULL) {
                        fprintf(stderr, "error executing '%s'\n", 
cmd_labeltext);
                        exit(EXIT_FAILURE);
-               } else if (fgets(line, sizeof(line), fp_labeltext) != NULL) {
+               } else if(fgets(line, sizeof(line), fp_labeltext) != NULL) {
                        // lastly, read the output of said command, and put it 
into the text variable to be used for the label widgets
                        // consider using 'printf %.10s as your 
--pre-display-cmd to limit a string to a determined width. 10 here is an example
                        size += strlen(line)+1; // we need place for the \0 of 
strcpy
                        text = (char *) realloc(text, size);
                        strcpy(text, line);
-                       while (fgets(line, sizeof(line), fp_labeltext) != NULL) 
{
+                       while(fgets(line, sizeof(line), fp_labeltext) != NULL) {
                                size += strlen(line);
                                text = (char *) realloc(text, size);
                                strncat(text, line, size);
                        }
                }
 
-               pclose(fp_labeltext);
+               if(pre_display_exec) {
+                       fclose(fp_labeltext);
+                       while(waitpid(-1, NULL, WNOHANG) > 0);
+               } else {
+                       pclose(fp_labeltext);
+               }
        }
 
        if(allow_images) {
@@ -584,6 +654,7 @@
                gtk_expander_set_label_widget(GTK_EXPANDER(parent), box);
 
                GtkWidget* exp_box = gtk_list_box_new();
+               gtk_widget_set_name(exp_box, "expander-box");
                
gtk_list_box_set_activate_on_single_click(GTK_LIST_BOX(exp_box), single_click);
                g_signal_connect(exp_box, "row-activated", 
G_CALLBACK(activate_item), NULL);
                gtk_container_add(GTK_CONTAINER(parent), exp_box);
@@ -1051,29 +1122,48 @@
 }
 
 static void select_first(void) {
-       GtkFlowBoxChild* child = 
gtk_flow_box_get_child_at_index(GTK_FLOW_BOX(inner_box), 1);
+       GtkFlowBoxChild* child = 
gtk_flow_box_get_child_at_index(GTK_FLOW_BOX(inner_box), 0);
        gtk_widget_grab_focus(GTK_WIDGET(child));
        gtk_flow_box_select_child(GTK_FLOW_BOX(inner_box), 
GTK_FLOW_BOX_CHILD(child));
 }
 
-static GdkModifierType get_mask_from_keyval(guint keyval) {
-       switch(keyval) {
-       case GDK_KEY_Shift_L:
-       case GDK_KEY_Shift_R:
+static GdkModifierType get_mask_from_keystate(guint state) {
+       if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) {
                return GDK_SHIFT_MASK;
-       case GDK_KEY_Control_L:
-       case GDK_KEY_Control_R:
+       }
+
+       if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) {
                return GDK_CONTROL_MASK;
-       case GDK_KEY_Alt_L:
-       case GDK_KEY_Alt_R:
+       }
+
+       // Alt
+       if ((state & GDK_MOD1_MASK) == GDK_MOD1_MASK) {
                return GDK_MOD1_MASK;
+       }
+
+       return 0;
+}
+
+static char* get_name_from_mask(GdkModifierType mask) {
+       switch(mask) {
+       case GDK_SHIFT_MASK:
+               return "Shift";
+       case GDK_CONTROL_MASK:
+               return "Ctrl";
+       case GDK_MOD1_MASK:
+               return "Alt";
        default:
-               return 0;
+               return NULL;
        }
 }
 
 static GdkModifierType get_mask_from_name(char* name) {
-       return get_mask_from_keyval(gdk_keyval_from_name(name));
+       GdkModifierType* mask = map_get(mods, name);
+       if (mask) {
+               return *mask;
+       }
+
+       return 0;
 }
 
 static void move_up(void) {
@@ -1114,12 +1204,21 @@
                select_first();
                return;
        }
+
        gtk_widget_child_focus(window, GTK_DIR_TAB_FORWARD);
+
+       if(gtk_widget_has_focus(entry)) {
+               select_first();
+       }
 }
 
 static void move_backward(void) {
        user_moved = true;
        gtk_widget_child_focus(window, GTK_DIR_TAB_BACKWARD);
+
+       if(gtk_widget_has_focus(entry)) {
+               move_backward();
+       }
 }
 
 static void move_pgup(void) {
@@ -1200,7 +1299,43 @@
        }
 }
 
+static void on_exit_set_custom_key_return_code(int status, void* data) {
+       _UNUSED(data);
+       if (status == EXIT_SUCCESS) {
+               fflush(stdout);
+               fflush(stderr);
+               _exit(custom_key_return_code);
+       }
+}
+
+static void do_custom_key(int custom_key_num) {
+       custom_key_return_code = custom_key_num + 10;
+}
+
+static void do_custom_key_0(void) {do_custom_key(0);}
+static void do_custom_key_1(void) {do_custom_key(1);}
+static void do_custom_key_2(void) {do_custom_key(2);}
+static void do_custom_key_3(void) {do_custom_key(3);}
+static void do_custom_key_4(void) {do_custom_key(4);}
+static void do_custom_key_5(void) {do_custom_key(5);}
+static void do_custom_key_6(void) {do_custom_key(6);}
+static void do_custom_key_7(void) {do_custom_key(7);}
+static void do_custom_key_8(void) {do_custom_key(8);}
+static void do_custom_key_9(void) {do_custom_key(9);}
+static void do_custom_key_10(void) {do_custom_key(10);}
+static void do_custom_key_11(void) {do_custom_key(11);}
+static void do_custom_key_12(void) {do_custom_key(12);}
+static void do_custom_key_13(void) {do_custom_key(13);}
+static void do_custom_key_14(void) {do_custom_key(14);}
+static void do_custom_key_15(void) {do_custom_key(15);}
+static void do_custom_key_16(void) {do_custom_key(16);}
+static void do_custom_key_17(void) {do_custom_key(17);}
+static void do_custom_key_18(void) {do_custom_key(18);}
+static void do_custom_key_19(void) {do_custom_key(19);}
+
 static bool do_key_action(GdkEvent* event, char* mod, void (*action)(void)) {
+       // GTK children focus gets all messed up if we don't first blow away any
+       // modifier keystate that's currently happening.
        if(mod != NULL) {
                GdkModifierType mask = get_mask_from_name(mod);
                if((event->key.state & mask) == mask) {
@@ -1280,9 +1415,24 @@
                return FALSE;
        }
 
-
        bool key_success = true;
-       struct key_entry* key_ent = map_get(keys, 
gdk_keyval_name(event->key.keyval));
+       struct key_entry* key_ent = NULL;
+       char* mod = NULL;
+
+       if (has_mod(event->key.state)) {
+               char* keyval = gdk_keyval_name(event->key.keyval);
+               GdkModifierType mask = get_mask_from_keystate(event->key.state);
+               mod = get_name_from_mask(mask);
+               size_t len = strlen(mod) + 1 + strlen(keyval) + 1;
+               char* mod_keyval = malloc(len);
+               strcpy(mod_keyval, mod);
+               strcat(mod_keyval, "-");
+               strcat(mod_keyval, keyval);
+               key_ent = map_get(keys, mod_keyval);
+               free(mod_keyval);
+       } else {
+               key_ent = map_get(keys, gdk_keyval_name(event->key.keyval));
+       }
 
        if(key_ent != NULL && key_ent->action != NULL) {
                key_success = do_key_action(event, key_ent->mod, 
key_ent->action);
@@ -1486,7 +1636,7 @@
        return NULL;
 }
 
-static void parse_mods(char* key, void (*action)(void)) {
+static void add_key_entry(char* key, void (*action)(void)) {
        char* tmp = strdup(key);
        char* save_ptr;
        char* str = strtok_r(tmp, ",", &save_ptr);
@@ -1495,22 +1645,20 @@
                        break;
                }
                char* hyphen = strchr(str, '-');
-               char* mod;
+               char* mod = NULL;
+               GdkModifierType modifier = 0;
                if(hyphen != NULL) {
-                       *hyphen = 0;
-                       guint key1 = gdk_keyval_from_name(str);
-                       guint key2 = gdk_keyval_from_name(hyphen + 1);
-                       if(get_mask_from_keyval(key1) != 0) {
+                       *hyphen = '\0';
+                       modifier = get_mask_from_name(str);
+                       if (modifier) {
                                mod = str;
                                str = hyphen + 1;
-                       } else if(get_mask_from_keyval(key2) != 0) {
-                               mod = hyphen + 1;
                        } else {
-                               fprintf(stderr, "Neither %s nor %s is a 
modifier, this is not supported\n", str, hyphen + 1);
-                               mod = NULL;
+                               fprintf(stderr,
+                                               "Could not parse %s as a 
modifier. Valid modifiers are "
+                                               "Ctrl, Shift, and Alt.\n",
+                                               str);
                        }
-               } else {
-                       mod = NULL;
                }
                struct key_entry* entry = malloc(sizeof(struct key_entry));
                if(mod == NULL) {
@@ -1519,7 +1667,20 @@
                        entry->mod = strdup(mod);
                }
                entry->action = action;
-               map_put_void(keys, str, entry);
+               char* map_key = NULL;
+
+               if (mod) {
+                       size_t len = strlen(mod) + 1 + strlen(str) + 1;
+                       map_key = malloc(len);
+                       strcpy(map_key, mod);
+                       strcat(map_key, "-");
+                       strcat(map_key, str);
+               } else {
+                       map_key = strdup(str);
+               }
+
+               map_put_void(keys, map_key, entry);
+               free(map_key);
        } while((str = strtok_r(NULL, ",", &save_ptr)) != NULL);
        free(tmp);
 }
@@ -1572,12 +1733,24 @@
        return G_SOURCE_CONTINUE;
 }
 
+static gboolean do_percent_size_first(gpointer data){
+       gdk_threads_add_timeout(50, do_percent_size, data);
+       do_percent_size(data);
+       return G_SOURCE_REMOVE;
+}
+
 void wofi_init(struct map* _config) {
        config = _config;
        char* width_str = config_get(config, "width", "50%");
        char* height_str = config_get(config, "height", "40%");
        width = strtol(width_str, NULL, 10);
        height = strtol(height_str, NULL, 10);
+
+       if(width > UINT16_MAX || height > UINT16_MAX) {
+               fprintf(stderr, "Do you actually have a monitor big enough to 
see this O_o? Dimensions can be no larger than %ux%u\n", UINT16_MAX, 
UINT16_MAX);
+               exit(1);
+       }
+
        x = map_get(config, "x");
        y = map_get(config, "y");
        bool normal_window = strcmp(config_get(config, "normal_window", 
"false"), "true") == 0;
@@ -1622,39 +1795,94 @@
        char* layer = config_get(config, "layer", "top");
        copy_exec = config_get(config, "copy_exec", "wl-copy");
        pre_display_cmd = map_get(config, "pre_display_cmd");
+       pre_display_exec = strcmp(config_get(config, "pre_display_exec", 
"false"), "true") == 0;
        single_click = strcmp(config_get(config, "single_click", "false"), 
"true") == 0;
 
        keys = map_init_void();
+       mods = map_init_void();
 
-
-
-       char* key_up = config_get(config, "key_up", "Up");
-       char* key_down = config_get(config, "key_down", "Down");
-       char* key_left = config_get(config, "key_left", "Left");
-       char* key_right = config_get(config, "key_right", "Right");
-       char* key_forward = config_get(config, "key_forward", "Tab");
-       char* key_backward = config_get(config, "key_backward", "ISO_Left_Tab");
-       char* key_submit = config_get(config, "key_submit", "Return");
-       char* key_exit = config_get(config, "key_exit", "Escape");
-       char* key_pgup = config_get(config, "key_pgup", "Page_Up");
-       char* key_pgdn = config_get(config, "key_pgdn", "Page_Down");
-       char* key_expand = config_get(config, "key_expand", "");
-       char* key_hide_search = config_get(config, "key_hide_search", "");
-       char* key_copy = config_get(config, "key_copy", "Control_L-c");
-
-       parse_mods(key_up, move_up);
-       parse_mods(key_down, move_down);
-       parse_mods(key_left, move_left);
-       parse_mods(key_right, move_right);
-       parse_mods(key_forward, move_forward);
-       parse_mods(key_backward, move_backward);
-       parse_mods(key_submit, NULL); //submit is a special case, when a NULL 
action is encountered submit is used instead
-       parse_mods(key_exit, do_exit);
-       parse_mods(key_pgup, move_pgup);
-       parse_mods(key_pgdn, move_pgdn);
-       parse_mods(key_expand, do_expand);
-       parse_mods(key_hide_search, do_hide_search);
-       parse_mods(key_copy, do_copy);
+       map_put_void(mods, "Shift", &shift_mask);
+       map_put_void(mods, "Ctrl", &ctrl_mask);
+       map_put_void(mods, "Alt", &alt_mask);
+
+       // First pass maps the default key entries.
+       // Second pass maps any custom key entry configs in addition to (or
+       // replacing) defaults.
+       for (int i = 0; i < 2; i++) {
+               char* key_default;
+
+               key_default = "Up";
+               char* key_up = (i == 0) ? "Up" : config_get(config, "key_up", 
key_default);
+               key_default = "Down";
+               char* key_down = (i == 0) ? key_default : config_get(config, 
"key_down", key_default);
+               key_default = "Left";
+               char* key_left = (i == 0) ? key_default : config_get(config, 
"key_left", key_default);
+               key_default = "Right";
+               char* key_right = (i == 0) ? key_default : config_get(config, 
"key_right", key_default);
+               key_default = "Tab";
+               char* key_forward = (i == 0) ? key_default : config_get(config, 
"key_forward", key_default);
+               key_default = "Shift-ISO_Left_Tab";
+               char* key_backward = (i == 0) ? key_default : 
config_get(config, "key_backward", key_default);
+               key_default = "Return";
+               char* key_submit = (i == 0) ? key_default : config_get(config, 
"key_submit", key_default);
+               key_default = "Escape";
+               char* key_exit = (i == 0) ? key_default : config_get(config, 
"key_exit", key_default);
+               key_default = "Page_Up";
+               char* key_pgup = (i == 0) ? key_default : config_get(config, 
"key_pgup", key_default);
+               key_default = "Page_Down";
+               char* key_pgdn = (i == 0) ? key_default : config_get(config, 
"key_pgdn", key_default);
+               key_default = "";
+               char* key_expand = (i == 0) ? key_default: config_get(config, 
"key_expand", key_default);
+               key_default = "";
+               char* key_hide_search = (i == 0) ? key_default: 
config_get(config, "key_hide_search", key_default);
+               key_default = "Ctrl-c";
+               char* key_copy = (i == 0) ? key_default : config_get(config, 
"key_copy", key_default);
+
+               char* keys_custom[CUSTOM_KEY_NUMBER];
+               key_default = "";
+               for (uint8_t kc_index = 0; kc_index < (sizeof(keys_custom) / 
sizeof(char*)); kc_index++) {
+                       char config_entry[15];
+                       sprintf(config_entry, "key_custom_%d", kc_index);
+                       keys_custom[kc_index] = (i == 0) ? key_default : 
config_get(config, config_entry, key_default);
+               }
+
+               add_key_entry(key_up, move_up);
+               add_key_entry(key_down, move_down);
+               add_key_entry(key_left, move_left);
+               add_key_entry(key_right, move_right);
+               add_key_entry(key_forward, move_forward);
+               add_key_entry(key_backward, move_backward);
+               add_key_entry(key_submit, NULL); //submit is a special case, 
when a NULL action is encountered submit is used instead
+               add_key_entry(key_exit, do_exit);
+               add_key_entry(key_pgup, move_pgup);
+               add_key_entry(key_pgdn, move_pgdn);
+               add_key_entry(key_expand, do_expand);
+               add_key_entry(key_hide_search, do_hide_search);
+               add_key_entry(key_copy, do_copy);
+
+               #define CUSTOM_KEY_FUNC(index) do_custom_key_##index
+
+               add_key_entry(keys_custom[0], CUSTOM_KEY_FUNC(0));
+               add_key_entry(keys_custom[1], CUSTOM_KEY_FUNC(1));
+               add_key_entry(keys_custom[2], CUSTOM_KEY_FUNC(2));
+               add_key_entry(keys_custom[3], CUSTOM_KEY_FUNC(3));
+               add_key_entry(keys_custom[4], CUSTOM_KEY_FUNC(4));
+               add_key_entry(keys_custom[5], CUSTOM_KEY_FUNC(5));
+               add_key_entry(keys_custom[6], CUSTOM_KEY_FUNC(6));
+               add_key_entry(keys_custom[7], CUSTOM_KEY_FUNC(7));
+               add_key_entry(keys_custom[8], CUSTOM_KEY_FUNC(8));
+               add_key_entry(keys_custom[9], CUSTOM_KEY_FUNC(9));
+               add_key_entry(keys_custom[10], CUSTOM_KEY_FUNC(10));
+               add_key_entry(keys_custom[11], CUSTOM_KEY_FUNC(11));
+               add_key_entry(keys_custom[12], CUSTOM_KEY_FUNC(12));
+               add_key_entry(keys_custom[13], CUSTOM_KEY_FUNC(13));
+               add_key_entry(keys_custom[14], CUSTOM_KEY_FUNC(14));
+               add_key_entry(keys_custom[15], CUSTOM_KEY_FUNC(15));
+               add_key_entry(keys_custom[16], CUSTOM_KEY_FUNC(16));
+               add_key_entry(keys_custom[17], CUSTOM_KEY_FUNC(17));
+               add_key_entry(keys_custom[18], CUSTOM_KEY_FUNC(18));
+               add_key_entry(keys_custom[19], CUSTOM_KEY_FUNC(19));
+       }
 
        modes = map_init_void();
 
@@ -1824,8 +2052,7 @@
                static char* geo_str[2];
                geo_str[0] = width_str;
                geo_str[1] = height_str;
-               gdk_threads_add_timeout(50, do_percent_size, geo_str);
-               do_percent_size(geo_str);
+               gdk_threads_add_timeout(25, do_percent_size_first, geo_str);
        }
 
        wl_list_init(&mode_list);
@@ -1836,4 +2063,6 @@
 
        gtk_window_set_title(GTK_WINDOW(window), prompt);
        gtk_widget_show_all(window);
+
+       on_exit(on_exit_set_custom_key_return_code, NULL);
 }

Reply via email to