Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package fcitx5-gtk for openSUSE:Factory 
checked in at 2026-10-22 15:49:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/fcitx5-gtk (Old)
 and      /work/SRC/openSUSE:Factory/.fcitx5-gtk.new.2252680 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "fcitx5-gtk"

Thu Oct 22 15:49:05 2026 rev:16 rq:1386554 version:5.1.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/fcitx5-gtk/fcitx5-gtk.changes    2026-02-09 
11:43:46.978814697 +0100
+++ /work/SRC/openSUSE:Factory/.fcitx5-gtk.new.2252680/fcitx5-gtk.changes       
2026-10-22 15:50:13.508924215 +0200
@@ -1,0 +2,8 @@
+Sat Oct 17 15:55:35 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to 5.1.7:
+  * Update cursor position when a key is pressed
+  * Replace gdk_popup with gtk_popover
+  * Fix parent window signal connection cleanup on destruction
+
+-------------------------------------------------------------------

Old:
----
  fcitx5-gtk-5.1.5.tar.zst

New:
----
  fcitx5-gtk-5.1.7.tar.zst

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

Other differences:
------------------
++++++ fcitx5-gtk.spec ++++++
--- /var/tmp/diff_new_pack.XCQh1B/_old  2026-10-22 15:50:14.311957877 +0200
+++ /var/tmp/diff_new_pack.XCQh1B/_new  2026-10-22 15:50:14.315958045 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           fcitx5-gtk
-Version:        5.1.5
+Version:        5.1.7
 Release:        0
 Summary:        Gtk im module for fcitx5 and glib based dbus client library
 License:        LGPL-2.1-or-later

++++++ fcitx5-gtk-5.1.5.tar.zst -> fcitx5-gtk-5.1.7.tar.zst ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fcitx5-gtk-5.1.5/CMakeLists.txt 
new/fcitx5-gtk-5.1.7/CMakeLists.txt
--- old/fcitx5-gtk-5.1.5/CMakeLists.txt 2025-12-22 07:18:11.000000000 +0100
+++ new/fcitx5-gtk-5.1.7/CMakeLists.txt 2026-06-20 06:19:08.000000000 +0200
@@ -1,5 +1,5 @@
 cmake_minimum_required(VERSION 3.6)
-project(fcitx5-gtk VERSION 5.1.5)
+project(fcitx5-gtk VERSION 5.1.7)
 
 find_package(ECM REQUIRED 1.0.0)
 set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake" 
${CMAKE_MODULE_PATH})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fcitx5-gtk-5.1.5/README.md 
new/fcitx5-gtk-5.1.7/README.md
--- old/fcitx5-gtk-5.1.5/README.md      2025-12-22 07:18:11.000000000 +0100
+++ new/fcitx5-gtk-5.1.7/README.md      2026-06-20 06:19:08.000000000 +0200
@@ -1,5 +1,5 @@
 Gtk im module for fcitx5 and glib based dbus client library
 ==========================================
