Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package wmenu for openSUSE:Factory checked 
in at 2025-10-14 18:07:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/wmenu (Old)
 and      /work/SRC/openSUSE:Factory/.wmenu.new.18484 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "wmenu"

Tue Oct 14 18:07:53 2025 rev:6 rq:1311155 version:0.2.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/wmenu/wmenu.changes      2024-09-19 
21:17:27.342752108 +0200
+++ /work/SRC/openSUSE:Factory/.wmenu.new.18484/wmenu.changes   2025-10-14 
18:09:33.361925001 +0200
@@ -1,0 +2,7 @@
+Mon Oct 13 14:19:44 UTC 2025 - llyyr <[email protected]>
+
+- Update to version 0.2.0:
+  * Bug fix for rendering on fractional scaling factors
+  * Optimizations
+
+-------------------------------------------------------------------

Old:
----
  0.1.9.tar.gz

New:
----
  0.2.0.tar.gz

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

Other differences:
------------------
++++++ wmenu.spec ++++++
--- /var/tmp/diff_new_pack.n3T5MU/_old  2025-10-14 18:09:34.641979087 +0200
+++ /var/tmp/diff_new_pack.n3T5MU/_new  2025-10-14 18:09:34.645979256 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package wmenu
 #
-# Copyright (c) 2024 SUSE LLC
+# Copyright (c) 2025 SUSE LLC and contributors
 #
 # 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:           wmenu
-Version:        0.1.9
+Version:        0.2.0
 Release:        0
 Summary:        A dynamic menu for Sway and wlroots-based Wayland compositors
 License:        MIT

++++++ 0.1.9.tar.gz -> 0.2.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wmenu/README.md new/wmenu/README.md
--- old/wmenu/README.md 2024-06-10 02:33:37.000000000 +0200
+++ new/wmenu/README.md 2025-04-29 21:23:10.000000000 +0200
@@ -15,7 +15,7 @@
 - scdoc (optional)
 
 ```
-$ meson build
+$ meson setup build
 $ ninja -C build
 # ninja -C build install
 ```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wmenu/menu.c new/wmenu/menu.c
--- old/wmenu/menu.c    2024-06-10 02:33:37.000000000 +0200
+++ new/wmenu/menu.c    2025-04-29 21:23:10.000000000 +0200
@@ -1,4 +1,5 @@
 #define _POSIX_C_SOURCE 200809L
+#include <assert.h>
 #include <ctype.h>
 #include <poll.h>
 #include <stdbool.h>
@@ -33,6 +34,8 @@
        menu->selectionbg = 0x005577ff;
        menu->selectionfg = 0xeeeeeeff;
        menu->callback = callback;
+       menu->test_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 
1);
+       menu->test_cairo = cairo_create(menu->test_surface);
        return menu;
 }
 
@@ -45,24 +48,20 @@
        }
 }
 
-static void free_item(struct item *item) {
-       free(item->text);
-       free(item);
-}
-
 static void free_items(struct menu *menu) {
-       struct item *next = menu->items;
-       while (next) {
-               struct item *item = next;
-               next = item->next;
-               free_item(item);
+       for (size_t i = 0; i < menu->item_count; i++) {
+               struct item *item = &menu->items[i];
+               free(item->text);
        }
+       free(menu->items);
 }
 
 // Destroys the menu, freeing memory associated with it.
 void menu_destroy(struct menu *menu) {
        free_pages(menu);
        free_items(menu);
+       cairo_destroy(menu->test_cairo);
+       cairo_surface_destroy(menu->test_surface);
        free(menu);
 }
 
@@ -167,34 +166,44 @@
 }
 
 // Add an item to the menu.
