diff --git a/pidgin/plugins/disco/gtkdisco.h b/pidgin/plugins/disco/gtkdisco.h
--- a/pidgin/plugins/disco/gtkdisco.h
+++ b/pidgin/plugins/disco/gtkdisco.h
@@ -49,7 +49,6 @@ struct _PidginDiscoDialog {
 	PidginDiscoList *discolist;
 
 	GtkPopoverMenu *popover;
-	GMenuModel *popover_menu;
 
 	gpointer prompt_handle;
 };
# HG changeset patch
# Node ID fa78f04a75bb
# Parent  7b1ce0a21d6f
diff --git a/pidgin/plugins/disco/gtkdisco.c b/pidgin/plugins/disco/gtkdisco.c
--- a/pidgin/plugins/disco/gtkdisco.c
+++ b/pidgin/plugins/disco/gtkdisco.c
@@ -281,9 +281,11 @@ activate_add_to_blist(G_GNUC_UNUSED GSim
 }
 
 static gboolean
-service_click_cb(GtkTreeView *tree, GdkEventButton *event, gpointer user_data)
+service_click_cb(G_GNUC_UNUSED GtkGestureClick *click,
+                 G_GNUC_UNUSED gint n_press,
+                 gdouble x, gdouble y, gpointer data)
 {
-	PidginDiscoDialog *dialog = user_data;
+	PidginDiscoDialog *dialog = data;
 	XmppDiscoService *service;
 
 	GtkTreePath *path;
@@ -292,13 +294,9 @@ service_click_cb(GtkTreeView *tree, GdkE
 
 	GdkRectangle rect;
 
-	if (!gdk_event_triggers_context_menu((GdkEvent *)event)) {
-		return FALSE;
-	}
-
 	/* Figure out what was clicked */
-	if (!gtk_tree_view_get_path_at_pos(tree, event->x, event->y, &path,
-		                               NULL, NULL, NULL))
+	if (!gtk_tree_view_get_path_at_pos(dialog->tree, (gint)x, (gint)y, &path,
+	                                   NULL, NULL, NULL))
 	{
 		return FALSE;
 	}
@@ -314,8 +312,7 @@ service_click_cb(GtkTreeView *tree, GdkE
 	}
 
 	gtk_tree_view_convert_bin_window_to_widget_coords(dialog->tree,
-	                                                  (gint)event->x,
-	                                                  (gint)event->y,
+	                                                  (gint)x, (gint)y,
 	                                                  &rect.x, &rect.y);
 	rect.width = rect.height = 1;
 
@@ -428,11 +425,6 @@ activate_stop(G_GNUC_UNUSED GSimpleActio
 	pidgin_disco_list_set_in_progress(dialog->discolist, FALSE);
 }
 
-static void close_button_cb(GtkButton *button, PidginDiscoDialog *dialog)
-{
-	gtk_widget_destroy(GTK_WIDGET(dialog));
-}
-
 static gboolean
 disco_query_tooltip(GtkWidget *widget, int x, int y, gboolean keyboard_mode,
                     GtkTooltip *tooltip, gpointer data)
@@ -565,7 +557,7 @@ void pidgin_disco_dialogs_destroy_all(vo
 	while (dialogs) {
 		GtkWidget *dialog = dialogs->data;
 
-		gtk_widget_destroy(dialog);
+		gtk_window_destroy(GTK_WINDOW(dialog));
 		/* destroy_win_cb removes the dialog from the list */
 	}
 }
@@ -594,11 +586,8 @@ pidgin_disco_dialog_class_init(PidginDis
 	                                     model);
 	gtk_widget_class_bind_template_child(widget_class, PidginDiscoDialog,
 	                                     popover);
-	gtk_widget_class_bind_template_child(widget_class, PidginDiscoDialog,
-	                                     popover_menu);
 
 	gtk_widget_class_bind_template_callback(widget_class, destroy_win_cb);
-	gtk_widget_class_bind_template_callback(widget_class, close_button_cb);
 	gtk_widget_class_bind_template_callback(widget_class,
 	                                        dialog_select_account_cb);
 	gtk_widget_class_bind_template_callback(widget_class, row_activated_cb);
@@ -660,9 +649,6 @@ pidgin_disco_dialog_init(PidginDiscoDial
 
 	gtk_widget_insert_action_group(GTK_WIDGET(dialog), "disco",
 	                               G_ACTION_GROUP(action_group));
-
-	gtk_popover_bind_model(GTK_POPOVER(dialog->popover), dialog->popover_menu,
-	                       NULL);
 }
 
 /******************************************************************************
@@ -679,7 +665,7 @@ PidginDiscoDialog *
 pidgin_disco_dialog_new(void)
 {
 	PidginDiscoDialog *dialog = g_object_new(PIDGIN_TYPE_DISCO_DIALOG, NULL);
-	gtk_widget_show_all(GTK_WIDGET(dialog));
+	gtk_widget_show(GTK_WIDGET(dialog));
 	return dialog;
 }
 
diff --git a/pidgin/plugins/disco/resources/disco.ui b/pidgin/plugins/disco/resources/disco.ui
--- a/pidgin/plugins/disco/resources/disco.ui
+++ b/pidgin/plugins/disco/resources/disco.ui
@@ -15,12 +15,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICU
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+along with this program; if not, see <https://www.gnu.org/licenses/>.
 
 -->
 <interface>
-  <requires lib="gtk+" version="3.18"/>
+  <requires lib="gtk" version="4.0"/>
   <requires lib="pidgin" version="3.0"/>
   <!-- interface-license-type gplv2 -->
   <!-- interface-name Pidgin -->
@@ -38,11 +37,6 @@ Foundation, Inc., 51 Franklin Street, Fi
       </item>
     </section>
   </menu>
-  <object class="GtkPopoverMenu" id="popover">
-    <property name="can_focus">False</property>
-    <property name="relative-to">tree</property>
-    <property name="position">bottom</property>
-  </object>
   <object class="PidginAccountStore" id="accounts"/>
   <object class="PidginAccountFilterConnected" id="accounts_connected">
     <property name="child_model">accounts</property>
@@ -64,192 +58,147 @@ Foundation, Inc., 51 Franklin Street, Fi
     </columns>
   </object>
   <template class="PidginDiscoDialog" parent="GtkDialog">
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes">Service Discovery</property>
-    <property name="role">service discovery</property>
-    <property name="type_hint">dialog</property>
+    <property name="title" translatable="1">Service Discovery</property>
     <signal name="destroy" handler="destroy_win_cb" swapped="no"/>
-    <child internal-child="vbox">
+    <child internal-child="content_area">
       <object class="GtkBox">
-        <property name="can_focus">False</property>
+        <property name="vexpand">1</property>
         <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
         <child>
           <object class="GtkBox">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkLabel">
+                <property name="label" translatable="1">_Account:</property>
+                <property name="use_underline">1</property>
+                <property name="xalign">0</property>
+              </object>
+            </child>
             <child>
-              <object class="GtkBox">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkLabel">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="label" translatable="yes">_Account:</property>
-                    <property name="use_underline">True</property>
-                    <property name="xalign">0</property>
+              <object class="PidginAccountChooser" id="account_chooser">
+                <property name="model">xmpp_accounts</property>
+                <property name="active">0</property>
+                <signal name="changed" handler="dialog_select_account_cb" object="PidginDiscoDialog" swapped="no"/>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow">
+            <property name="vexpand">1</property>
+            <property name="focusable">1</property>
+            <property name="hscrollbar_policy">always</property>
+            <property name="vscrollbar_policy">always</property>
+            <property name="min_content_height">250</property>
+            <property name="child">
+              <object class="GtkTreeView" id="tree">
+                <property name="focusable">1</property>
+                <property name="model">model</property>
+                <signal name="row-activated" handler="row_activated_cb" object="PidginDiscoDialog" swapped="no"/>
+                <signal name="row-expanded" handler="row_expanded_cb" object="PidginDiscoDialog" swapped="no"/>
+                <child internal-child="selection">
+                  <object class="GtkTreeSelection">
+                    <signal name="changed" handler="selection_changed_cb" swapped="no"/>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
                 </child>
                 <child>
-                  <object class="PidginAccountChooser" id="account_chooser">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="model">xmpp_accounts</property>
-                    <property name="active">0</property>
-                    <signal name="changed" handler="dialog_select_account_cb" object="PidginDiscoDialog" swapped="no"/>
+                  <object class="GtkGestureClick">
+                    <property name="button">3</property>
+                    <signal name="pressed" handler="service_click_cb" object="PidginDiscoDialog" swapped="no"/>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
+                </child>
+                <child>
+                  <object class="GtkPopoverMenu" id="popover">
+                    <property name="menu-model">popover_menu</property>
+                  </object>
                 </child>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkScrolledWindow">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="hscrollbar_policy">always</property>
-                <property name="vscrollbar_policy">always</property>
-                <property name="shadow_type">in</property>
-                <property name="min_content_height">250</property>
                 <child>
-                  <object class="GtkTreeView" id="tree">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="model">model</property>
-                    <signal name="button-press-event" handler="service_click_cb" object="PidginDiscoDialog" swapped="no"/>
-                    <signal name="row-activated" handler="row_activated_cb" object="PidginDiscoDialog" swapped="no"/>
-                    <signal name="row-expanded" handler="row_expanded_cb" object="PidginDiscoDialog" swapped="no"/>
-                    <child internal-child="selection">
-                      <object class="GtkTreeSelection">
-                        <signal name="changed" handler="selection_changed_cb" swapped="no"/>
-                      </object>
+                  <object class="GtkTreeViewColumn">
+                    <property name="resizable">1</property>
+                    <property name="title" translatable="1">Name</property>
+                    <property name="reorderable">1</property>
+                    <property name="sort_column_id">1</property>
+                    <child>
+                      <object class="GtkCellRendererPixbuf"/>
+                      <attributes>
+                        <attribute name="pixbuf">0</attribute>
+                      </attributes>
                     </child>
                     <child>
-                      <object class="GtkTreeViewColumn">
-                        <property name="resizable">True</property>
-                        <property name="title" translatable="yes">Name</property>
-                        <property name="reorderable">True</property>
-                        <property name="sort_column_id">1</property>
-                        <child>
-                          <object class="GtkCellRendererPixbuf"/>
-                          <attributes>
-                            <attribute name="pixbuf">0</attribute>
-                          </attributes>
-                        </child>
-                        <child>
-                          <object class="GtkCellRendererText"/>
-                          <attributes>
-                            <attribute name="text">1</attribute>
-                          </attributes>
-                        </child>
-                      </object>
+                      <object class="GtkCellRendererText"/>
+                      <attributes>
+                        <attribute name="text">1</attribute>
+                      </attributes>
                     </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn">
+                    <property name="resizable">1</property>
+                    <property name="title" translatable="1">Description</property>
+                    <property name="reorderable">1</property>
+                    <property name="sort_column_id">2</property>
                     <child>
-                      <object class="GtkTreeViewColumn">
-                        <property name="resizable">True</property>
-                        <property name="title" translatable="yes">Description</property>
-                        <property name="reorderable">True</property>
-                        <property name="sort_column_id">2</property>
-                        <child>
-                          <object class="GtkCellRendererText"/>
-                          <attributes>
-                            <attribute name="text">2</attribute>
-                          </attributes>
-                        </child>
-                      </object>
+                      <object class="GtkCellRendererText"/>
+                      <attributes>
+                        <attribute name="text">2</attribute>
+                      </attributes>
                     </child>
                   </object>
                 </child>
               </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkProgressBar" id="progress">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
+            </property>
           </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
+        </child>
+        <child>
+          <object class="GtkProgressBar" id="progress">
+            <property name="valign">center</property>
+          </object>
         </child>
       </object>
     </child>
     <child type="action">
       <object class="GtkButton" id="stop_button">
-        <property name="label" translatable="yes">_Stop</property>
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="receives_default">True</property>
-        <property name="use_underline">True</property>
+        <property name="label" translatable="1">_Stop</property>
+        <property name="focusable">1</property>
+        <property name="receives_default">1</property>
+        <property name="use_underline">1</property>
         <property name="action-name">disco.stop</property>
       </object>
     </child>
     <child type="action">
       <object class="GtkButton" id="browse_button">
-        <property name="label" translatable="yes">_Browse</property>
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="receives_default">True</property>
-        <property name="use_underline">True</property>
+        <property name="label" translatable="1">_Browse</property>
+        <property name="focusable">1</property>
+        <property name="receives_default">1</property>
+        <property name="use_underline">1</property>
         <property name="action-name">disco.browse</property>
       </object>
     </child>
     <child type="action">
       <object class="GtkButton" id="register_button">
-        <property name="label" translatable="yes">Register</property>
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="receives_default">True</property>
+        <property name="label" translatable="1">Register</property>
+        <property name="focusable">1</property>
+        <property name="receives_default">1</property>
         <property name="action-name">disco.register</property>
       </object>
     </child>
     <child type="action">
       <object class="GtkButton" id="add_button">
-        <property name="label" translatable="yes">_Add</property>
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="receives_default">True</property>
-        <property name="use_underline">True</property>
+        <property name="label" translatable="1">_Add</property>
+        <property name="focusable">1</property>
+        <property name="receives_default">1</property>
+        <property name="use_underline">1</property>
         <property name="action-name">disco.add</property>
       </object>
     </child>
     <child type="action">
       <object class="GtkButton" id="close_button">
-        <property name="label" translatable="yes">_Close</property>
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="receives_default">True</property>
-        <property name="use_underline">True</property>
-        <signal name="clicked" handler="close_button_cb" swapped="no"/>
+        <property name="label" translatable="1">_Close</property>
+        <property name="focusable">1</property>
+        <property name="receives_default">1</property>
+        <property name="use_underline">1</property>
+        <signal name="clicked" handler="gtk_window_destroy" object="PidginDiscoDialog" swapped="yes"/>
       </object>
     </child>
     <action-widgets>