-[![Jenkins Build 
Status](https://img.shields.io/jenkins/s/https/jenkins.fcitx-im.org/job/fcitx5-gtk.svg)](https://jenkins.fcitx-im.org/job/fcitx5-gtk/)
+[![Jenkins 
Build](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins.fcitx-im.org%2Fjob%2Ffcitx5-gtk%2F)](https://jenkins.fcitx-im.org/job/fcitx5-gtk/)
 
 [![Coverity Scan 
Status](https://img.shields.io/coverity/scan/12702.svg)](https://scan.coverity.com/projects/fcitx-fcitx5-gtk)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fcitx5-gtk-5.1.5/gtk3/fcitximcontext.cpp 
new/fcitx5-gtk-5.1.7/gtk3/fcitximcontext.cpp
--- old/fcitx5-gtk-5.1.5/gtk3/fcitximcontext.cpp        2025-12-22 
07:18:11.000000000 +0100
+++ new/fcitx5-gtk-5.1.7/gtk3/fcitximcontext.cpp        2026-06-20 
06:19:08.000000000 +0200
@@ -1624,6 +1624,12 @@
             break;
         }
 
+        /* set_cursor_location_internal() will get origin from X server,
+         * it blocks UI. So delay it to idle callback. */
+        gdk_threads_add_idle_full(
+            G_PRIORITY_DEFAULT_IDLE, 
(GSourceFunc)_set_cursor_location_internal,
+            g_object_ref(fcitxcontext), (GDestroyNotify)g_object_unref);
+
         _request_surrounding_text(&fcitxcontext);
         if (G_UNLIKELY(!fcitxcontext))
             return FALSE;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fcitx5-gtk-5.1.5/gtk4/fcitximcontext.cpp 
new/fcitx5-gtk-5.1.7/gtk4/fcitximcontext.cpp
--- old/fcitx5-gtk-5.1.5/gtk4/fcitximcontext.cpp        2025-12-22 
07:18:11.000000000 +0100
+++ new/fcitx5-gtk-5.1.7/gtk4/fcitximcontext.cpp        2026-06-20 
06:19:08.000000000 +0200
@@ -407,8 +407,6 @@
         return;
     }
 
-    delete fcitxcontext->candidate_window;
-    fcitxcontext->candidate_window = nullptr;
     g_clear_object(&fcitxcontext->client_widget);
     if (!client_widget)
         return;
@@ -417,8 +415,10 @@
 
     _fcitx_im_context_set_capability(fcitxcontext, FALSE);
 
-    fcitxcontext->candidate_window =
-        new Gtk4InputWindow(_uiconfig, fcitxcontext->client);
+    if (!fcitxcontext->candidate_window) {
+        fcitxcontext->candidate_window =
+            new Gtk4InputWindow(_uiconfig, fcitxcontext->client);
+    }
     fcitxcontext->candidate_window->setParent(fcitxcontext->client_widget);
     fcitxcontext->candidate_window->setCursorRect(fcitxcontext->area);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fcitx5-gtk-5.1.5/gtk4/gtk4inputwindow.cpp 
new/fcitx5-gtk-5.1.7/gtk4/gtk4inputwindow.cpp
--- old/fcitx5-gtk-5.1.5/gtk4/gtk4inputwindow.cpp       2025-12-22 
07:18:11.000000000 +0100
+++ new/fcitx5-gtk-5.1.7/gtk4/gtk4inputwindow.cpp       2026-06-20 
06:19:08.000000000 +0200
@@ -5,24 +5,239 @@
  *
  */
 #include "gtk4inputwindow.h"
+#include "inputwindow.h"
+#include <cairo.h>
+#include <gdk/gdk.h>
+#include <glib-object.h>
+#include <glib.h>
+#include <graphene.h>
+#include <gsk/gsk.h>
 #include <gtk/gtk.h>
-#include <gtk3/fcitxtheme.h>
+#include <pango/pangocairo.h>
+#include <tuple>
+
+G_BEGIN_DECLS
+
+#define FCITX_TYPE_CLIENT_SIDE_POPUP (fcitx_client_side_popup_get_type())
+G_DECLARE_FINAL_TYPE(FcitxClientSidePopup, fcitx_client_side_popup, FCITX,
+                     CLIENT_SIDE_POPUP, GtkPopover)
+
+GtkWidget *fcitx_client_side_popup_new(void);
+
+G_END_DECLS
+
+struct _FcitxClientSidePopup {
+    GtkPopover parent_instance;
+    // You can add custom state fields here (e.g., colors, values, etc.)
+    fcitx::gtk::Gtk4InputWindow
+        *inputWindow; // Back-reference to the input window for interaction
+};
+
+G_DEFINE_TYPE(FcitxClientSidePopup, fcitx_client_side_popup, GTK_TYPE_POPOVER)
+
+static void fcitx_client_side_popup_snapshot(GtkWidget *widget,
+                                             GtkSnapshot *snapshot) {
+    int width = gtk_widget_get_width(widget);
+    int height = gtk_widget_get_height(widget);
+
+    if (width <= 0 || height <= 0) {
+        return;
+    }
+
+    // Create a bounding box for the Cairo context
+    graphene_rect_t bounds;
+    graphene_rect_init(&bounds, 0, 0, width, height);
+
+    // Request a Cairo context from the GTK snapshot layer
+    cairo_t *cr = gtk_snapshot_append_cairo(snapshot, &bounds);
+
+    if (auto *window = FCITX_CLIENT_SIDE_POPUP(widget)->inputWindow) {
+        window->draw(cr);
+    }
+
+    // Clean up the cairo context
+    cairo_destroy(cr);
+}
+
+static void fcitx_client_side_popup_set_parent(FcitxClientSidePopup *self,
+                                               GtkWidget *parent) {
+    if (parent == gtk_widget_get_parent(GTK_WIDGET(self))) {
+        return;
+    }
+    if (auto *oldParent = gtk_widget_get_parent(GTK_WIDGET(self))) {
+        g_signal_handlers_disconnect_by_data(oldParent, self);
+        gtk_widget_unparent(GTK_WIDGET(self));
+    }
+    if (parent) {
+        gtk_widget_set_parent(GTK_WIDGET(self), parent);
+        g_signal_connect(parent, "destroy",
+                         G_CALLBACK(+[](GtkWidget *widget, gpointer data) {
+                             if (gtk_widget_get_parent(GTK_WIDGET(data)) ==
+                                 widget) {
+                                 gtk_widget_unparent(GTK_WIDGET(data));
+                             }
+                         }),
+                         self);
+    } else {
+        gtk_popover_popdown(GTK_POPOVER(self));
+    }
+}
+
+static void fcitx_client_side_popup_init(FcitxClientSidePopup *self) {
+    self->inputWindow = nullptr; // Initialize back-reference
+    gtk_widget_add_css_class(GTK_WIDGET(self), "fcitx-popup");
+    gtk_widget_set_halign(GTK_WIDGET(self), GTK_ALIGN_START);
+    gtk_popover_set_position(GTK_POPOVER(self), GTK_POS_BOTTOM);
+    gtk_popover_set_autohide(GTK_POPOVER(self), false);
+    gtk_popover_set_has_arrow(GTK_POPOVER(self), false);
+    gtk_popover_set_cascade_popdown(GTK_POPOVER(self), false);
+    gtk_popover_set_mnemonics_visible(GTK_POPOVER(self), false);
+
+    auto *motionController = gtk_event_controller_motion_new();
+    g_signal_connect(motionController, "motion",
+                     G_CALLBACK(+[](GtkEventControllerMotion * /*controller*/,
+                                    gdouble x, gdouble y, gpointer user_data) {
+                         auto *self =
+                             static_cast<FcitxClientSidePopup *>(user_data);
+                         if (self->inputWindow) {
+                             self->inputWindow->motion(x, y);
+                         }
+                     }),
+                     self);
+    g_signal_connect(motionController, "leave",
+                     G_CALLBACK(+[](GtkEventControllerMotion * /*controller*/,
+                                    gpointer user_data) {
+                         auto *self =
+                             static_cast<FcitxClientSidePopup *>(user_data);
+                         if (self->inputWindow) {
+                             self->inputWindow->leave();
+                         }
+                     }),
+                     self);
+    gtk_widget_add_controller(GTK_WIDGET(self),
+                              GTK_EVENT_CONTROLLER(motionController));
+
+    auto *scrollController =
+        gtk_event_controller_scroll_new(GTK_EVENT_CONTROLLER_SCROLL_VERTICAL);
+    g_signal_connect(
+        scrollController, "scroll",
+        G_CALLBACK(+[](GtkEventControllerScroll * /*controller*/, gdouble x,
+                       gdouble y, gpointer user_data) -> gboolean {
+            auto *self = static_cast<FcitxClientSidePopup *>(user_data);
+            if (self->inputWindow) {
+                return self->inputWindow->scroll(x, y);
+            }
+            return false;
+        }),
+        self);
+    gtk_widget_add_controller(GTK_WIDGET(self),
+                              GTK_EVENT_CONTROLLER(scrollController));
+
+    auto *clickController = gtk_gesture_click_new();
+    g_signal_connect(
+        clickController, "released",
+        G_CALLBACK(+[](GtkGestureClick *controller, gint /*n_press*/, gdouble 
x,
+                       gdouble y, gpointer user_data) {
+            auto *self = static_cast<FcitxClientSidePopup *>(user_data);
+            if (self->inputWindow) {
+                guint button = gtk_gesture_single_get_current_button(
+                    GTK_GESTURE_SINGLE(controller));
+                if (button == GDK_BUTTON_PRIMARY) {
+                    self->inputWindow->click(x, y);
+                }
+            }
+        }),
+        self);
+    gtk_widget_add_controller(GTK_WIDGET(self),
+                              GTK_EVENT_CONTROLLER(clickController));
+
+    g_signal_connect(GTK_WIDGET(self), "notify::visible",
+                     G_CALLBACK(+[](GtkWidget *self, GParamSpec * /*pspec*/,
+                                    gpointer /*data*/) {
+                         auto inputWindow =
+                             FCITX_CLIENT_SIDE_POPUP(self)->inputWindow;
+                         // Do not become visible if the input window is not
+                         // visible. This may happen when gtk_widget_show_all 
is
+                         // called which recursively shows all children,
+                         // including our attached popup.
+                         if (!inputWindow || !inputWindow->visible()) {
+                             gtk_widget_set_visible(self, FALSE);
+                             fcitx_client_side_popup_set_parent(
+                                 FCITX_CLIENT_SIDE_POPUP(self), nullptr);
+                         }
+                     }),
+                     nullptr);
+}
+
+static void fcitx_client_side_popup_dispose(GObject *object) {
+    fcitx_client_side_popup_set_parent(FCITX_CLIENT_SIDE_POPUP(object),
+                                       nullptr);
+    G_OBJECT_CLASS(fcitx_client_side_popup_parent_class)->dispose(object);
+}
+
+static void
+fcitx_client_side_popup_class_init(FcitxClientSidePopupClass *klass) {
+    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+
+    // Hook up our overridden functions
+    widget_class->snapshot = fcitx_client_side_popup_snapshot;
+    G_OBJECT_CLASS(klass)->dispose = fcitx_client_side_popup_dispose;
+}
+
+GtkWidget *fcitx_client_side_popup_new(void) {
+    return GTK_WIDGET(g_object_new(FCITX_TYPE_CLIENT_SIDE_POPUP, nullptr));
+}
 
 namespace fcitx::gtk {
 
+static void ensureFcitxPopupCss() {
+    static GtkCssProvider *provider = nullptr;
+    auto *display = gdk_display_get_default();
+    if (provider || !display) {
+        return;
+    }
+
+    provider = gtk_css_provider_new();
+    const char *css = R"css(
+popover.fcitx-popup contents {
+    box-shadow: none;
+    padding: 0px;
+    border-radius: 0px;
+    background-color: transparent;
+    background-clip: border-box;
+    border: none;
+}
+)css";
+    gtk_css_provider_load_from_string(provider, css);
+    gtk_style_context_add_provider_for_display(
+        display, GTK_STYLE_PROVIDER(provider),
+        GTK_STYLE_PROVIDER_PRIORITY_USER);
+}
+
 Gtk4InputWindow::Gtk4InputWindow(ClassicUIConfig *config, FcitxGClient *client)
     : InputWindow(config, client) {
     rect_.x = rect_.y = rect_.height = rect_.width = 0;
-    dummyWidget_.reset(GTK_WINDOW(gtk_window_new()));
 }
 
 Gtk4InputWindow::~Gtk4InputWindow() {
-    if (window_) {
-        g_signal_handlers_disconnect_by_data(window_.get(), this);
-        gdk_surface_destroy(window_.release());
-    }
-    // Clean up weak pointer.
     setParent(nullptr);
+
+    if (!window_) {
+        return;
+    }
+    auto *popup = FCITX_CLIENT_SIDE_POPUP(window_.get());
+    popup->inputWindow = nullptr;
+    window_.reset();
+}
+
+void Gtk4InputWindow::init() {
+    if (!window_) {
+        ensureFcitxPopupCss();
+        // We want to indefinitely keep the window alive through the lifetime 
of
+        // Gtk4InputWindow.
+        window_.reset(g_object_ref_sink(fcitx_client_side_popup_new()));
+        FCITX_CLIENT_SIDE_POPUP(window_.get())->inputWindow = this;
+    }
 }
 
 void Gtk4InputWindow::draw(cairo_t *cr) { paint(cr, width_, height_); }
@@ -38,240 +253,118 @@
     if (parent) {
         g_object_add_weak_pointer(G_OBJECT(parent),
                                   reinterpret_cast<gpointer *>(&parent_));
-        resetWindow();
     }
     parent_ = parent;
+    if (window_) {
+        fcitx_client_side_popup_set_parent(
+            FCITX_CLIENT_SIDE_POPUP(window_.get()), parent);
+    }
 }
 
 void Gtk4InputWindow::setCursorRect(GdkRectangle rect) {
     if (!parent_) {
         return;
     }
-    auto *root = gtk_widget_get_native(parent_);
-    if (!root) {
-        return;
-    }
-
-    double px, py;
-    gtk_widget_translate_coordinates(parent_, GTK_WIDGET(root), rect.x, rect.y,
-                                     &px, &py);
-    double offsetX = 0, offsetY = 0;
-
-    if (auto native = gtk_widget_get_native(GTK_WIDGET(root))) {
-        gtk_native_get_surface_transform(native, &offsetX, &offsetY);
-    }
-    rect.x = px + offsetX;
-    rect.y = py + offsetY;
-
-    // Sanitize the rect value to workaround a mutter bug:
-    // https://gitlab.gnome.org/GNOME/mutter/-/issues/2525
-    // The procedure make sure the rect is with in the parent window region.
-    const int rootWidth = gtk_widget_get_width(GTK_WIDGET(root));
-    const int rootHeight = gtk_widget_get_height(GTK_WIDGET(root));
-    if (rootWidth <= 0 || rootHeight <= 0) {
-        return;
-    }
-    rect.x = CLAMP(rect.x, 0, rootWidth - 1);
-    rect.y = CLAMP(rect.y, 0, rootHeight - 1);
-    rect.width = CLAMP(rect.width, 1, rootWidth - rect.x);
-    rect.height = CLAMP(rect.height, 1, rootHeight - rect.y);
 
     rect_ = rect;
-
-    if (window_) {
-        reposition();
-    }
+    reposition();
 }
 
 void Gtk4InputWindow::update() {
-    if (!visible() || !parent_) {
-        resetWindow();
-        return;
-    }
+    do {
+        if (!visible()) {
+            break;
+        }
 
-    syncFontOptions();
-    std::tie(width_, height_) = sizeHint();
-    if (width_ <= 0 || height_ <= 0) {
-        resetWindow();
-        return;
-    }
-    auto native = gtk_widget_get_native(parent_);
-    if (!native) {
-        return;
-    }
+        init();
+        syncFontOptions();
+        std::tie(width_, height_) = sizeHint();
+        if (width_ <= 0 || height_ <= 0) {
+            break;
+        }
 
-    auto surface = gtk_native_get_surface(native);
-    if (!surface) {
+        if (!reposition()) {
+            break;
+        }
         return;
-    }
-
+    } while (false);
     if (window_) {
-        if (surface == gdk_popup_get_parent(GDK_POPUP(window_.get()))) {
-            gdk_surface_queue_render(window_.get());
-            reposition();
-            return;
-        }
+        gtk_popover_popdown(GTK_POPOVER(window_.get()));
     }
-
-    resetWindow();
-    window_.reset(gdk_surface_new_popup(surface, false));
-    cairoCcontext_.reset(gdk_surface_create_cairo_context(window_.get()));
-
-    auto mapped = [](GdkSurface *surface, GParamSpec *, gpointer user_data) {
-        Gtk4InputWindow *that = static_cast<Gtk4InputWindow *>(user_data);
-        that->surfaceNotifyMapped(surface);
-    };
-    g_signal_connect(surface, "notify::mapped", G_CALLBACK(+mapped), this);
-
-    auto surface_render = [](GdkSurface *surface, cairo_region_t *,
-                             gpointer user_data) {
-        Gtk4InputWindow *that = static_cast<Gtk4InputWindow *>(user_data);
-        cairo_rectangle_int_t r;
-        r.x = 0;
-        r.y = 0;
-        r.width = gdk_surface_get_width(surface);
-        r.height = gdk_surface_get_height(surface);
-        auto region = cairo_region_create_rectangle(&r);
-        gdk_draw_context_begin_frame(
-            GDK_DRAW_CONTEXT(that->cairoCcontext_.get()), region);
-        cairo_region_destroy(region);
-        auto cr = gdk_cairo_context_cairo_create(that->cairoCcontext_.get());
-
-        static_cast<Gtk4InputWindow *>(user_data)->draw(cr);
-
-        cairo_destroy(cr);
-
-        gdk_draw_context_end_frame(
-            GDK_DRAW_CONTEXT(that->cairoCcontext_.get()));
-        return TRUE;
-    };
-    auto event = [](GdkSurface *, gpointer event, gpointer user_data) {
-        return static_cast<Gtk4InputWindow *>(user_data)->event(
-            static_cast<GdkEvent *>(event));
-    };
-    g_signal_connect(window_.get(), "render", G_CALLBACK(+surface_render),
-                     this);
-    g_signal_connect(window_.get(), "event", G_CALLBACK(+event), this);
-
-    surfaceNotifyMapped(surface);
 }
 
-void Gtk4InputWindow::reposition() {
-    if (!window_) {
-        return;
+bool Gtk4InputWindow::reposition() {
+    if (!window_ || !parent_ || width_ <= 0 || height_ <= 0 || !visible()) {
+        return false;
     }
 
-    auto popupLayout = gdk_popup_layout_new(&rect_, GDK_GRAVITY_SOUTH_WEST,
-                                            GDK_GRAVITY_NORTH_WEST);
-    gdk_popup_layout_set_anchor_hints(
-        popupLayout,
-        static_cast<GdkAnchorHints>(GDK_ANCHOR_SLIDE_X | GDK_ANCHOR_FLIP_Y |
-                                    GDK_ANCHOR_SLIDE_Y));
-
-    gdk_popup_layout_set_shadow_width(
-        popupLayout, config_->theme_.shadowMargin.marginLeft,
-        config_->theme_.shadowMargin.marginRight,
-        config_->theme_.shadowMargin.marginTop,
-        config_->theme_.shadowMargin.marginBottom);
-    gdk_popup_present(GDK_POPUP(window_.get()), width_, height_, popupLayout);
-    gdk_popup_layout_unref(popupLayout);
-}
+    // Check if parent is visible and mapped. If not, we should not pop up the
+    // candidate.
+    if (!gtk_widget_is_visible(parent_)) {
+        return false;
+    }
 
-void Gtk4InputWindow::surfaceNotifyMapped(GdkSurface *surface) {
-    if (surface != gdk_popup_get_parent(GDK_POPUP(window_.get()))) {
-        return;
+    auto *native = gtk_widget_get_native(parent_);
+    if (!native) {
+        return false;
     }
-    if (!window_) {
-        return;
+    auto *surface = gtk_native_get_surface(GTK_NATIVE(native));
+    if (!surface) {
+        return false;
     }
     if (!gdk_surface_get_mapped(surface)) {
-        resetWindow();
-        return;
-    } else if (visible()) {
-        reposition();
+        return false;
     }
-}
 
-void Gtk4InputWindow::resetWindow() {
-    if (!window_) {
-        return;
-    }
-    if (auto parent = gdk_popup_get_parent(GDK_POPUP(window_.get()))) {
-        g_signal_handlers_disconnect_by_data(parent, this);
-        g_signal_handlers_disconnect_by_data(window_.get(), this);
-        cairoCcontext_.reset();
-        window_.reset();
-    }
+    fcitx_client_side_popup_set_parent(FCITX_CLIENT_SIDE_POPUP(window_.get()),
+                                       parent_);
+    gtk_widget_set_size_request(window_.get(), width_, height_);
+    gtk_popover_set_pointing_to(GTK_POPOVER(window_.get()), &rect_);
+    gtk_popover_popup(GTK_POPOVER(window_.get()));
+    return true;
 }
 
 void Gtk4InputWindow::syncFontOptions() {
-    auto context = 
gtk_widget_get_pango_context(GTK_WIDGET(dummyWidget_.get()));
+    auto *context = gtk_widget_get_pango_context(window_.get());
+    if (!context) {
+        return;
+    }
     pango_cairo_context_set_font_options(
         context_.get(), pango_cairo_context_get_font_options(context));
     dpi_ = pango_cairo_context_get_resolution(context);
     pango_cairo_context_set_resolution(context_.get(), dpi_);
 }
 
-gboolean Gtk4InputWindow::event(GdkEvent *event) {
-    auto eventType = gdk_event_get_event_type(event);
-    if (eventType == GDK_MOTION_NOTIFY) {
-        double x = 0, y = 0;
-        gdk_event_get_position(event, &x, &y);
-        if (hover(x, y)) {
-            gdk_surface_queue_render(window_.get());
-        }
-    } else if (eventType == GDK_LEAVE_NOTIFY) {
-        auto oldHighlight = highlight();
-        hoverIndex_ = -1;
-        if (highlight() != oldHighlight) {
-            gdk_surface_queue_render(window_.get());
-        }
-        return true;
-    } else if (eventType == GDK_SCROLL) {
-        double vscroll_factor = 0.0;
-        double x_scroll, y_scroll;
-        // Handle discrete scrolling with a known constant delta;
-        const double delta = 1.0;
-
-        // In Gtk 4, there will be either discrete or axis event.
-        auto direction = gdk_scroll_event_get_direction(event);
-        switch (direction) {
-        case GDK_SCROLL_UP:
-            vscroll_factor = -delta;
-            break;
-        case GDK_SCROLL_DOWN:
-            vscroll_factor = delta;
-            break;
-        case GDK_SCROLL_SMOOTH:
-            gdk_scroll_event_get_deltas(event, &x_scroll, &y_scroll);
-            // Handle smooth scrolling directly
-            vscroll_factor = y_scroll;
-            break;
-        default:
-            // no scrolling
-            break;
-        }
-        if (vscroll_factor != 0) {
-            scrollDelta_ += vscroll_factor;
-            while (scrollDelta_ >= delta) {
-                scrollDelta_ -= delta;
-                next();
-            }
-            while (scrollDelta_ <= -delta) {
-                scrollDelta_ += delta;
-                prev();
-            }
-        }
-        return true;
-    } else if (eventType == GDK_BUTTON_RELEASE) {
-        guint button = gdk_button_event_get_button(event);
-        if (button == 1) {
-            double x = 0, y = 0;
-            gdk_event_get_position(event, &x, &y);
-            click(x, y);
-        }
+void Gtk4InputWindow::motion(double x, double y) {
+    if (hover(x, y)) {
+        gtk_widget_queue_draw(GTK_WIDGET(window_.get()));
+    }
+}
+
+void Gtk4InputWindow::leave() {
+    auto oldHighlight = highlight();
+    hoverIndex_ = -1;
+    if (highlight() != oldHighlight) {
+        gtk_widget_queue_draw(GTK_WIDGET(window_.get()));
+    }
+}
+
+bool Gtk4InputWindow::scroll(double /*x*/, double y) {
+    if (y == 0) {
+        return false;
+    }
+
+    scrollDelta_ += y;
+    const double delta = 1.0;
+    while (scrollDelta_ >= delta) {
+        scrollDelta_ -= delta;
+        next();
+    }
+    while (scrollDelta_ <= -delta) {
+        scrollDelta_ += delta;
+        prev();
     }
-    return false;
+    return true;
 }
 
 } // namespace fcitx::gtk
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/fcitx5-gtk-5.1.5/gtk4/gtk4inputwindow.h 
new/fcitx5-gtk-5.1.7/gtk4/gtk4inputwindow.h
--- old/fcitx5-gtk-5.1.5/gtk4/gtk4inputwindow.h 2025-12-22 07:18:11.000000000 
+0100
+++ new/fcitx5-gtk-5.1.7/gtk4/gtk4inputwindow.h 2026-06-20 06:19:08.000000000 
+0200
@@ -15,31 +15,30 @@
 class Gtk4InputWindow : public InputWindow {
 public:
     Gtk4InputWindow(ClassicUIConfig *config, FcitxGClient *client);
-
     ~Gtk4InputWindow();
 
     void setParent(GtkWidget *parent);
     void update() override;
     void setCursorRect(GdkRectangle rect);
+    void draw(cairo_t *cr);
+
+    void motion(double x, double y);
+    void leave();
+    bool scroll(double x, double y);
 
 private:
-    void draw(cairo_t *cr);
-    gboolean event(GdkEvent *event);
-    void reposition();
-    void surfaceNotifyMapped(GdkSurface *surface);
-    void resetWindow();
+    void init();
+    bool reposition();
     void syncFontOptions();
 
     bool supportAlpha = false;
     // Dummy widget to track font options.
-    UniqueCPtr<GtkWindow, gtk_window_destroy> dummyWidget_;
-    UniqueCPtr<GdkSurface, gdk_surface_destroy> window_;
-    UniqueCPtr<GdkCairoContext, g_object_unref> cairoCcontext_;
-    GtkWidget *parent_ = nullptr;
+    GObjectUniquePtr<GtkWidget> window_;
     size_t width_ = 1;
     size_t height_ = 1;
     GdkRectangle rect_;
     double scrollDelta_ = 0;
+    GtkWidget *parent_ = nullptr;
 };
 
 } // namespace fcitx::gtk

Reply via email to