-void menu_add_item(struct menu *menu, char *text, bool sort) {
-       struct item *new = calloc(1, sizeof(struct item));
-       if (!new) {
-               return;
+void menu_add_item(struct menu *menu, char *text) {
+       if ((menu->item_count & (menu->item_count - 1)) == 0) {
+               size_t alloc_size = menu->item_count ? 2 * menu->item_count : 1;
+               void *new_array = realloc(menu->items, sizeof(struct item) * 
alloc_size);
+               if (!new_array) {
+                       fprintf(stderr, "could not realloc %zu bytes", 
sizeof(struct item) * alloc_size);
+                       exit(EXIT_FAILURE);
+               }
+               menu->items = new_array;
        }
+
+       struct item *new = &menu->items[menu->item_count];
        new->text = text;
 
-       if (sort) {
-               for (struct item **item = &menu->items; *item; item = 
&(*item)->next) {
-                       int result = strcmp(new->text, (*item)->text);
-                       if (result == 0) {
-                               free_item(new);
-                               return;
-                       }
-                       if (result < 0) {
-                               new->next = *item;
-                               *item = new;
-                               return;
-                       }
-               }
-       }
+       menu->item_count++;
+}
 
-       if (menu->lastitem) {
-               menu->lastitem->next = new;
-       } else {
-               menu->items = new;
+static int compare_items(const void *a, const void *b) {
+       const struct item *item_a = a;
+       const struct item *item_b = b;
+       return strcmp(item_a->text, item_b->text);
+}
+
+void menu_sort_and_deduplicate(struct menu *menu) {
+       size_t j = 1;
+       size_t i;
+
+       qsort(menu->items, menu->item_count, sizeof(*menu->items), 
compare_items);
+
+       for (i = 1; i < menu->item_count; i++) {
+               if (strcmp(menu->items[i].text, menu->items[j - 1].text) == 0) {
+                       free(menu->items[i].text);
+               } else {
+                       menu->items[j] = menu->items[i];
+                       j++;
+               }
        }
-       menu->lastitem = new;
+       menu->item_count = j;
 }
 
 static void append_page(struct page *page, struct page **first, struct page 
**last) {
@@ -291,6 +300,7 @@
        char buf[sizeof menu->input], *tok;
        char **tokv = NULL;
        int i, tokc = 0;
+       size_t k;
        size_t tok_len;
        menu->matches = NULL;
        menu->matches_end = NULL;
@@ -314,8 +324,8 @@
        }
        tok_len = tokc ? strlen(tokv[0]) : 0;
 
-       struct item *item;
-       for (item = menu->items; item; item = item->next) {
+       for (k = 0; k < menu->item_count; k++) {
+               struct item *item = &menu->items[k];
                for (i = 0; i < tokc; i++) {
                        if (!fstrstr(menu, item->text, tokv[i])) {
                                /* token does not match */
@@ -366,9 +376,13 @@
        }
 }
 
+// Marks the menu as needing to be rendered again.
+void menu_invalidate(struct menu *menu) {
+       menu->rendered = false;
+}
+
 // Render menu items.
 void menu_render_items(struct menu *menu) {
-       render_menu(menu);
        calc_widths(menu);
        match_items(menu);
        render_menu(menu);
@@ -489,13 +503,13 @@
                        // Delete right
                        menu->input[menu->cursor] = '\0';
                        match_items(menu);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                        return;
                case XKB_KEY_u:
                        // Delete left
                        insert(menu, NULL, 0 - menu->cursor);
                        match_items(menu);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                        return;
                case XKB_KEY_w:
                        // Delete word
@@ -506,7 +520,7 @@
                                insert(menu, NULL, nextrune(menu, -1) - 
menu->cursor);
                        }
                        match_items(menu);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                        return;
                case XKB_KEY_Y:
                        // Paste clipboard
@@ -514,17 +528,17 @@
                                return;
                        }
                        match_items(menu);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                        return;
                case XKB_KEY_Left:
                case XKB_KEY_KP_Left:
                        movewordedge(menu, -1);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                        return;
                case XKB_KEY_Right:
                case XKB_KEY_KP_Right:
                        movewordedge(menu, +1);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                        return;
 
                case XKB_KEY_Return:
@@ -538,11 +552,11 @@
                switch (sym) {
                case XKB_KEY_b:
                        movewordedge(menu, -1);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                        return;
                case XKB_KEY_f:
                        movewordedge(menu, +1);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                        return;
                case XKB_KEY_g:
                        sym = XKB_KEY_Home;
@@ -584,10 +598,10 @@
        case XKB_KEY_KP_Up:
                if (menu->sel && menu->sel->prev_match) {
                        menu->sel = menu->sel->prev_match;
-                       render_menu(menu);
+                       menu_invalidate(menu);
                } else if (menu->cursor > 0) {
                        menu->cursor = nextrune(menu, -1);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                }
                break;
        case XKB_KEY_Right:
@@ -596,51 +610,51 @@
        case XKB_KEY_KP_Down:
                if (menu->cursor < len) {
                        menu->cursor = nextrune(menu, +1);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                } else if (menu->sel && menu->sel->next_match) {
                        menu->sel = menu->sel->next_match;
-                       render_menu(menu);
+                       menu_invalidate(menu);
                }
                break;
        case XKB_KEY_Prior:
        case XKB_KEY_KP_Prior:
                if (menu->sel && menu->sel->page->prev) {
                        menu->sel = menu->sel->page->prev->first;
-                       render_menu(menu);
+                       menu_invalidate(menu);
                }
                break;
        case XKB_KEY_Next:
        case XKB_KEY_KP_Next:
                if (menu->sel && menu->sel->page->next) {
                        menu->sel = menu->sel->page->next->first;
-                       render_menu(menu);
+                       menu_invalidate(menu);
                }
                break;
        case XKB_KEY_Home:
        case XKB_KEY_KP_Home:
                if (menu->sel == menu->matches) {
                        menu->cursor = 0;
-                       render_menu(menu);
+                       menu_invalidate(menu);
                } else {
                        menu->sel = menu->matches;
-                       render_menu(menu);
+                       menu_invalidate(menu);
                }
                break;
        case XKB_KEY_End:
        case XKB_KEY_KP_End:
                if (menu->cursor < len) {
                        menu->cursor = len;
-                       render_menu(menu);
+                       menu_invalidate(menu);
                } else {
                        menu->sel = menu->matches_end;
-                       render_menu(menu);
+                       menu_invalidate(menu);
                }
                break;
        case XKB_KEY_BackSpace:
                if (menu->cursor > 0) {
                        insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
                        match_items(menu);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                }
                break;
        case XKB_KEY_Delete:
@@ -651,7 +665,7 @@
                menu->cursor = nextrune(menu, +1);
                insert(menu, NULL, nextrune(menu, -1) - menu->cursor);
                match_items(menu);
-               render_menu(menu);
+               menu_invalidate(menu);
                break;
        case XKB_KEY_Tab:
                if (!menu->sel) {
@@ -661,7 +675,7 @@
                memcpy(menu->input, menu->sel->text, menu->cursor);
                menu->input[menu->cursor] = '\0';
                match_items(menu);
-               render_menu(menu);
+               menu_invalidate(menu);
                break;
        case XKB_KEY_Escape:
                menu->exit = true;
@@ -671,7 +685,7 @@
                if (xkb_keysym_to_utf8(sym, buf, 8)) {
                        insert(menu, buf, strnlen(buf, 8));
                        match_items(menu);
-                       render_menu(menu);
+                       menu_invalidate(menu);
                }
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wmenu/menu.h new/wmenu/menu.h
--- old/wmenu/menu.h    2024-06-10 02:33:37.000000000 +0200
+++ new/wmenu/menu.h    2025-04-29 21:23:10.000000000 +0200
@@ -1,6 +1,7 @@
 #ifndef WMENU_MENU_H
 #define WMENU_MENU_H
 
+#include <cairo/cairo.h>
 #include <stdbool.h>
 #include <sys/types.h>
 #include <xkbcommon/xkbcommon.h>
@@ -13,7 +14,6 @@
 struct item {
        char *text;
        int width;
-       struct item *next;       // traverses all items
        struct item *prev_match; // previous matching item
        struct item *next_match; // next matching item
        struct page *page;       // the page holding this item
@@ -52,6 +52,10 @@
 
        struct wl_context *context;
 
+       // 1x1 surface used estimate text sizes with pango
+       cairo_surface_t *test_surface;
+       cairo_t *test_cairo;
+
        int width;
        int height;
        int line_height;
@@ -60,12 +64,13 @@
        int promptw;
        int left_arrow;
        int right_arrow;
+       bool rendered;
 
        char input[BUFSIZ];
        size_t cursor;
 
-       struct item *items;       // list of all items
-       struct item *lastitem;    // last item in the list
+       struct item *items;       // array of all items
+       size_t item_count;
        struct item *matches;     // list of matching items
        struct item *matches_end; // last matching item
        struct item *sel;         // selected item
@@ -79,7 +84,9 @@
 struct menu *menu_create(menu_callback callback);
 void menu_destroy(struct menu *menu);
 void menu_getopts(struct menu *menu, int argc, char *argv[]);
-void menu_add_item(struct menu *menu, char *text, bool sort);
+void menu_add_item(struct menu *menu, char *text);
+void menu_sort_and_deduplicate(struct menu *menu);
+void menu_invalidate(struct menu *menu);
 void menu_render_items(struct menu *menu);
 void menu_paste(struct menu *menu, const char *text, ssize_t len);
 void menu_keypress(struct menu *menu, enum wl_keyboard_key_state key_state,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wmenu/meson.build new/wmenu/meson.build
--- old/wmenu/meson.build       2024-06-10 02:33:37.000000000 +0200
+++ new/wmenu/meson.build       2025-04-29 21:23:10.000000000 +0200
@@ -1,7 +1,7 @@
 project(
        'wmenu',
        'c',
-       version: '0.1.9',
+       version: '0.2.0',
        license: 'MIT',
        default_options: [
                'c_std=c11',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wmenu/render.c new/wmenu/render.c
--- old/wmenu/render.c  2024-06-10 02:33:37.000000000 +0200
+++ new/wmenu/render.c  2025-04-29 21:23:10.000000000 +0200
@@ -13,8 +13,13 @@
 // Calculate text widths.
 void calc_widths(struct menu *menu) {
        struct wl_context *context = menu->context;
-       struct pool_buffer *current = context_get_current_buffer(context);
-       cairo_t *cairo = current->cairo;
+       int scale = context_get_scale(context);
+       cairo_surface_set_device_scale(menu->test_surface, scale, scale);
+       cairo_set_antialias(menu->test_cairo, CAIRO_ANTIALIAS_BEST);
+       cairo_font_options_t *fo = cairo_font_options_create();
+       cairo_set_font_options(menu->test_cairo, fo);
+       cairo_font_options_destroy(fo);
+       cairo_t *cairo = menu->test_cairo;
 
        // Calculate prompt width
        if (menu->prompt) {
@@ -28,7 +33,8 @@
        menu->right_arrow = text_width(cairo, menu->font, ">") + 2 * 
menu->padding;
 
        // Calculate item widths and input area width
-       for (struct item *item = menu->items; item; item = item->next) {
+       for (size_t i = 0; i < menu->item_count; i++) {
+               struct item *item = &menu->items[i];
                item->width = text_width(cairo, menu->font, item->text);
                if (item->width > menu->inputw) {
                        menu->inputw = item->width;
@@ -183,33 +189,18 @@
 void render_menu(struct menu *menu) {
        struct wl_context *context = menu->context;
 
-       cairo_surface_t *recorder = cairo_recording_surface_create(
-                       CAIRO_CONTENT_COLOR_ALPHA, NULL);
-       cairo_t *cairo = cairo_create(recorder);
-       cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
-       cairo_font_options_t *fo = cairo_font_options_create();
-       cairo_set_font_options(cairo, fo);
-       cairo_font_options_destroy(fo);
-       cairo_save(cairo);
-       cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
-       cairo_paint(cairo);
-       cairo_restore(cairo);
-
-       render_to_cairo(menu, cairo);
-
        int scale = context_get_scale(context);
        struct pool_buffer *buffer = context_get_next_buffer(context, scale);
        if (!buffer) {
-               goto cleanup;
+               return;
        }
 
        cairo_t *shm = buffer->cairo;
-       cairo_save(shm);
-       cairo_set_operator(shm, CAIRO_OPERATOR_CLEAR);
-       cairo_paint(shm);
-       cairo_restore(shm);
-       cairo_set_source_surface(shm, recorder, 0, 0);
-       cairo_paint(shm);
+       cairo_set_antialias(shm, CAIRO_ANTIALIAS_BEST);
+       cairo_font_options_t *fo = cairo_font_options_create();
+       cairo_set_font_options(shm, fo);
+       cairo_font_options_destroy(fo);
+       render_to_cairo(menu, shm);
 
        struct wl_surface *surface = context_get_surface(context);
        wl_surface_set_buffer_scale(surface, scale);
@@ -217,7 +208,5 @@
        wl_surface_damage(surface, 0, 0, menu->width, menu->height);
        wl_surface_commit(surface);
 
-cleanup:
-       cairo_destroy(cairo);
-       cairo_surface_destroy(recorder);
+       menu->rendered = true;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wmenu/wayland.c new/wmenu/wayland.c
--- old/wmenu/wayland.c 2024-06-10 02:33:37.000000000 +0200
+++ new/wmenu/wayland.c 2025-04-29 21:23:10.000000000 +0200
@@ -3,7 +3,6 @@
 #include <errno.h>
 #include <poll.h>
 #include <stdbool.h>
-#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -18,6 +17,7 @@
 
 #include "menu.h"
 #include "pool-buffer.h"
+#include "render.h"
 #include "wayland.h"
 #include "xdg-activation-v1-client-protocol.h"
 #include "wlr-layer-shell-unstable-v1-client-protocol.h"
@@ -208,6 +208,7 @@
 static void surface_enter(void *data, struct wl_surface *surface, struct 
wl_output *wl_output) {
        struct wl_context *context = data;
        context->output = wl_output_get_user_data(wl_output);
+       menu_invalidate(context->menu);
 }
 
 static const struct wl_surface_listener surface_listener = {
@@ -439,7 +440,7 @@
                context->layer_shell,
                context->surface,
                context->output ? context->output->output : NULL,
-               ZWLR_LAYER_SHELL_V1_LAYER_TOP,
+               ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY,
                "menu"
        );
        assert(layer_surface != NULL);
@@ -492,6 +493,11 @@
                if (fds[1].revents & POLLIN) {
                        keyboard_repeat(context->keyboard);
                }
+
+               // Render the menu if necessary
+               if (!menu->rendered) {
+                       render_menu(menu);
+               }
        }
 
        context_destroy(context);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wmenu/wmenu-run.c new/wmenu/wmenu-run.c
--- old/wmenu/wmenu-run.c       2024-06-10 02:33:37.000000000 +0200
+++ new/wmenu/wmenu-run.c       2025-04-29 21:23:10.000000000 +0200
@@ -20,10 +20,11 @@
                        if (ent->d_name[0] == '.') {
                                continue;
                        }
-                       menu_add_item(menu, strdup(ent->d_name), true);
+                       menu_add_item(menu, strdup(ent->d_name));
                }
                closedir(dir);
        }
+       menu_sort_and_deduplicate(menu);
        free(path);
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wmenu/wmenu.c new/wmenu/wmenu.c
--- old/wmenu/wmenu.c   2024-06-10 02:33:37.000000000 +0200
+++ new/wmenu/wmenu.c   2025-04-29 21:23:10.000000000 +0200
@@ -13,7 +13,7 @@
                if (p) {
                        *p = '\0';
                }
-               menu_add_item(menu, strdup(buf), false);
+               menu_add_item(menu, strdup(buf));
        }
 }
 

Reply via email to