Blob Blame History Raw
From 7295e3ca5b6ce5061666c2da4c339853f0d16efc Mon Sep 17 00:00:00 2001
From: Jordan Petridis <jordan@centricular.com>
Date: Sat, 10 Apr 2021 01:57:50 +0300
Subject: [PATCH] Revert "Revert "Revert the introduction of the amtk library""

This reverts commit 18369a6958664f10b68c9edb749dbd3af7cc731a.

amtk is now archived.
---
 .gitignore                     |   1 +
 README.md                      |   1 -
 flatpak/org.gnome.Devhelp.json |  45 ++++++
 flatpak/org.gnome.Devhelp.yml  |  45 ------
 meson.build                    |   2 +-
 po/POTFILES.in                 |   3 +
 src/dh-app.c                   | 255 ++++++++++-----------------------
 src/dh-app.h                   |   2 -
 src/dh-main.c                  |   3 -
 src/dh-window.c                | 255 ++++++---------------------------
 src/dh-window.ui               | 245 +++++++++++++++++++++++++++++++
 src/dh.gresource.xml           |   5 +
 src/help-overlay.ui            | 117 +++++++++++++++
 src/menus.ui                   |  58 ++++++++
 14 files changed, 599 insertions(+), 438 deletions(-)
 create mode 100644 flatpak/org.gnome.Devhelp.json
 delete mode 100644 flatpak/org.gnome.Devhelp.yml
 create mode 100644 src/dh-window.ui
 create mode 100644 src/help-overlay.ui
 create mode 100644 src/menus.ui

