From b89025f85ee172103524d9505ea7fa4e0878eaaa Mon Sep 17 00:00:00 2001 From: tangjie02 Date: Sat, 30 Jul 2022 13:54:50 +0800 Subject: [PATCH] fix(menu): fix the grab problem when popup menu on search entry or drag menu app icon. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复在搜索框弹出右键菜单后开始菜单未抓取问题 - 修复开始菜单拖拽到开始菜单后开始菜单未抓取问题 Signed-off-by: tangjie02 --- src/menu/menu-app-item.cpp | 29 +++++++++++++++++------------ src/menu/menu-app-item.h | 5 ++--- src/menu/menu-applet-window.cpp | 21 ++++++++++----------- src/menu/menu-applet-window.h | 5 ----- src/menu/menu-power-button.cpp | 12 ------------ src/menu/menu-power-button.h | 5 ----- src/menu/recent-files-list-box.cpp | 15 +++++---------- 7 files changed, 34 insertions(+), 58 deletions(-) diff --git a/src/menu/menu-app-item.cpp b/src/menu/menu-app-item.cpp index e2afab2..fba3994 100644 --- a/src/menu/menu-app-item.cpp +++ b/src/menu/menu-app-item.cpp @@ -47,12 +47,14 @@ MenuAppItem::MenuAppItem(const std::shared_ptr &app_, int _icon_size set_can_focus(true); set_tooltip_text(app_->get_locale_comment()); - context_menu.signal_deactivate().connect( - sigc::mem_fun(*this, &MenuAppItem::on_context_menu_deactivated)); - init_drag_and_drop(); } +MenuAppItem::~MenuAppItem() +{ + this->idle_drag_connection_.disconnect(); +} + const std::shared_ptr MenuAppItem::get_app() const { return app.lock(); @@ -122,16 +124,19 @@ void MenuAppItem::on_drag_data_get(const Glib::RefPtr &context void MenuAppItem::on_drag_end(const Glib::RefPtr &context) { - /* 让开始菜单窗口重新获取输入焦点 */ - Gtk::Container *toplevel = get_toplevel(); - KiranHelper::grab_input(*toplevel); -} + /* FIXME: 当拖动图标到任务栏时,无法收到drag-end信号,因为任务栏时kiran-panel的子窗口,kiran-panel是通过 + 代理的方式将拖拽信息发送给任务栏,但是任务栏拖拽完成后,这个代理并没有把完成的消息转发给源控件(开始菜单), + 因此无法收到drag-end信号,当前函数也不会被调用。这个时候窗口不再被抓取,需要手动点击左下角开始菜单按钮才能隐藏。*/ -void MenuAppItem::on_context_menu_deactivated() -{ - /* 让开始菜单窗口重新获取输入焦点 */ - auto toplevel = get_toplevel(); - KiranHelper::grab_input(*toplevel); + // 如果拖拽被取消,拖拽的ungrab操作可能在drag-end信号之后,所以这里的grab操作放入到后面的事件循环处理。 + if (this->idle_drag_connection_.empty()) + { + this->idle_drag_connection_ = Glib::signal_idle().connect([this]() -> bool { + Gtk::Container *toplevel = this->get_toplevel(); + KiranHelper::grab_input(*toplevel); + return false; + }); + } } bool MenuAppItem::on_key_press_event(GdkEventKey *key_event) diff --git a/src/menu/menu-app-item.h b/src/menu/menu-app-item.h index db7c0f3..39f3767 100644 --- a/src/menu/menu-app-item.h +++ b/src/menu/menu-app-item.h @@ -23,7 +23,7 @@ class MenuAppItem : public MenuListItemWidget { public: MenuAppItem(const std::shared_ptr &_app, int icon_size = 24, Gtk::Orientation orient = Gtk::ORIENTATION_HORIZONTAL); - ~MenuAppItem() = default; + virtual ~MenuAppItem(); sigc::signal signal_launched(); virtual void set_orientation(Gtk::Orientation orient) override; void launch_app(); @@ -38,8 +38,6 @@ protected: virtual void on_drag_data_get(const Glib::RefPtr &context, Gtk::SelectionData &selection, guint info, guint timestamp) override; virtual void on_drag_end(const Glib::RefPtr &context) override; - virtual void on_context_menu_deactivated(); - virtual void init_drag_and_drop(); bool pin_app_to_taskbar(); @@ -55,6 +53,7 @@ private: bool menu_shown; sigc::signal m_signal_launched; + sigc::connection idle_drag_connection_; bool is_in_favorite(); bool is_fixed_on_taskbar(); diff --git a/src/menu/menu-applet-window.cpp b/src/menu/menu-applet-window.cpp index 952e401..941c2b8 100644 --- a/src/menu/menu-applet-window.cpp +++ b/src/menu/menu-applet-window.cpp @@ -71,6 +71,16 @@ MenuAppletWindow::MenuAppletWindow(Gtk::WindowType window_type) : Glib::ObjectBa signal_grab_broken_event().connect( sigc::mem_fun(*this, &MenuAppletWindow::on_grab_broken_event)); + + // 窗口激活时抓取窗口 + this->property_is_active().signal_changed().connect( + [this]() -> void + { + if (this->property_is_active().get_value()) + { + KiranHelper::grab_input(*this); + } + }); } MenuAppletWindow::~MenuAppletWindow() @@ -193,11 +203,6 @@ bool MenuAppletWindow::on_grab_broken_event(GdkEventGrabBroken *grab_broken_even return false; } -void MenuAppletWindow::on_power_menu_deactivated() -{ - KiranHelper::grab_input(*this); -} - void MenuAppletWindow::init_ui() { Gtk::Box *search_box, *main_box, *sider_box; @@ -544,10 +549,6 @@ bool MenuAppletWindow::on_map_event(GdkEventAny *any_event) on_search_stop(); - /* - * 获取当前系统的鼠标事件,这样才能在鼠标点击窗口外部时及时隐藏窗口 - */ - KiranHelper::grab_input(*this); if (display_mode == DISPLAY_MODE_EXPAND || profile.get_default_page() == PAGE_ALL_APPS) search_entry->grab_focus(); return true; @@ -677,8 +678,6 @@ void MenuAppletWindow::add_sidebar_buttons() side_box->add(*launcher_btn); auto power_btn = Gtk::make_managed(); - power_btn->signal_power_menu_deactivated().connect( - sigc::mem_fun(*this, &MenuAppletWindow::on_power_menu_deactivated)); side_box->add(*power_btn); side_box->show_all(); diff --git a/src/menu/menu-applet-window.h b/src/menu/menu-applet-window.h index d6224a4..0eae7d7 100644 --- a/src/menu/menu-applet-window.h +++ b/src/menu/menu-applet-window.h @@ -105,11 +105,6 @@ protected: */ virtual bool on_grab_broken_event(GdkEventGrabBroken *grab_broken_event); - /** - * @brief 回调函数,电源菜单关闭时调用 - */ - virtual void on_power_menu_deactivated(); - virtual void init_ui(); virtual void init_avatar_widget(); diff --git a/src/menu/menu-power-button.cpp b/src/menu/menu-power-button.cpp index 3b07e89..1a5a224 100644 --- a/src/menu/menu-power-button.cpp +++ b/src/menu/menu-power-button.cpp @@ -34,11 +34,6 @@ MenuPowerButton::~MenuPowerButton() delete menu; } -sigc::signal MenuPowerButton::signal_power_menu_deactivated() -{ - return m_signal_power_menu_deactivated; -} - void MenuPowerButton::on_clicked() { GdkEvent *event = gtk_get_current_event(); @@ -47,16 +42,9 @@ void MenuPowerButton::on_clicked() delete menu; menu = new MenuPowerMenu(); - menu->signal_deactivate().connect( - sigc::mem_fun(*this, &MenuPowerButton::on_power_menu_deactivated)); menu->attach_to_widget(*this); menu->show_all(); menu->popup_at_widget(this, Gdk::GRAVITY_SOUTH_EAST, Gdk::GRAVITY_SOUTH_WEST, event); gdk_event_free(event); } - -void MenuPowerButton::on_power_menu_deactivated() -{ - signal_power_menu_deactivated().emit(); -} diff --git a/src/menu/menu-power-button.h b/src/menu/menu-power-button.h index 9fec030..fb94225 100644 --- a/src/menu/menu-power-button.h +++ b/src/menu/menu-power-button.h @@ -24,17 +24,12 @@ public: MenuPowerButton(); ~MenuPowerButton(); - sigc::signal signal_power_menu_deactivated(); - protected: virtual void on_clicked() override; - virtual void on_power_menu_deactivated(); private: Gtk::Image icon; Gtk::Menu *menu; - - sigc::signal m_signal_power_menu_deactivated; }; #endif // MENU_POWER_BUTTON_H diff --git a/src/menu/recent-files-list-box.cpp b/src/menu/recent-files-list-box.cpp index 3f8e869..86ffd60 100644 --- a/src/menu/recent-files-list-box.cpp +++ b/src/menu/recent-files-list-box.cpp @@ -26,10 +26,11 @@ RecentFilesListBox::RecentFilesListBox() : filter_pattern("*") get_style_context()->add_class("menu-recent-list"); /* 最近访问文件列表发生变化时重新加载 */ - Gtk::RecentManager::get_default()->signal_changed().connect([this]() { - KLOG_DEBUG("The recent files are changed."); - this->load(); - }); + Gtk::RecentManager::get_default()->signal_changed().connect( + [this]() { + KLOG_DEBUG("The recent files are changed."); + this->load(); + }); load(); } @@ -172,12 +173,6 @@ Gtk::Widget *RecentFilesListBox::create_recent_item(const Glib::RefPtrattach_to_widget(*widget); - context_menu->signal_deactivate().connect( - [this]() -> void { - auto toplevel = get_toplevel(); - KiranHelper::grab_input(*toplevel); - }); - label->set_ellipsize(Pango::ELLIPSIZE_END); label->set_xalign(0.0f); -- 2.33.0