diff --git a/src/components/chatmessage.cpp b/src/components/chatmessage.cpp index 4d6eec5..fd71fce 100644 --- a/src/components/chatmessage.cpp +++ b/src/components/chatmessage.cpp @@ -32,7 +32,6 @@ ChatMessageItemContainer *ChatMessageItemContainer::FromMessage(const Message &d if (!data.Content.empty() || data.Type != MessageType::DEFAULT) { container->m_text_component = container->CreateTextComponent(data); - container->AttachEventHandlers(*container->m_text_component); container->m_main.add(*container->m_text_component); } @@ -101,7 +100,6 @@ void ChatMessageItemContainer::UpdateContent() { if (!data->Embeds.empty()) { m_embed_component = CreateEmbedsComponent(data->Embeds); - AttachEventHandlers(*m_embed_component); m_main.add(*m_embed_component); m_embed_component->show_all(); } @@ -155,9 +153,9 @@ void ChatMessageItemContainer::AddClickHandler(Gtk::Widget *widget, const std::s widget->signal_button_press_event().connect([url](GdkEventButton *event) -> bool { if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) { LaunchBrowser(url); - return false; + return true; } - return true; + return false; }, false); // clang-format on } @@ -174,6 +172,8 @@ Gtk::TextView *ChatMessageItemContainer::CreateTextComponent(const Message &data tv->set_halign(Gtk::ALIGN_FILL); tv->set_hexpand(true); + tv->signal_button_press_event().connect(sigc::mem_fun(*this, &ChatMessageItemContainer::OnTextViewButtonPress), false); + UpdateTextComponent(tv); return tv; @@ -281,8 +281,6 @@ void ChatMessageItemContainer::UpdateTextComponent(Gtk::TextView *tv) { tag->property_weight() = Pango::WEIGHT_BOLD; m_channel_tagmap[tag] = *data->MessageReference->ChannelID; b->insert_with_tag(iter, data->Content, tag); - - tv->signal_button_press_event().connect(sigc::mem_fun(*this, &ChatMessageItemContainer::OnClickChannel), false); } else { b->insert_markup(s, "" + author->GetEscapedBoldName() + " started a thread: " + Glib::Markup::escape_text(data->Content) + ""); } @@ -297,12 +295,10 @@ Gtk::Widget *ChatMessageItemContainer::CreateEmbedsComponent(const std::vectorProxyURL, *embed.Thumbnail->URL, *embed.Thumbnail->Width, *embed.Thumbnail->Height); widget->show(); - AttachEventHandlers(*widget); box->add(*widget); } else { auto *widget = CreateEmbedComponent(embed); widget->show(); - AttachEventHandlers(*widget); box->add(*widget); } } @@ -493,12 +489,22 @@ Gtk::Widget *ChatMessageItemContainer::CreateImageComponent(const std::string &p Gtk::EventBox *ev = Gtk::manage(new Gtk::EventBox); Gtk::Image *widget = Gtk::manage(new LazyImage(proxy_url, w, h, false)); ev->add(*widget); + ev->set_halign(Gtk::ALIGN_START); widget->set_halign(Gtk::ALIGN_START); widget->set_size_request(w, h); - AttachEventHandlers(*ev); AddClickHandler(ev, url); + const auto on_button_press_event = [this, url](GdkEventButton *e) -> bool { + if (e->type == GDK_BUTTON_PRESS && e->button == GDK_BUTTON_SECONDARY) { + m_selected_link = url; + m_link_menu.popup_at_pointer(reinterpret_cast(e)); + return true; + } + return false; + }; + ev->signal_button_press_event().connect(on_button_press_event, false); + return ev; } @@ -510,9 +516,18 @@ Gtk::Widget *ChatMessageItemContainer::CreateAttachmentComponent(const Attachmen ev->get_style_context()->add_class("message-attachment-box"); ev->add(*btn); - AttachEventHandlers(*ev); AddClickHandler(ev, data.URL); + const auto on_button_press_event = [this, url = data.URL](GdkEventButton *e) -> bool { + if (e->type == GDK_BUTTON_PRESS && e->button == GDK_BUTTON_SECONDARY) { + m_selected_link = url; + m_link_menu.popup_at_pointer(reinterpret_cast(e)); + return true; + } + return false; + }; + ev->signal_button_press_event().connect(on_button_press_event, false); + return ev; } @@ -534,7 +549,6 @@ Gtk::Widget *ChatMessageItemContainer::CreateStickersComponent(const std::vector box->show(); - AttachEventHandlers(*box); return box; } @@ -956,7 +970,6 @@ void ChatMessageItemContainer::HandleChannelMentions(const Glib::RefPtrsignal_button_press_event().connect(sigc::mem_fun(*this, &ChatMessageItemContainer::OnClickChannel), false); HandleChannelMentions(tv->get_buffer()); } @@ -990,6 +1003,20 @@ bool ChatMessageItemContainer::OnClickChannel(GdkEventButton *ev) { return false; } +bool ChatMessageItemContainer::OnTextViewButtonPress(GdkEventButton *ev) { + // run all button press handlers and propagate if none return true + if (OnLinkClick(ev)) return true; + if (OnClickChannel(ev)) return true; + + if (ev->type == GDK_BUTTON_PRESS && ev->button == GDK_BUTTON_SECONDARY) { + // send the event upward skipping TextView's handler because we dont want it + gtk_propagate_event(GTK_WIDGET(m_main.gobj()), reinterpret_cast(ev)); + return true; + } + + return false; +} + void ChatMessageItemContainer::on_link_menu_copy() { Gtk::Clipboard::get()->set_text(m_selected_link); } @@ -997,8 +1024,6 @@ void ChatMessageItemContainer::on_link_menu_copy() { void ChatMessageItemContainer::HandleLinks(Gtk::TextView &tv) { const auto rgx = Glib::Regex::create(R"(\bhttps?:\/\/[^\s]+\.[^\s]+\b)"); - tv.signal_button_press_event().connect(sigc::mem_fun(*this, &ChatMessageItemContainer::OnLinkClick), false); - auto buf = tv.get_buffer(); Glib::ustring text = GetText(buf); @@ -1070,18 +1095,6 @@ ChatMessageItemContainer::type_signal_action_reaction_remove ChatMessageItemCont return m_signal_action_reaction_remove; } -void ChatMessageItemContainer::AttachEventHandlers(Gtk::Widget &widget) { - const auto on_button_press_event = [this](GdkEventButton *e) -> bool { - if (e->type == GDK_BUTTON_PRESS && e->button == GDK_BUTTON_SECONDARY) { - event(reinterpret_cast(e)); // illegal ooooooh - return true; - } - - return false; - }; - widget.signal_button_press_event().connect(on_button_press_event, false); -} - ChatMessageHeader::ChatMessageHeader(const Message &data) : m_main_box(Gtk::ORIENTATION_HORIZONTAL) , m_content_box(Gtk::ORIENTATION_VERTICAL) diff --git a/src/components/chatmessage.hpp b/src/components/chatmessage.hpp index 86c3fea..7851351 100644 --- a/src/components/chatmessage.hpp +++ b/src/components/chatmessage.hpp @@ -2,7 +2,7 @@ #include #include "discord/discord.hpp" -class ChatMessageItemContainer : public Gtk::Box { +class ChatMessageItemContainer : public Gtk::EventBox { public: Snowflake ID; Snowflake ChannelID; @@ -44,6 +44,7 @@ protected: void HandleChannelMentions(const Glib::RefPtr &buf); void HandleChannelMentions(Gtk::TextView *tv); bool OnClickChannel(GdkEventButton *ev); + bool OnTextViewButtonPress(GdkEventButton *ev); // reused for images and links Gtk::Menu m_link_menu; @@ -57,8 +58,6 @@ protected: std::map, std::string> m_link_tagmap; std::map, Snowflake> m_channel_tagmap; - void AttachEventHandlers(Gtk::Widget &widget); - Gtk::EventBox *_ev; Gtk::Box m_main; Gtk::Label *m_attrib_label = nullptr;