\ No newline at end of file
diff --git a/README.md b/README.md
index 6057f78b..2d83a3c2 100644
--- a/README.md
+++ b/README.md
@@ -1,54 +1,53 @@
 Devhelp
 =======
 
 The Devhelp web page:
 
 https://wiki.gnome.org/Apps/Devhelp
 
 Installation of the Devhelp Flatpak
 -----------------------------------
 
 - [Devhelp on Flathub](https://flathub.org/apps/details/org.gnome.Devhelp)
 
 How to contribute
 -----------------
 
 See the [HACKING](HACKING) file.
 
 Dependencies
 ------------
 
 - GLib
 - GTK
 - WebKitGTK
-- [Amtk](https://wiki.gnome.org/Projects/Amtk)
 - gsettings-desktop-schemas
 
 Description
 -----------
 
 Devhelp is a developer tool for browsing and searching API documentation.
 It provides an easy way to navigate through libraries and to search by
 function, struct, or macro.
 
 The documentation must be installed locally, so an internet connection is
 not needed to use Devhelp.
 
 Devhelp works natively with GTK-Doc, so the GTK and GNOME libraries are
 well supported. But other development platforms can be supported as well,
 as long as the API documentation is available in HTML and a `*.devhelp2`
 index file is generated.
 
 Devhelp integrates with other applications such as Glade, Builder or
 Anjuta, and plugins are available for different text editors (gedit, Vim,
 Emacs, Geany, …).
 
 Integration with other developer tools
 --------------------------------------
 
 Devhelp provides some command line options, such as `--search` and
 `--search-assistant`. A text editor plugin can for example launch the command
 `devhelp --search function_name` when a keyboard shortcut is pressed, with the
 `function_name` under the cursor.
 
 Devhelp also provides a shared library, to integrate the GTK widgets inside an
diff --git a/flatpak/org.gnome.Devhelp.json b/flatpak/org.gnome.Devhelp.json
new file mode 100644
index 00000000..a2d1372d
--- /dev/null
+++ b/flatpak/org.gnome.Devhelp.json
@@ -0,0 +1,45 @@
+{
+    "app-id" : "org.gnome.Devhelp",
+    "runtime" : "org.gnome.Sdk",
+    "runtime-version" : "master",
+    "sdk" : "org.gnome.Sdk",
+    "command" : "devhelp",
+    "tags" : [
+        "nightly"
+    ],
+    "desktop-file-name-prefix" : "(Nightly) ",
+    "finish-args" : [
+        "--share=ipc",
+        "--socket=x11",
+        "--socket=wayland",
+        "--device=dri",
+        "--filesystem=host:ro"
+    ],
+    "cleanup" : [
+        "/include",
+        "/lib/pkgconfig",
+        "/share/pkgconfig",
+        "share/aclocal",
+        "man",
+        "share/man",
+        "*.la",
+        "*.a"
+    ],
+    "modules" : [
+        {
+            "name" : "devhelp",
+            "buildsystem" : "meson",
+            "config-opts" : [
+                "-Dflatpak_build=true"
+            ],
+            "run-tests" : true,
+            "sources" : [
+                {
+                    "type" : "git",
+                    "url" : "https://gitlab.gnome.org/GNOME/devhelp.git",
+                    "branch" : "master"
+                }
+            ]
+        }
+    ]
+}
diff --git a/flatpak/org.gnome.Devhelp.yml b/flatpak/org.gnome.Devhelp.yml
deleted file mode 100644
index 49b838b7..00000000
--- a/flatpak/org.gnome.Devhelp.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-app-id: org.gnome.Devhelp
-runtime: org.gnome.Sdk
-runtime-version: master
-sdk: org.gnome.Sdk
-command: devhelp
-tags:
-  - nightly
-desktop-file-name-prefix: "(Nightly) "
-
-finish-args:
-  # X11 + XShm access
-  - --share=ipc
-  - --socket=x11
-  # Wayland access
-  - --socket=wayland
-  # OpenGL for Webkit
-  - --device=dri
-  # We want full fs access to see the API docs installed by traditional Linux
-  # distro packages.
-  - --filesystem=host:ro
-
-build-options:
-  cflags: -O2 -g
-  cxxflags: -O2 -g
-
-cleanup:
-  - /share/man
-  - /lib/pkgconfig
-  - /include
-
-modules:
-  - name: amtk
-    buildsystem: meson
-    run-tests: true
-    sources:
-      - type: git
-        url: https://gitlab.gnome.org/GNOME/amtk.git
-
-  - name: devhelp
-    buildsystem: meson
-    config-opts: [ "-Dflatpak_build=true" ]
-    run-tests: true
-    sources:
-      - type: git
-        url: https://gitlab.gnome.org/GNOME/devhelp.git
diff --git a/meson.build b/meson.build
index bdd66056..d71d748d 100644
--- a/meson.build
+++ b/meson.build
@@ -35,61 +35,61 @@ LIBDEVHELP_API_VERSION_FULL = '3.0'
 #    changed since the last update, increment CURRENT and set REVISION
 #    to 0.
 # 3. If any exported functions or data have been added since the last
 #    public release, increment AGE.
 # 4. If any exported functions or data have been removed since the last
 #    public release, set AGE to 0.
 #
 # When incrementing the API version (usually for a new major package version),
 # set CURRENT, REVISION and AGE to 0 since it's like a new library.
 lt_current = 6
 lt_revision = 3
 lt_age = 0
 LIBDEVHELP_LT_VERSION = '@0@.@1@.@2@'.format(lt_current, lt_revision, lt_age)
 
 LIBDEVHELP_PUBLIC_DEPS = [
   dependency('gio-2.0', version: '>= 2.64'),
   dependency('gtk+-3.0', version: '>= 3.22'),
   dependency('webkit2gtk-4.0', version: '>= 2.26'),
 ]
 LIBDEVHELP_PRIVATE_DEPS = [
   dependency('gsettings-desktop-schemas'),
 ]
 LIBDEVHELP_DEPS = [
   LIBDEVHELP_PUBLIC_DEPS,
   LIBDEVHELP_PRIVATE_DEPS,
   meson.get_compiler('c').find_library('m'),
 ]
 
 DEVHELP_APP_DEPS = [
   LIBDEVHELP_DEPS,
-  dependency('amtk-5', version: '>= 5.0'),
+  dependency('gsettings-desktop-schemas'),
 ]
 
 # config.h
 
 config_data = configuration_data()
 GETTEXT_PACKAGE_NAME = meson.project_name()
 config_data.set_quoted('GETTEXT_PACKAGE', GETTEXT_PACKAGE_NAME)
 config_data.set_quoted('DATADIR', get_option('prefix') / get_option('datadir'))
 config_data.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir'))
 config_data.set_quoted('PACKAGE_VERSION', meson.project_version())
 config_data.set_quoted('LIBDEVHELP_API_VERSION', LIBDEVHELP_API_VERSION)
 config_data.set10('FLATPAK_BUILD', get_option('flatpak_build'))
 
 configure_file(
   output: 'config.h',
   configuration: config_data
 )
 
 # Misc
 
 # For #include <devhelp/something.h> or #include "config.h".
 ROOT_INCLUDE_DIR = include_directories('.')
 
 add_project_arguments(
   '-DG_LOG_DOMAIN="@0@"'.format(meson.project_name()),
   language: 'c'
 )
 
 #####
 # CFLAGS
diff --git a/po/POTFILES.in b/po/POTFILES.in
index db463e9e..cd6e6ed8 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -15,30 +15,33 @@ devhelp/dh-book-manager.c
 devhelp/dh-book-tree.c
 devhelp/dh-completion.c
 devhelp/dh-error.c
 devhelp/dh-init.c
 devhelp/dh-keyword-model.c
 devhelp/dh-link.c
 devhelp/dh-notebook.c
 devhelp/dh-parser.c
 devhelp/dh-profile-builder.c
 devhelp/dh-profile.c
 devhelp/dh-search-bar.c
 devhelp/dh-search-context.c
 devhelp/dh-settings-builder.c
 devhelp/dh-settings.c
 devhelp/dh-sidebar.c
 devhelp/dh-tab.c
 devhelp/dh-tab-label.c
 devhelp/dh-util-lib.c
 devhelp/dh-web-view.c
 plugins/gedit-plugin/devhelp.plugin.desktop.in
 plugins/gedit-plugin/devhelp.py
 src/dh-app.c
 src/dh-assistant.c
 src/dh-assistant.ui
 src/dh-main.c
 src/dh-preferences.c
 src/dh-preferences.ui
 src/dh-settings-app.c
 src/dh-util-app.c
 src/dh-window.c
+src/dh-window.ui
+src/help-overlay.ui
+src/menus.ui
diff --git a/src/dh-app.c b/src/dh-app.c
index 9ceae7f0..da97158c 100644
--- a/src/dh-app.c
+++ b/src/dh-app.c
@@ -1,200 +1,48 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
 /* SPDX-FileCopyrightText: 2002 CodeFactory AB
  * SPDX-FileCopyrightText: 2002 Mikael Hallendal <micke@imendio.com>
  * SPDX-FileCopyrightText: 2004-2008 Imendio AB
  * SPDX-FileCopyrightText: 2012 Aleksander Morgado <aleksander@gnu.org>
  * SPDX-FileCopyrightText: 2017, 2018 Sébastien Wilmet <swilmet@gnome.org>
  * SPDX-License-Identifier: GPL-3.0-or-later
  */
 
 #include "config.h"
 #include "dh-app.h"
 #include <glib/gi18n.h>
-#include <amtk/amtk.h>
 #include "dh-assistant.h"
 #include "dh-preferences.h"
 #include "dh-settings-app.h"
 #include "dh-util-app.h"
 
-struct _DhAppPrivate {
-        /* AmtkActionInfoStore for actions that are present in a menu. */
-        AmtkActionInfoStore *menu_action_info_store;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (DhApp, dh_app, GTK_TYPE_APPLICATION);
-
-/* This function adds the AmtkActionInfo's for the GActions that are present in
- * a menu.
- */
-static void
-add_menu_action_infos (DhApp *app)
-{
-        const gchar *accels[] = {NULL, NULL, NULL, NULL};
-        AmtkActionInfo *action_info;
-
-        const AmtkActionInfoEntry entries[] = {
-                /* action, icon, label, accel, tooltip */
-
-                /* Actions related to the whole application */
-                { "app.new-window", NULL, N_("New _Window"), "<Control>n",
-                  N_("Open a new window") },
-                { "app.preferences", NULL, N_("_Preferences") },
-                { "win.shortcuts-window", NULL, N_("_Keyboard Shortcuts"), "<Control>question",
-                  N_("Show keyboard shortcuts") },
-                { "app.help", NULL, N_("_Help"), "F1",
-                  N_("Show help") },
-                { "app.about", NULL, N_("_About Devhelp") },
-                { "app.quit", NULL, N_("_Quit"), "<Control>q",
-                  N_("Close all windows (quit the application)") },
-
-                /* Actions related to the current main window */
-                { "win.show-sidebar", NULL, N_("_Side Panel"), "F9",
-                  N_("Toggle side panel visibility") },
-                { "win.print", NULL, N_("_Print"), "<Control>p" },
-                { "win.find", NULL, N_("_Find"), "<Control>f",
-                  N_("Find in current page") },
-                { "win.zoom-in", NULL, N_("_Larger Text"), NULL,
-                  N_("Larger text") },
-                { "win.zoom-out", NULL, N_("S_maller Text"), NULL,
-                  N_("Smaller text") },
-                { "win.zoom-default", NULL, N_("_Normal Size"), NULL,
-                  N_("Normal size") },
-                { NULL }
-        };
-
-        g_assert (app->priv->menu_action_info_store == NULL);
-        app->priv->menu_action_info_store = amtk_action_info_store_new ();
-
-        amtk_action_info_store_add_entries (app->priv->menu_action_info_store,
-                                            entries, -1,
-                                            GETTEXT_PACKAGE);
-
-        /* The same as in Epiphany. */
-        accels[0] = "<Control>minus";
-        accels[1] = "<Control>KP_Subtract";
-        action_info = amtk_action_info_store_lookup (app->priv->menu_action_info_store, "win.zoom-out");
-        amtk_action_info_set_accels (action_info, accels);
-
-        /* The same as in Epiphany. */
-        accels[0] = "<Control>0";
-        accels[1] = "<Control>KP_0";
-        action_info = amtk_action_info_store_lookup (app->priv->menu_action_info_store, "win.zoom-default");
-        amtk_action_info_set_accels (action_info, accels);
-
-        /* For "<Control>equal": Epiphany also has this keyboard shortcut for
-         * zoom-in. On keyboards the = and + are usually on the same key, but +
-         * is less convenient to type because Shift must be pressed too.
-         * Apparently it's usual on Windows to press Ctrl+= to zoom in.
-         * https://bugzilla.gnome.org/show_bug.cgi?id=743704
-         */
-        accels[0] = "<Control>plus";
-        accels[1] = "<Control>equal";
-        accels[2] = "<Control>KP_Add";
-        action_info = amtk_action_info_store_lookup (app->priv->menu_action_info_store, "win.zoom-in");
-        amtk_action_info_set_accels (action_info, accels);
-
-        amtk_action_info_store_set_all_accels_to_app (app->priv->menu_action_info_store,
-                                                      GTK_APPLICATION (app));
-}
-
-/* This function adds the AmtkActionInfo's for other GActions (GActions that are
- * not present in a menu).
- */
-static void
-add_other_action_infos (DhApp *app)
-{
-        AmtkActionInfoStore *store;
-        AmtkActionInfo *action_info;
-        const gchar *accels[] = {NULL, NULL, NULL, NULL};
-
-        const AmtkActionInfoEntry entries[] = {
-                /* action, icon, label, accel, tooltip */
-                { "win.new-tab", NULL, NULL, "<Control>t", N_("Open a new tab") },
-                { "win.close-tab", NULL, NULL, "<Control>w", N_("Close the current tab") },
-                { "win.go-back", NULL, NULL, NULL, N_("Go back") },
-                { "win.go-forward", NULL, NULL, NULL, N_("Go forward") },
-                { "win.focus-search", NULL, NULL, NULL, N_("Focus global search") },
-                { NULL }
-        };
-
-        store = amtk_action_info_store_new ();
-        amtk_action_info_store_add_entries (store, entries, -1, GETTEXT_PACKAGE);
-
-        accels[0] = "<Alt>Left";
-        accels[1] = "Back";
-        action_info = amtk_action_info_store_lookup (store, "win.go-back");
-        amtk_action_info_set_accels (action_info, accels);
-
-        accels[0] = "<Alt>Right";
-        accels[1] = "Forward";
-        action_info = amtk_action_info_store_lookup (store, "win.go-forward");
-        amtk_action_info_set_accels (action_info, accels);
-
-        accels[0] = "<Control>k";
-        accels[1] = "<Control>s";
-        accels[2] = "<Control>l";
-        action_info = amtk_action_info_store_lookup (store, "win.focus-search");
-        amtk_action_info_set_accels (action_info, accels);
-
-        amtk_action_info_store_set_all_accels_to_app (store, GTK_APPLICATION (app));
-        g_object_unref (store);
-}
-
-/* This function adds the AmtkActionInfo's for things that have no related
- * GActions.
- */
-static void
-add_no_gaction_action_infos (void)
-{
-        AmtkActionInfoStore *store;
-
-        const AmtkActionInfoEntry entries[] = {
-                /* action, icon, label, accel, tooltip */
-                { "no-gaction-open-menu", NULL, NULL, "F10", N_("Open the menu") },
-                { "no-gaction-prev-tab", NULL, NULL, "<Control>Page_Up", N_("Previous tab") },
-                { "no-gaction-next-tab", NULL, NULL, "<Control>Page_Down", N_("Next tab") },
-                { NULL }
-        };
-
-        store = amtk_action_info_store_new ();
-        amtk_action_info_store_add_entries (store, entries, -1, GETTEXT_PACKAGE);
-        g_object_unref (store);
-}
-
-static void
-add_action_infos (DhApp *app)
-{
-        add_menu_action_infos (app);
-        add_other_action_infos (app);
-        add_no_gaction_action_infos ();
-}
+G_DEFINE_TYPE (DhApp, dh_app, GTK_TYPE_APPLICATION);
 
 static DhAssistant *
 get_active_assistant_window (DhApp *app)
 {
         GList *windows;
         GList *l;
 
         windows = gtk_application_get_windows (GTK_APPLICATION (app));
 
         for (l = windows; l != NULL; l = l->next) {
                 GtkWindow *cur_window = GTK_WINDOW (l->data);
 
                 if (DH_IS_ASSISTANT (cur_window))
                         return DH_ASSISTANT (cur_window);
         }
 
         return NULL;
 }
 
 static void
 save_active_main_window_gsettings (DhApp *app)
 {
         DhWindow *active_window;
         DhSettingsApp *settings;
 
         active_window = dh_app_get_active_main_window (app, FALSE);
         if (active_window == NULL)
                 return;
 
         settings = dh_settings_app_get_singleton ();
@@ -202,62 +50,60 @@ save_active_main_window_gsettings (DhApp *app)
                                       dh_settings_app_peek_window_settings (settings));
 }
 
 static void
 save_active_assistant_window_gsettings (DhApp *app)
 {
         DhAssistant *active_assistant;
         DhSettingsApp *settings;
 
         active_assistant = get_active_assistant_window (app);
         if (active_assistant == NULL)
                 return;
 
         settings = dh_settings_app_get_singleton ();
         dh_util_window_settings_save (GTK_WINDOW (active_assistant),
                                       dh_settings_app_peek_assistant_settings (settings));
 }
 
 static void
 new_window_cb (GSimpleAction *action,
                GVariant      *parameter,
                gpointer       user_data)
 {
         DhApp *app = DH_APP (user_data);
         GtkWidget *new_window;
 
         save_active_main_window_gsettings (app);
 
         new_window = dh_window_new (GTK_APPLICATION (app));
         gtk_widget_show_all (new_window);
-
-        amtk_action_info_store_check_all_used (app->priv->menu_action_info_store);
 }
 
 static void
 preferences_cb (GSimpleAction *action,
                 GVariant      *parameter,
                 gpointer       user_data)
 {
         DhApp *app = DH_APP (user_data);
         GtkWindow *parent_window;
 
         parent_window = (GtkWindow *) dh_app_get_active_main_window (app, FALSE);
         dh_preferences_show_dialog (parent_window);
 }
 
 static void
 help_cb (GSimpleAction *action,
          GVariant      *parameter,
          gpointer       user_data)
 {
         DhApp *app = DH_APP (user_data);
         GtkWindow *window;
         GError *error = NULL;
 
         window = (GtkWindow *) dh_app_get_active_main_window (app, FALSE);
 
         gtk_show_uri_on_window (window, "help:devhelp", GDK_CURRENT_TIME, &error);
 
         if (error != NULL) {
                 g_warning ("Failed to open the documentation: %s", error->message);
                 g_clear_error (&error);
@@ -364,127 +210,195 @@ raise_cb (GSimpleAction *action,
           GVariant      *parameter,
           gpointer       user_data)
 {
         DhApp *app = DH_APP (user_data);
         GtkWindow *window;
 
         window = gtk_application_get_active_window (GTK_APPLICATION (app));
         if (window == NULL)
                 window = (GtkWindow *) dh_app_get_active_main_window (app, TRUE);
 
         gtk_window_present (window);
 }
 
 static void
 add_action_entries (DhApp *app)
 {
         const GActionEntry app_entries[] = {
                 /* General actions */
                 { "new-window", new_window_cb },
                 { "preferences", preferences_cb },
                 { "help", help_cb },
                 { "about", about_cb },
                 { "quit", quit_cb },
 
                 /* Additional commandline-specific actions */
                 { "search", search_cb, "s" },
                 { "search-assistant", search_assistant_cb, "s" },
                 { "raise", raise_cb },
         };
 
-        amtk_action_map_add_action_entries_check_dups (G_ACTION_MAP (app),
-                                                       app_entries,
-                                                       G_N_ELEMENTS (app_entries),
-                                                       app);
+        g_action_map_add_action_entries (G_ACTION_MAP (app),
+                                         app_entries,
+                                         G_N_ELEMENTS (app_entries),
+                                         app);
 }
 
 static void
 setup_go_to_tab_accelerators (GtkApplication *app)
 {
         const gchar *accels[] = {NULL, NULL};
         gint key_num;
 
         for (key_num = 1; key_num <= 9; key_num++) {
                 gchar *accel;
                 gchar *detailed_action_name;
 
                 accel = g_strdup_printf ("<Alt>%d", key_num);
                 accels[0] = accel;
 
                 detailed_action_name = g_strdup_printf ("win.go-to-tab(uint16 %d)", key_num - 1);
 
                 gtk_application_set_accels_for_action (app, detailed_action_name, accels);
 
                 g_free (accel);
                 g_free (detailed_action_name);
         }
 
         /* On a typical keyboard the 0 is after 9, so it's the equivalent of 10
          * (9 starting from 0).
          */
         accels[0] = "<Alt>0";
         gtk_application_set_accels_for_action (app, "win.go-to-tab(uint16 9)", accels);
 }
 
 static void
-setup_additional_accelerators (GtkApplication *app)
+setup_accelerators (GtkApplication *app)
 {
-        const gchar *accels[] = {NULL, NULL};
+        const gchar *accels[] = {NULL, NULL, NULL, NULL};
 
         setup_go_to_tab_accelerators (app);
 
+        accels[0] = "<Control>0";
+        gtk_application_set_accels_for_action (app, "win.zoom-default", accels);
+
+        accels[0] = "<Control>minus";
+        gtk_application_set_accels_for_action (app, "win.zoom-out", accels);
+
+        /* For "<Control>equal": Epiphany also has this keyboard shortcut for
+         * zoom-in. On keyboards the = and + are usually on the same key, but +
+         * is less convenient to type because Shift must be pressed too.
+         * Apparently it's usual on Windows to press Ctrl+= to zoom in.
+         * https://bugzilla.gnome.org/show_bug.cgi?id=743704
+         */
+        accels[0] = "<Control>plus";
+        accels[1] = "<Control>equal";
+        gtk_application_set_accels_for_action (app, "win.zoom-in", accels);
+        accels[1] = NULL;
+
+        accels[0] = "<Control>f";
+        gtk_application_set_accels_for_action (app, "win.find", accels);
+
         accels[0] = "<Control>c";
         gtk_application_set_accels_for_action (app, "win.copy", accels);
 
+        accels[0] = "<Control>p";
+        gtk_application_set_accels_for_action (app, "win.print", accels);
+
+        accels[0] = "<Control>t";
+        gtk_application_set_accels_for_action (app, "win.new-tab", accels);
+
+        accels[0] = "<Control>n";
+        gtk_application_set_accels_for_action (app, "app.new-window", accels);
+
         accels[0] = "<Control>Page_Down";
         gtk_application_set_accels_for_action (app, "win.next-tab", accels);
 
         accels[0] = "<Control>Page_Up";
         gtk_application_set_accels_for_action (app, "win.prev-tab", accels);
 
+        accels[0] = "<Control>w";
+        gtk_application_set_accels_for_action (app, "win.close-tab", accels);
+
+        accels[0] = "<Control>q";
+        gtk_application_set_accels_for_action (app, "app.quit", accels);
+
+        accels[0] = "F1";
+        gtk_application_set_accels_for_action (app, "app.help", accels);
+
+        accels[0] = "F9";
+        gtk_application_set_accels_for_action (app, "win.show-sidebar", accels);
+
         accels[0] = "F10";
         gtk_application_set_accels_for_action (app, "win.show-window-menu", accels);
+
+        accels[0] = "<Alt>Right";
+        accels[1] = "Forward";
+        gtk_application_set_accels_for_action (app, "win.go-forward", accels);
+
+        accels[0] = "<Alt>Left";
+        accels[1] = "Back";
+        gtk_application_set_accels_for_action (app, "win.go-back", accels);
+
+        accels[0] = "<Control>k";
+        accels[1] = "<Control>s";
+        accels[2] = "<Control>l";
+        gtk_application_set_accels_for_action (app, "win.focus-search", accels);
+}
+
+static void
+set_app_menu_if_needed (GtkApplication *app)
+{
+        GMenu *manual_app_menu;
+
+        manual_app_menu = gtk_application_get_menu_by_id (app, "manual-app-menu");
+
+        /* Have the g_return in all cases, to catch problems in all cases. */
+        g_return_if_fail (manual_app_menu != NULL);
+
+        if (gtk_application_prefers_app_menu (app))
+                gtk_application_set_app_menu (app, G_MENU_MODEL (manual_app_menu));
 }
 
 static void
 dh_app_startup (GApplication *application)
 {
         DhApp *app = DH_APP (application);
 
         g_application_set_resource_base_path (application, "/org/gnome/devhelp");
 
         if (G_APPLICATION_CLASS (dh_app_parent_class)->startup != NULL)
                 G_APPLICATION_CLASS (dh_app_parent_class)->startup (application);
 
-        add_action_infos (app);
         add_action_entries (app);
-        setup_additional_accelerators (GTK_APPLICATION (app));
+        setup_accelerators (GTK_APPLICATION (app));
+        set_app_menu_if_needed (GTK_APPLICATION (app));
 }
 
 static void
 dh_app_activate (GApplication *app)
 {
         g_action_group_activate_action (G_ACTION_GROUP (app), "new-window", NULL);
 }
 
 static gboolean option_version;
 
 static GOptionEntry options[] = {
         { "new-window", 'n',
           0, G_OPTION_ARG_NONE, NULL,
           N_("Opens a new Devhelp window"),
           NULL
         },
         { "search", 's',
           0, G_OPTION_ARG_STRING, NULL,
           N_("Search for a keyword"),
           N_("KEYWORD")
         },
         { "search-assistant", 'a',
           0, G_OPTION_ARG_STRING, NULL,
           N_("Search and display any hit in the assistant window"),
           N_("KEYWORD")
         },
         { "version", 'v',
           0, G_OPTION_ARG_NONE, &option_version,
           N_("Display the version and exit"),
           NULL
@@ -523,89 +437,74 @@ dh_app_command_line (GApplication            *g_app,
         options_dict = g_application_command_line_get_options_dict (command_line);
 
         g_variant_dict_lookup (options_dict, "new-window", "b", &option_new_window);
         g_variant_dict_lookup (options_dict, "search", "&s", &option_search);
         g_variant_dict_lookup (options_dict, "search-assistant", "&s", &option_search_assistant);
         g_variant_dict_lookup (options_dict, "quit", "b", &option_quit);
 
         if (option_quit) {
                 g_action_group_activate_action (G_ACTION_GROUP (app), "quit", NULL);
                 return 0;
         }
 
         if (option_new_window)
                 g_action_group_activate_action (G_ACTION_GROUP (app), "new-window", NULL);
 
         if (option_search != NULL)
                 g_action_group_activate_action (G_ACTION_GROUP (app),
                                                 "search",
                                                 g_variant_new_string (option_search));
 
         if (option_search_assistant != NULL)
                 g_action_group_activate_action (G_ACTION_GROUP (app),
                                                 "search-assistant",
                                                 g_variant_new_string (option_search_assistant));
 
         g_action_group_activate_action (G_ACTION_GROUP (app), "raise", NULL);
 
         return 0;
 }
 
-static void
-dh_app_dispose (GObject *object)
-{
-        DhApp *app = DH_APP (object);
-
-        g_clear_object (&app->priv->menu_action_info_store);
-
-        G_OBJECT_CLASS (dh_app_parent_class)->dispose (object);
-}
-
 static void
 dh_app_class_init (DhAppClass *klass)
 {
-        GObjectClass *object_class = G_OBJECT_CLASS (klass);
         GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
 
-        object_class->dispose = dh_app_dispose;
-
         application_class->startup = dh_app_startup;
         application_class->activate = dh_app_activate;
         application_class->handle_local_options = dh_app_handle_local_options;
         application_class->command_line = dh_app_command_line;
 }
 
 static void
 dh_app_init (DhApp *app)
 {
-        app->priv = dh_app_get_instance_private (app);
-
         /* Translators: please don't translate "Devhelp" (it's marked as
          * translatable for transliteration only).
          */
         g_set_application_name (_("Devhelp"));
         gtk_window_set_default_icon_name ("org.gnome.Devhelp");
 
         g_application_add_main_option_entries (G_APPLICATION (app), options);
 }
 
 DhApp *
 dh_app_new (void)
 {
         return g_object_new (DH_TYPE_APP,
                              "application-id", "org.gnome.Devhelp",
                              "flags", G_APPLICATION_HANDLES_COMMAND_LINE,
                              NULL);
 }
 
 /* Returns: (transfer none) (nullable). */
 DhWindow *
 dh_app_get_active_main_window (DhApp    *app,
                                gboolean  create_if_none)
 {
         GList *windows;
         GList *l;
 
         g_return_val_if_fail (DH_IS_APP (app), NULL);
 
         windows = gtk_application_get_windows (GTK_APPLICATION (app));
 
diff --git a/src/dh-app.h b/src/dh-app.h
index d7ce15ba..5be3d939 100644
--- a/src/dh-app.h
+++ b/src/dh-app.h
@@ -1,44 +1,42 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
 /* SPDX-FileCopyrightText: 2012 Aleksander Morgado <aleksander@gnu.org>
  * SPDX-FileCopyrightText: 2017 Sébastien Wilmet <swilmet@gnome.org>
  * SPDX-License-Identifier: GPL-3.0-or-later
  */
 
 #ifndef DH_APP_H
 #define DH_APP_H
 
 #include <gtk/gtk.h>
 #include "dh-window.h"
 
 G_BEGIN_DECLS
 
 #define DH_TYPE_APP         (dh_app_get_type ())
 #define DH_APP(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), DH_TYPE_APP, DhApp))
 #define DH_APP_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), DH_TYPE_APP, DhAppClass))
 #define DH_IS_APP(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), DH_TYPE_APP))
 #define DH_IS_APP_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), DH_TYPE_APP))
 #define DH_APP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DH_TYPE_APP, DhAppClass))
 
 typedef struct _DhApp        DhApp;
 typedef struct _DhAppClass   DhAppClass;
-typedef struct _DhAppPrivate DhAppPrivate;
 
 struct _DhApp {
         GtkApplication parent_instance;
-        DhAppPrivate *priv;
 };
 
 struct _DhAppClass {
         GtkApplicationClass parent_class;
 };
 
 GType           dh_app_get_type                 (void) G_GNUC_CONST;
 
 DhApp *         dh_app_new                      (void);
 
 DhWindow *      dh_app_get_active_main_window   (DhApp    *app,
                                                  gboolean  create_if_none);
 
 G_END_DECLS
 
 #endif /* DH_APP_H */
diff --git a/src/dh-main.c b/src/dh-main.c
index 50d21974..f28aefde 100644
--- a/src/dh-main.c
+++ b/src/dh-main.c
@@ -1,36 +1,33 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
 /* SPDX-FileCopyrightText: 2001-2003 CodeFactory AB
  * SPDX-FileCopyrightText: 2001-2008 Imendio AB
  * SPDX-License-Identifier: GPL-3.0-or-later
  */
 
 #include "config.h"
 #include <locale.h>
 #include <glib/gi18n.h>
 #include <devhelp/devhelp.h>
-#include <amtk/amtk.h>
 #include "dh-app.h"
 #include "dh-settings-app.h"
 
 int
 main (int argc, char **argv)
 {
         DhApp *application;
         gint status;
 
         setlocale (LC_ALL, "");
         textdomain (GETTEXT_PACKAGE);
 
         dh_init ();
-        amtk_init ();
 
         application = dh_app_new ();
         status = g_application_run (G_APPLICATION (application), argc, argv);
         g_object_unref (application);
 
-        amtk_finalize ();
         dh_finalize ();
         dh_settings_app_unref_singleton ();
 
         return status;
 }
diff --git a/src/dh-window.c b/src/dh-window.c
index 6dea6209..f29d5d62 100644
--- a/src/dh-window.c
+++ b/src/dh-window.c
@@ -1,96 +1,109 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
 /* SPDX-FileCopyrightText: 2001-2008 Imendio AB
  * SPDX-FileCopyrightText: 2012 Aleksander Morgado <aleksander@gnu.org>
  * SPDX-FileCopyrightText: 2012 Thomas Bechtold <toabctl@gnome.org>
  * SPDX-FileCopyrightText: 2015-2020 Sébastien Wilmet <swilmet@gnome.org>
  * SPDX-License-Identifier: GPL-3.0-or-later
  */
 
 #include "dh-window.h"
 #include <glib/gi18n.h>
 #include <webkit2/webkit2.h>
 #include <devhelp/devhelp.h>
-#include <amtk/amtk.h>
 #include "dh-settings-app.h"
 #include "dh-util-app.h"
 
 typedef struct {
         GtkHeaderBar *header_bar;
-        GtkMenuButton *menu_button;
+        GtkMenuButton *window_menu_button;
+        GMenuModel *window_menu_plus_app_menu;
+
+        GtkPaned *hpaned;
+        GtkWidget *grid_sidebar;
+        GtkWidget *grid_documents;
 
         DhSidebar *sidebar;
         DhSearchBar *search_bar;
         DhNotebook *notebook;
 } DhWindowPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (DhWindow, dh_window, GTK_TYPE_APPLICATION_WINDOW);
 
 static gboolean
 dh_window_delete_event (GtkWidget   *widget,
                         GdkEventAny *event)
 {
         DhSettingsApp *settings;
 
         settings = dh_settings_app_get_singleton ();
         dh_util_window_settings_save (GTK_WINDOW (widget),
                                       dh_settings_app_peek_window_settings (settings));
 
         if (GTK_WIDGET_CLASS (dh_window_parent_class)->delete_event == NULL)
                 return GDK_EVENT_PROPAGATE;
 
         return GTK_WIDGET_CLASS (dh_window_parent_class)->delete_event (widget, event);
 }
 
 static void
 dh_window_dispose (GObject *object)
 {
         DhWindowPrivate *priv = dh_window_get_instance_private (DH_WINDOW (object));
 
         priv->header_bar = NULL;
-        priv->menu_button = NULL;
+        priv->window_menu_button = NULL;
         priv->sidebar = NULL;
         priv->search_bar = NULL;
         priv->notebook = NULL;
 
         G_OBJECT_CLASS (dh_window_parent_class)->dispose (object);
 }
 
 static void
 dh_window_class_init (DhWindowClass *klass)
 {
         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
         GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
         widget_class->delete_event = dh_window_delete_event;
 
         object_class->dispose = dh_window_dispose;
+
+        /* Bind class to template */
+        gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/devhelp/dh-window.ui");
+        gtk_widget_class_bind_template_child_private (widget_class, DhWindow, header_bar);
+        gtk_widget_class_bind_template_child_private (widget_class, DhWindow, window_menu_button);
+        gtk_widget_class_bind_template_child_private (widget_class, DhWindow, window_menu_plus_app_menu);
+        gtk_widget_class_bind_template_child_private (widget_class, DhWindow, hpaned);
+        gtk_widget_class_bind_template_child_private (widget_class, DhWindow, grid_sidebar);
+        gtk_widget_class_bind_template_child_private (widget_class, DhWindow, grid_documents);
 }
 
 /* Can return NULL during initialization and finalization, so it's better to
  * handle the NULL case with the return value of this function.
  */
 static DhWebView *
 get_active_web_view (DhWindow *window)
 {
         DhWindowPrivate *priv = dh_window_get_instance_private (window);
 
         return dh_notebook_get_active_web_view (priv->notebook);
 }
 
 static void
 update_window_title (DhWindow *window)
 {
         DhWindowPrivate *priv = dh_window_get_instance_private (window);
         DhWebView *web_view;
         const gchar *title;
 
         web_view = get_active_web_view (window);
         if (web_view == NULL)
                 return;
 
         title = dh_web_view_get_devhelp_title (web_view);
         gtk_header_bar_set_title (priv->header_bar, title);
 }
 
 static void
 update_zoom_actions_sensitivity (DhWindow *window)
@@ -198,62 +211,67 @@ go_to_tab_cb (GSimpleAction *action,
         gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), tab_num);
 }
 
 static void
 print_cb (GSimpleAction *action,
           GVariant      *parameter,
           gpointer       user_data)
 {
         DhWindow *window = DH_WINDOW (user_data);
         DhWebView *web_view;
         WebKitPrintOperation *print_operation;
 
         web_view = get_active_web_view (window);
         if (web_view == NULL)
                 return;
 
         print_operation = webkit_print_operation_new (WEBKIT_WEB_VIEW (web_view));
         webkit_print_operation_run_dialog (print_operation, GTK_WINDOW (window));
         g_object_unref (print_operation);
 }
 
 static void
 close_tab_cb (GSimpleAction *action,
               GVariant      *parameter,
               gpointer       user_data)
 {
         DhWindow *window = DH_WINDOW (user_data);
         DhWindowPrivate *priv = dh_window_get_instance_private (window);
         gint page_num;
 
-        page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
-        gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), page_num);
+        /* FIXME: the code here closes the current *tab*, but in help-overlay.ui
+         * it is documented as "Close the current window". Look for example at
+         * what gedit does, or other GNOME apps with a GtkNotebook plus Ctrl+W
+         * shortcut, and do the same.
+         */
+        page_num = gtk_notebook_get_current_page (priv->notebook);
+        gtk_notebook_remove_page (priv->notebook, page_num);
 }
 
 static void
 copy_cb (GSimpleAction *action,
          GVariant      *parameter,
          gpointer       user_data)
 {
         DhWindow *window = DH_WINDOW (user_data);
         DhWindowPrivate *priv = dh_window_get_instance_private (window);
         GtkWidget *widget;
 
         widget = gtk_window_get_focus (GTK_WINDOW (window));
 
         if (GTK_IS_EDITABLE (widget)) {
                 gtk_editable_copy_clipboard (GTK_EDITABLE (widget));
         } else if (GTK_IS_TREE_VIEW (widget) &&
                    gtk_widget_is_ancestor (widget, GTK_WIDGET (priv->sidebar))) {
                 DhLink *link;
 
                 link = dh_sidebar_get_selected_link (priv->sidebar);
                 if (link != NULL) {
                         GtkClipboard *clipboard;
 
                         clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD);
                         gtk_clipboard_set_text (clipboard, dh_link_get_name (link), -1);
                         dh_link_unref (link);
                 }
         } else {
                 DhWebView *web_view;
 
@@ -327,285 +345,108 @@ focus_search_cb (GSimpleAction *action,
 
         dh_sidebar_set_search_focus (priv->sidebar);
 }
 
 static void
 go_back_cb (GSimpleAction *action,
             GVariant      *parameter,
             gpointer       user_data)
 {
         DhWindow *window = DH_WINDOW (user_data);
         DhWebView *web_view;
 
         web_view = get_active_web_view (window);
         if (web_view != NULL)
                 webkit_web_view_go_back (WEBKIT_WEB_VIEW (web_view));
 }
 
 static void
 go_forward_cb (GSimpleAction *action,
                GVariant      *parameter,
                gpointer       user_data)
 {
         DhWindow *window = DH_WINDOW (user_data);
         DhWebView *web_view;
 
         web_view = get_active_web_view (window);
         if (web_view != NULL)
                 webkit_web_view_go_forward (WEBKIT_WEB_VIEW (web_view));
 }
 
-static void
-shortcuts_window_cb (GSimpleAction *action,
-                     GVariant      *parameter,
-                     gpointer       user_data)
-{
-        DhWindow *app_window = DH_WINDOW (user_data);
-        GtkShortcutsWindow *shortcuts_window;
-        GtkContainer *section;
-        GtkContainer *group;
-        AmtkFactory *factory;
-
-        shortcuts_window = amtk_shortcuts_window_new (GTK_WINDOW (app_window));
-
-        section = amtk_shortcuts_section_new (NULL);
-        g_object_set (section,
-                      "max-height", 10,
-                      NULL);
-
-        factory = amtk_factory_new (NULL);
-        amtk_factory_set_default_flags (factory, AMTK_FACTORY_IGNORE_GACTION);
-
-        group = amtk_shortcuts_group_new (_("Search"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.focus-search"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.find"));
-        gtk_container_add (section, GTK_WIDGET (group));
-
-        group = amtk_shortcuts_group_new (_("History"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.go-back"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.go-forward"));
-        gtk_container_add (section, GTK_WIDGET (group));
-
-        group = amtk_shortcuts_group_new (_("Zoom"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.zoom-in"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.zoom-out"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.zoom-default"));
-        gtk_container_add (section, GTK_WIDGET (group));
-
-        group = amtk_shortcuts_group_new (_("Tabs and Windows"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.new-tab"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "app.new-window"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "no-gaction-prev-tab"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "no-gaction-next-tab"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.close-tab"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "app.quit"));
-        gtk_container_add (section, GTK_WIDGET (group));
-
-        group = amtk_shortcuts_group_new (_("Miscellaneous"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.print"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.show-sidebar"));
-        gtk_container_add (section, GTK_WIDGET (group));
-
-        group = amtk_shortcuts_group_new (_("General"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "app.help"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "no-gaction-open-menu"));
-        gtk_container_add (group, amtk_factory_create_shortcut (factory, "win.shortcuts-window"));
-        gtk_container_add (section, GTK_WIDGET (group));
-
-        g_object_unref (factory);
-
-        gtk_container_add (GTK_CONTAINER (shortcuts_window), GTK_WIDGET (section));
-        gtk_widget_show_all (GTK_WIDGET (shortcuts_window));
-}
-
 static void
 add_actions (DhWindow *window)
 {
         DhWindowPrivate *priv = dh_window_get_instance_private (window);
         GPropertyAction *property_action;
 
         const GActionEntry win_entries[] = {
                 /* Tabs */
                 { "new-tab", new_tab_cb },
                 { "next-tab", next_tab_cb },
                 { "prev-tab", prev_tab_cb },
                 { "go-to-tab", go_to_tab_cb, "q" },
                 { "print", print_cb },
                 { "close-tab", close_tab_cb },
 
                 /* Edit */
                 { "copy", copy_cb },
                 { "find", find_cb },
 
                 /* View */
                 { "zoom-in", zoom_in_cb },
                 { "zoom-out", zoom_out_cb },
                 { "zoom-default", zoom_default_cb },
                 { "focus-search", focus_search_cb },
 
                 /* Go */
                 { "go-back", go_back_cb },
                 { "go-forward", go_forward_cb },
-
-                /* Help */
-                { "shortcuts-window", shortcuts_window_cb },
         };
 
-        amtk_action_map_add_action_entries_check_dups (G_ACTION_MAP (window),
-                                                       win_entries,
-                                                       G_N_ELEMENTS (win_entries),
-                                                       window);
+        g_action_map_add_action_entries (G_ACTION_MAP (window),
+                                         win_entries,
+                                         G_N_ELEMENTS (win_entries),
+                                         window);
 
         property_action = g_property_action_new ("show-sidebar",
-                                                 priv->sidebar,
+                                                 priv->grid_sidebar,
                                                  "visible");
         g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (property_action));
         g_object_unref (property_action);
 
         property_action = g_property_action_new ("show-window-menu",
-                                                 priv->menu_button,
+                                                 priv->window_menu_button,
                                                  "active");
         g_action_map_add_action (G_ACTION_MAP (window), G_ACTION (property_action));
         g_object_unref (property_action);
 }
 
-static GMenuModel *
-create_menu (void)
-{
-        GMenu *menu;
-        GMenu *section;
-        AmtkFactory *factory;
-
-        menu = g_menu_new ();
-        factory = amtk_factory_new (NULL);
-
-        section = g_menu_new ();
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "app.new-window"));
-        amtk_gmenu_append_section (menu, NULL, section);
-
-        section = g_menu_new ();
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "win.show-sidebar"));
-        amtk_gmenu_append_section (menu, NULL, section);
-
-        section = g_menu_new ();
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "win.print"));
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "win.find"));
-        amtk_gmenu_append_section (menu, NULL, section);
-
-        section = g_menu_new ();
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "win.zoom-in"));
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "win.zoom-out"));
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "win.zoom-default"));
-        amtk_gmenu_append_section (menu, NULL, section);
-
-        section = g_menu_new ();
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "app.preferences"));
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "win.shortcuts-window"));
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "app.help"));
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "app.about"));
-        /* Keep the Quit menu item. The GNOME goal recommends to remove it:
-         * https://gitlab.gnome.org/GNOME/Initiatives/wikis/App-Menu-Retirement
-         * “There is no need for the Quit menu item and the recommendation is to
-         * remove it from all locations.”
-         * In Devhelp, there *is* a need for the Quit menu item: after
-         * installing/uninstalling books on the filesystem, it may be necessary
-         * to restart Devhelp because the file monitoring is not perfect, see
-         * the class description of DhBookListDirectory. Instead of closing the
-         * Devhelp windows one by one, it's simpler to quit the whole
-         * application at once. But this can be fixed by adding a “reload books”
-         * action.
-         * Another use-case with the Quit menu item is when the app bugs, just
-         * restarting the app will most probably fix the problem (and then the
-         * user needs to avoid repeating the actions that make the app to bug).
-         */
-        amtk_gmenu_append_item (section, amtk_factory_create_gmenu_item (factory, "app.quit"));
-        amtk_gmenu_append_section (menu, NULL, section);
-
-        g_object_unref (factory);
-        g_menu_freeze (menu);
-
-        return G_MENU_MODEL (menu);
-}
-
-static void
-init_header_bar (DhWindow *window)
-{
-        DhWindowPrivate *priv = dh_window_get_instance_private (window);
-        GtkWidget *back_forward_hbox;
-        GtkStyleContext *style_context;
-        GtkWidget *back_button;
-        GtkWidget *forward_button;
-        GMenuModel *menu;
-        GtkWidget *new_tab_button;
-
-        g_assert (priv->header_bar == NULL);
-        g_assert (priv->menu_button == NULL);
-
-        priv->header_bar = GTK_HEADER_BAR (gtk_header_bar_new ());
-        gtk_header_bar_set_show_close_button (priv->header_bar, TRUE);
-
-        /* Back/forward buttons */
-        back_forward_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
-        style_context = gtk_widget_get_style_context (back_forward_hbox);
-        // Test also in RTL (right-to-left) text. It needs to be a GtkBox.
-        gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_LINKED);
-
-        back_button = gtk_button_new_from_icon_name ("go-previous-symbolic", GTK_ICON_SIZE_BUTTON);
-        gtk_actionable_set_action_name (GTK_ACTIONABLE (back_button), "win.go-back");
-        gtk_widget_set_tooltip_text (back_button, _("Back"));
-
-        forward_button = gtk_button_new_from_icon_name ("go-next-symbolic", GTK_ICON_SIZE_BUTTON);
-        gtk_actionable_set_action_name (GTK_ACTIONABLE (forward_button), "win.go-forward");
-        gtk_widget_set_tooltip_text (forward_button, _("Forward"));
-
-        gtk_container_add (GTK_CONTAINER (back_forward_hbox), back_button);
-        gtk_container_add (GTK_CONTAINER (back_forward_hbox), forward_button);
-        gtk_header_bar_pack_start (priv->header_bar, back_forward_hbox);
-
-        /* Menu */
-        priv->menu_button = GTK_MENU_BUTTON (gtk_menu_button_new ());
-        gtk_menu_button_set_direction (priv->menu_button, GTK_ARROW_NONE);
-        gtk_header_bar_pack_end (priv->header_bar, GTK_WIDGET (priv->menu_button));
-
-        menu = create_menu ();
-        gtk_menu_button_set_menu_model (priv->menu_button, menu);
-        g_object_unref (menu);
-
-        /* New tab button */
-        new_tab_button = gtk_button_new_from_icon_name ("tab-new-symbolic", GTK_ICON_SIZE_BUTTON);
-        gtk_actionable_set_action_name (GTK_ACTIONABLE (new_tab_button), "win.new-tab");
-        gtk_widget_set_tooltip_text (new_tab_button, _("New Tab"));
-        gtk_header_bar_pack_end (priv->header_bar, new_tab_button);
-
-        gtk_widget_show_all (GTK_WIDGET (priv->header_bar));
-}
-
 static void
 web_view_title_notify_cb (DhWebView  *web_view,
                           GParamSpec *param_spec,
                           DhWindow   *window)
 {
         if (web_view == get_active_web_view (window))
                 update_window_title (window);
 }
 
 static void
 web_view_zoom_level_notify_cb (DhWebView  *web_view,
                                GParamSpec *pspec,
                                DhWindow   *window)
 {
         if (web_view == get_active_web_view (window))
                 update_zoom_actions_sensitivity (window);
 }
 
 static void
 notebook_page_added_after_cb (GtkNotebook *notebook,
                               GtkWidget   *child,
                               guint        page_num,
                               DhWindow    *window)
 {
         DhTab *tab;
         DhWebView *web_view;
         WebKitBackForwardList *back_forward_list;
 
         g_return_if_fail (DH_IS_TAB (child));
 
@@ -628,118 +469,116 @@ notebook_page_added_after_cb (GtkNotebook *notebook,
                                  G_CALLBACK (update_back_forward_actions_sensitivity),
                                  window,
                                  G_CONNECT_AFTER | G_CONNECT_SWAPPED);
 }
 
 static void
 notebook_page_removed_after_cb (GtkNotebook *notebook,
                                 GtkWidget   *child,
                                 guint        page_num,
                                 DhWindow    *window)
 {
         if (gtk_notebook_get_n_pages (notebook) == 0)
                 gtk_window_close (GTK_WINDOW (window));
 }
 
 static void
 notebook_switch_page_after_cb (GtkNotebook *notebook,
                                GtkWidget   *new_page,
                                guint        new_page_num,
                                DhWindow    *window)
 {
         update_window_title (window);
         update_zoom_actions_sensitivity (window);
         update_back_forward_actions_sensitivity (window);
 }
 
 static void
 dh_window_init (DhWindow *window)
 {
         DhWindowPrivate *priv = dh_window_get_instance_private (window);
-        GtkPaned *hpaned;
+        GtkApplication *app;
         DhSettingsApp *settings;
         GSettings *paned_settings;
-        GtkWidget *contents_vgrid;
 
-        /* Header bar */
-        init_header_bar (window);
-        gtk_window_set_titlebar (GTK_WINDOW (window), GTK_WIDGET (priv->header_bar));
+        gtk_widget_init_template (GTK_WIDGET (window));
+
+        add_actions (window);
 
-        /* Horizontal paned */
-        hpaned = GTK_PANED (gtk_paned_new (GTK_ORIENTATION_HORIZONTAL));
+        app = GTK_APPLICATION (g_application_get_default ());
+        if (!gtk_application_prefers_app_menu (app)) {
+                gtk_menu_button_set_menu_model (priv->window_menu_button,
+                                                priv->window_menu_plus_app_menu);
+        }
 
         settings = dh_settings_app_get_singleton ();
         paned_settings = dh_settings_app_peek_paned_settings (settings);
         g_settings_bind (paned_settings, "position",
-                         hpaned, "position",
+                         priv->hpaned, "position",
                          G_SETTINGS_BIND_DEFAULT |
                          G_SETTINGS_BIND_NO_SENSITIVITY);
 
-        /* Left side of hpaned */
+        /* Sidebar */
         priv->sidebar = dh_sidebar_new2 (NULL);
-
-        /* Right side of hpaned */
-        contents_vgrid = gtk_grid_new ();
-        gtk_orientable_set_orientation (GTK_ORIENTABLE (contents_vgrid), GTK_ORIENTATION_VERTICAL);
+        gtk_widget_show (GTK_WIDGET (priv->sidebar));
+        gtk_container_add (GTK_CONTAINER (priv->grid_sidebar),
+                           GTK_WIDGET (priv->sidebar));
 
         // DhNotebook
         priv->notebook = dh_notebook_new (NULL);
+        gtk_widget_show (GTK_WIDGET (priv->notebook));
 
         dh_application_window_bind_sidebar_and_notebook (priv->sidebar, priv->notebook);
 
         g_signal_connect_after (priv->notebook,
                                 "page-added",
                                 G_CALLBACK (notebook_page_added_after_cb),
                                 window);
 
         g_signal_connect_after (priv->notebook,
                                 "page-removed",
                                 G_CALLBACK (notebook_page_removed_after_cb),
                                 window);
 
         g_signal_connect_after (priv->notebook,
                                 "switch-page",
                                 G_CALLBACK (notebook_switch_page_after_cb),
                                 window);
 
         // DhSearchBar
         priv->search_bar = dh_search_bar_new (priv->notebook);
+        gtk_widget_show (GTK_WIDGET (priv->search_bar));
 
-        /* Packing */
-        gtk_container_add (GTK_CONTAINER (contents_vgrid),
+        gtk_container_add (GTK_CONTAINER (priv->grid_documents),
                            GTK_WIDGET (priv->search_bar));
-        gtk_container_add (GTK_CONTAINER (contents_vgrid),
+        gtk_container_add (GTK_CONTAINER (priv->grid_documents),
                            GTK_WIDGET (priv->notebook));
-        gtk_paned_pack1 (hpaned, GTK_WIDGET (priv->sidebar), FALSE, FALSE);
-        gtk_paned_add2 (hpaned, contents_vgrid);
-        gtk_widget_show_all (GTK_WIDGET (hpaned));
-        gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (hpaned));
 
         add_actions (window);
 
         dh_notebook_open_new_tab (priv->notebook, NULL, TRUE);
 
         /* Focus search in sidebar by default. */
         dh_sidebar_set_search_focus (priv->sidebar);
 }
 
 GtkWidget *
 dh_window_new (GtkApplication *application)
 {
         DhWindow *window;
         DhSettingsApp *settings;
 
         g_return_val_if_fail (GTK_IS_APPLICATION (application), NULL);
 
         window = g_object_new (DH_TYPE_WINDOW,
                                "application", application,
                                NULL);
 
         settings = dh_settings_app_get_singleton ();
         gtk_widget_realize (GTK_WIDGET (window));
         dh_util_window_settings_restore (GTK_WINDOW (window),
                                          dh_settings_app_peek_window_settings (settings));
 
         return GTK_WIDGET (window);
 }
 
 void
diff --git a/src/dh-window.ui b/src/dh-window.ui
new file mode 100644
index 00000000..cff68898
--- /dev/null
+++ b/src/dh-window.ui
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.8 -->
+  <menu id="window_menu_simple">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Side Panel</attribute>
+        <attribute name="action">win.show-sidebar</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Print</attribute>
+        <attribute name="action">win.print</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Find</attribute>
+        <attribute name="action">win.find</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Larger Text</attribute>
+        <attribute name="action">win.zoom-in</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">S_maller Text</attribute>
+        <attribute name="action">win.zoom-out</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Normal Size</attribute>
+        <attribute name="action">win.zoom-default</attribute>
+      </item>
+    </section>
+  </menu>
+  <menu id="window_menu_plus_app_menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">New _Window</attribute>
+        <attribute name="action">app.new-window</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Side Panel</attribute>
+        <attribute name="action">win.show-sidebar</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Print</attribute>
+        <attribute name="action">win.print</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Find</attribute>
+        <attribute name="action">win.find</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Larger Text</attribute>
+        <attribute name="action">win.zoom-in</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">S_maller Text</attribute>
+        <attribute name="action">win.zoom-out</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Normal Size</attribute>
+        <attribute name="action">win.zoom-default</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Preferences</attribute>
+        <attribute name="action">app.preferences</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
+        <attribute name="action">win.show-help-overlay</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Help</attribute>
+        <attribute name="action">app.help</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_About Devhelp</attribute>
+        <attribute name="action">app.about</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Quit</attribute>
+        <attribute name="action">app.quit</attribute>
+      </item>
+    </section>
+  </menu>
+  <template class="DhWindow" parent="GtkApplicationWindow">
+    <property name="can_focus">False</property>
+    <property name="has_focus">False</property>
+    <property name="is_focus">False</property>
+    <child type="titlebar">
+      <object class="GtkHeaderBar" id="header_bar">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="vexpand">False</property>
+        <property name="show_close_button">True</property>
+        <child>
+          <object class="GtkBox" id="box">
+            <property name="visible">True</property>
+            <property name="valign">center</property>
+            <property name="can_focus">False</property>
+            <style>
+              <class name="linked"/>
+            </style>
+            <child>
+              <object class="GtkButton" id="back_button">
+                <property name="visible">True</property>
+                <property name="valign">center</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">Back</property>
+                <property name="action_name">win.go-back</property>
+                <style>
+                  <class name="image-button"/>
+                </style>
+                <child>
+                  <object class="GtkImage" id="back_button_image">
+                    <property name="visible">True</property>
+                    <property name="icon_size">1</property>
+                    <property name="icon_name">go-previous-symbolic</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="forward_button">
+                <property name="visible">True</property>
+                <property name="valign">center</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">Forward</property>
+                <property name="action_name">win.go-forward</property>
+                <style>
+                  <class name="image-button"/>
+                </style>
+                <child>
+                  <object class="GtkImage" id="forward_button_image">
+                    <property name="visible">True</property>
+                    <property name="icon_size">1</property>
+                    <property name="icon_name">go-next-symbolic</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="pack_type">start</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkMenuButton" id="window_menu_button">
+            <property name="visible">True</property>
+            <property name="valign">center</property>
+            <property name="can_focus">False</property>
+            <property name="menu_model">window_menu_simple</property>
+            <property name="use_popover">True</property>
+            <style>
+              <class name="image-button"/>
+            </style>
+            <child>
+              <object class="GtkImage" id="window_menu_image">
+                <property name="visible">True</property>
+                <property name="icon_size">1</property>
+                <property name="icon_name">open-menu-symbolic</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="pack_type">end</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="new_tab_button">
+            <property name="visible">True</property>
+            <property name="valign">center</property>
+            <property name="can_focus">False</property>
+            <property name="tooltip_text" translatable="yes">New Tab</property>
+            <property name="action_name">win.new-tab</property>
+            <style>
+              <class name="image-button"/>
+            </style>
+            <child>
+              <object class="GtkImage" id="new_tab_button_image">
+                <property name="visible">True</property>
+                <property name="icon_size">1</property>
+                <property name="icon_name">tab-new-symbolic</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="pack_type">end</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child>
+      <object class="GtkGrid" id="grid">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="has_focus">False</property>
+        <property name="is_focus">False</property>
+        <child>
+          <object class="GtkPaned" id="hpaned">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="has_focus">False</property>
+            <property name="is_focus">False</property>
+            <child>
+              <object class="GtkGrid" id="grid_sidebar">
+                <property name="visible">True</property>
+                <style>
+                  <class name="sidebar"/>
+                </style>
+              </object>
+              <packing>
+		<property name="shrink">False</property>
+	      </packing>
+            </child>
+            <child>
+              <object class="GtkGrid" id="grid_documents">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">1</property>
+            <property name="width">1</property>
+            <property name="height">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/dh.gresource.xml b/src/dh.gresource.xml
index 78fda590..d59c7663 100644
--- a/src/dh.gresource.xml
+++ b/src/dh.gresource.xml
@@ -1,15 +1,20 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
   SPDX-FileCopyrightText: 2013 Thomas Bechtold <thomasbechtold@jpberlin.de>
   SPDX-FileCopyrightText: 2013 Ignacio Casal Quinteiro <ignacio.casal@nice-software.com>
   SPDX-FileCopyrightText: 2016 Frédéric Péters <fpeters@0d.be>
   SPDX-FileCopyrightText: 2018 Günther Wagner <info@gunibert.de>
   SPDX-FileCopyrightText: 2018 Sébastien Wilmet <swilmet@gnome.org>
   SPDX-License-Identifier: GPL-3.0-or-later
 -->
 <gresources>
   <gresource prefix="/org/gnome/devhelp">
     <file preprocess="xml-stripblanks">dh-assistant.ui</file>
     <file preprocess="xml-stripblanks">dh-preferences.ui</file>
+    <file preprocess="xml-stripblanks">dh-window.ui</file>
+  </gresource>
+  <gresource prefix="/org/gnome/devhelp/gtk">
+    <file preprocess="xml-stripblanks">help-overlay.ui</file>
+    <file preprocess="xml-stripblanks">menus.ui</file>
   </gresource>
 </gresources>
diff --git a/src/help-overlay.ui b/src/help-overlay.ui
new file mode 100644
index 00000000..80eea36c
--- /dev/null
+++ b/src/help-overlay.ui
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkShortcutsWindow" id="help_overlay">
+    <property name="modal">1</property>
+    <child>
+      <object class="GtkShortcutsSection">
+        <property name="visible">1</property>
+        <property name="section-name">shortcuts</property>
+        <property name="max-height">10</property>
+        <child>
+          <object class="GtkShortcutsGroup">
+            <property name="visible">1</property>
+            <property name="title" translatable="yes" context="shortcut window">General</property>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;Control&gt;K</property>
+                <property name="title" translatable="yes" context="shortcut window">Focus global search</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;Control&gt;F</property>
+                <property name="title" translatable="yes" context="shortcut window">Find in current page</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;Control&gt;N</property>
+                <property name="title" translatable="yes" context="shortcut window">Open a new window</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;Control&gt;T</property>
+                <property name="title" translatable="yes" context="shortcut window">Open a new tab</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">F9</property>
+                <property name="title" translatable="yes" context="shortcut window">Toggle side panel visibility</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;alt&gt;Left</property>
+                <property name="title" translatable="yes" context="shortcut window">Go back</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;alt&gt;Right</property>
+                <property name="title" translatable="yes" context="shortcut window">Go forward</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;Control&gt;P</property>
+                <property name="title" translatable="yes" context="shortcut window">Print</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;Control&gt;W</property>
+                <property name="title" translatable="yes" context="shortcut window">Close the current window</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;Control&gt;Q</property>
+                <property name="title" translatable="yes" context="shortcut window">Close all windows</property>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="GtkShortcutsGroup">
+            <property name="visible">1</property>
+            <property name="title" translatable="yes" context="shortcut window">Zoom</property>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;ctrl&gt;plus</property>
+                <property name="title" translatable="yes" context="shortcut window">Zoom in</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;ctrl&gt;minus</property>
+                <property name="title" translatable="yes" context="shortcut window">Zoom out</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkShortcutsShortcut">
+                <property name="visible">1</property>
+                <property name="accelerator">&lt;ctrl&gt;0</property>
+                <property name="title" translatable="yes" context="shortcut window">Reset Zoom</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/src/menus.ui b/src/menus.ui
new file mode 100644
index 00000000..a2d53483
--- /dev/null
+++ b/src/menus.ui
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  This file is part of Devhelp.
+
+  Copyright (C) 2010 Imendio AB
+  Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org>
+  Copyright (C) 2017, 2018 Sébastien Wilmet <swilmet@gnome.org>
+
+  Devhelp is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published
+  by the Free Software Foundation, either version 3 of the License,
+  or (at your option) any later version.
+
+  Devhelp is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Devhelp.  If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<interface>
+  <requires lib="gtk+" version="3.0"/>
+  <!-- The app menu is set manually if needed. -->
+  <menu id="manual-app-menu">
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">New _Window</attribute>
+        <attribute name="action">app.new-window</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Preferences</attribute>
+        <attribute name="action">app.preferences</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
+        <attribute name="action">win.show-help-overlay</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Help</attribute>
+        <attribute name="action">app.help</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_About</attribute>
+        <attribute name="action">app.about</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">_Quit</attribute>
+        <attribute name="action">app.quit</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>
-- 
2.31.1