[console/wip/exalm/gtk4: 1/4] Port to GTK4 and libadwaita
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [console/wip/exalm/gtk4: 1/4] Port to GTK4 and libadwaita
- Date: Mon, 25 Jul 2022 06:27:58 +0000 (UTC)
commit c1f39d38f4dc9dc7a3fd3ce4b63db17bf749daa1
Author: Alexander Mikhaylenko <alexm gnome org>
Date: Mon Jul 18 03:29:29 2022 +0400
Port to GTK4 and libadwaita
.gitlab-ci.yml | 4 +-
build-aux/flatpak/org.gnome.Console.Devel.json | 4 +-
meson.build | 14 +-
src/help-overlay.ui | 15 +-
src/kgx-application.c | 51 +-
src/kgx-application.h | 4 +-
src/kgx-close-dialog.c | 8 +-
src/kgx-close-dialog.ui | 6 +-
src/kgx-pages.c | 170 +++----
src/kgx-pages.h | 9 +-
src/kgx-pages.ui | 19 +-
src/kgx-simple-tab.ui | 10 +-
src/kgx-tab-button.c | 30 +-
src/kgx-tab-button.h | 6 +-
src/kgx-tab-button.ui | 16 +-
src/kgx-tab-switcher-row.c | 55 ++-
src/kgx-tab-switcher-row.h | 8 +-
src/kgx-tab-switcher-row.ui | 52 +--
src/kgx-tab-switcher.c | 379 +++++++--------
src/kgx-tab-switcher.h | 12 +-
src/kgx-tab-switcher.ui | 41 +-
src/kgx-tab.c | 186 +++-----
src/kgx-tab.h | 4 +-
src/kgx-tab.ui | 60 +--
src/kgx-terminal.c | 318 +++++++------
src/kgx-terminal.h | 8 +-
src/kgx-theme-switcher.c | 34 +-
src/kgx-theme-switcher.h | 2 +-
src/kgx-theme-switcher.ui | 25 +-
src/kgx-window.c | 184 +++-----
src/kgx-window.h | 12 +-
src/kgx-window.ui | 253 ++++------
src/kgx.gresource.xml.in | 2 -
src/menus.ui | 2 +-
src/meson.build | 13 +-
src/styles/_definitions.scss | 31 --
src/styles/_drawing.scss | 614 -------------------------
src/styles/_recoloring.scss | 205 ---------
src/styles/_styles.scss | 185 +++-----
src/styles/meson.build | 5 -
src/styles/styles-hc-dark.scss | 4 -
src/styles/styles-hc.scss | 4 -
subprojects/adwaita.wrap | 4 +
subprojects/handy.wrap | 4 -
44 files changed, 954 insertions(+), 2118 deletions(-)
---
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index fd11e0e..4a19889 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -5,7 +5,7 @@ debian:
stage: build
before_script:
- apt -y update
- - apt -y install gcc g++ gettext git libgnutls28-dev libgtk-3-dev
+ - apt -y install gcc g++ gettext git libgnutls28-dev libgtk-4-dev
libsystemd-dev libgtop2-dev meson sassc desktop-file-utils appstream-util
gsettings-desktop-schemas-dev
script:
@@ -18,7 +18,7 @@ fedora:
before_script:
- dnf update -y --nogpgcheck
- dnf install -y --nogpgcheck meson gettext glib2-devel gcc gcc-c++ git
- desktop-file-utils gperf "pkgconfig(gtk+-3.0)" libappstream-glib
+ desktop-file-utils gperf "pkgconfig(gtk4)" libappstream-glib
"pkgconfig(vte-2.91)" "pkgconfig(libgtop-2.0)" "pkgconfig(fribidi)"
"pkgconfig(gnutls)" "pkgconfig(libsystemd)" "pkgconfig(libpcre2-8)"
"pkgconfig(gsettings-desktop-schemas)" sassc
diff --git a/build-aux/flatpak/org.gnome.Console.Devel.json b/build-aux/flatpak/org.gnome.Console.Devel.json
index 7ee5bca..cfdc60b 100644
--- a/build-aux/flatpak/org.gnome.Console.Devel.json
+++ b/build-aux/flatpak/org.gnome.Console.Devel.json
@@ -27,7 +27,9 @@
{
"name" : "vte",
"config-opts" : [
- "-Dvapi=false"
+ "-Dvapi=false",
+ "-Dgtk3=false",
+ "-Dgtk4=true"
],
"buildsystem" : "meson",
"sources" : [
diff --git a/meson.build b/meson.build
index 03fd02e..65da618 100644
--- a/meson.build
+++ b/meson.build
@@ -10,10 +10,12 @@ project('gnome-console', 'c', version: '42.beta',
'vte:gir=false',
'vte:vapi=false',
'libsass:werror=false',
- 'handy:werror=false',
- 'handy:vapi=false',
- 'handy:introspection=disabled',
- 'handy:tests=false',
+ 'vte:gtk3=false',
+ 'vte:gtk4=true',
+ 'adwaita:werror=false',
+ 'adwaita:vapi=false',
+ 'adwaita:introspection=disabled',
+ 'adwaita:tests=false',
],
)
@@ -63,11 +65,9 @@ config_h = vcs_tag( input: config_h_in,
command: ['git', 'rev-parse', '--short', 'HEAD'],
fallback: 'Devel')
-gtk_ver = 'GDK_VERSION_3_24'
+gtk_ver = 'GDK_VERSION_4_0'
glib_ver = 'GLIB_VERSION_2_66'
add_project_arguments([
- '-DGDK_VERSION_MIN_REQUIRED=@0@'.format(gtk_ver),
- '-DGDK_VERSION_MAX_ALLOWED=@0@'.format(gtk_ver),
'-DGLIB_VERSION_MIN_REQUIRED=@0@'.format(glib_ver),
'-DGLIB_VERSION_MAX_ALLOWED=@0@'.format(glib_ver),
'-DG_LOG_USE_STRUCTURED',
diff --git a/src/help-overlay.ui b/src/help-overlay.ui
index 0c78737..451bfdc 100644
--- a/src/help-overlay.ui
+++ b/src/help-overlay.ui
@@ -1,20 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.20"/>
+ <requires lib="gtk" version="4.0"/>
<object class="GtkShortcutsWindow" id="help_overlay">
<property name="modal">True</property>
<child>
<object class="GtkShortcutsSection">
<property name="section-name">shortcuts</property>
<property name="max-height">12</property>
- <property name="visible">True</property>
<child>
<object class="GtkShortcutsGroup">
<property name="title" translatable="yes" context="shortcut window">Application</property>
- <property name="visible">True</property>
<child>
<object class="GtkShortcutsShortcut">
- <property name="visible">True</property>
<property name="action-name">win.new-window</property>
<property name="title" translatable="yes" context="shortcut window">New Window</property>
</object>
@@ -24,24 +21,20 @@
<child>
<object class="GtkShortcutsGroup">
<property name="title" translatable="yes" context="shortcut window">Terminal</property>
- <property name="visible">True</property>
<child>
<object class="GtkShortcutsShortcut">
- <property name="visible">True</property>
<property name="action-name">win.find</property>
<property name="title" translatable="yes" context="shortcut window">Find</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
- <property name="visible">True</property>
<property name="action-name">term.copy</property>
<property name="title" translatable="yes" context="shortcut window">Copy</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
- <property name="visible">True</property>
<property name="action-name">term.paste</property>
<property name="title" translatable="yes" context="shortcut window">Paste</property>
</object>
@@ -51,38 +44,32 @@
<child>
<object class="GtkShortcutsGroup">
<property name="title" translatable="yes" context="shortcut window">Tabs</property>
- <property name="visible">True</property>
<child>
<object class="GtkShortcutsShortcut">
- <property name="visible">True</property>
<property name="action-name">win.new-tab</property>
<property name="title" translatable="yes" context="shortcut window">New Tab</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
- <property name="visible">True</property>
<property name="action-name">win.close-tab</property>
<property name="title" translatable="yes" context="shortcut window">Close Tab</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
- <property name="visible">True</property>
<property name="accelerator"><primary>Tab</property>
<property name="title" translatable="yes" context="shortcut window">Next Tab</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
- <property name="visible">True</property>
<property name="accelerator"><shift><primary>Tab</property>
<property name="title" translatable="yes" context="shortcut window">Previous Tab</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
- <property name="visible">True</property>
<property name="accelerator"><alt>1...9</property>
<property name="title" translatable="yes" context="shortcut window">Switch to Tab</property>
</object>
diff --git a/src/kgx-application.c b/src/kgx-application.c
index 753f37e..0c5cd92 100644
--- a/src/kgx-application.c
+++ b/src/kgx-application.c
@@ -44,7 +44,7 @@
#define LOGO_COL_SIZE 28
#define LOGO_ROW_SIZE 14
-G_DEFINE_TYPE (KgxApplication, kgx_application, GTK_TYPE_APPLICATION)
+G_DEFINE_TYPE (KgxApplication, kgx_application, ADW_TYPE_APPLICATION)
enum {
PROP_0,
@@ -62,25 +62,25 @@ static void
kgx_application_set_theme (KgxApplication *self,
KgxTheme theme)
{
- HdyStyleManager *style_manager;
+ AdwStyleManager *style_manager;
g_return_if_fail (KGX_IS_APPLICATION (self));
self->theme = theme;
- style_manager = hdy_style_manager_get_default ();
+ style_manager = adw_style_manager_get_default ();
switch (theme) {
case KGX_THEME_AUTO:
- hdy_style_manager_set_color_scheme (style_manager, HDY_COLOR_SCHEME_PREFER_LIGHT);
+ adw_style_manager_set_color_scheme (style_manager, ADW_COLOR_SCHEME_PREFER_LIGHT);
break;
case KGX_THEME_DAY:
- hdy_style_manager_set_color_scheme (style_manager, HDY_COLOR_SCHEME_FORCE_LIGHT);
+ adw_style_manager_set_color_scheme (style_manager, ADW_COLOR_SCHEME_FORCE_LIGHT);
break;
case KGX_THEME_NIGHT:
case KGX_THEME_HACKER:
default:
- hdy_style_manager_set_color_scheme (style_manager, HDY_COLOR_SCHEME_FORCE_DARK);
+ adw_style_manager_set_color_scheme (style_manager, ADW_COLOR_SCHEME_FORCE_DARK);
break;
}
@@ -317,15 +317,10 @@ set_watcher (KgxApplication *self, gboolean focused)
static void
update_styles (KgxApplication *self)
{
- HdyStyleManager *style_manager = hdy_style_manager_get_default ();
- gboolean dark = hdy_style_manager_get_dark (style_manager);
- gboolean hc = hdy_style_manager_get_high_contrast (style_manager);
-
- if (hc && dark) {
- gtk_css_provider_load_from_resource (self->provider, KGX_APPLICATION_PATH "styles-hc-dark.css");
- } else if (hc) {
- gtk_css_provider_load_from_resource (self->provider, KGX_APPLICATION_PATH "styles-hc.css");
- } else if (dark) {
+ AdwStyleManager *style_manager = adw_style_manager_get_default ();
+ gboolean dark = adw_style_manager_get_dark (style_manager);
+
+ if (dark) {
gtk_css_provider_load_from_resource (self->provider, KGX_APPLICATION_PATH "styles-dark.css");
} else {
gtk_css_provider_load_from_resource (self->provider, KGX_APPLICATION_PATH "styles-light.css");
@@ -337,7 +332,7 @@ static void
kgx_application_startup (GApplication *app)
{
KgxApplication *self = KGX_APPLICATION (app);
- HdyStyleManager *style_manager;
+ AdwStyleManager *style_manager;
g_autoptr (GAction) settings_action = NULL;
const char *const new_window_accels[] = { "<shift><primary>n", NULL };
@@ -359,8 +354,6 @@ kgx_application_startup (GApplication *app)
G_APPLICATION_CLASS (kgx_application_parent_class)->startup (app);
- hdy_init ();
-
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
"win.new-window", new_window_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (app),
@@ -389,14 +382,14 @@ kgx_application_startup (GApplication *app)
g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (settings_action));
self->provider = gtk_css_provider_new ();
- gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
- GTK_STYLE_PROVIDER (self->provider),
- /* Is this stupid? Yes
- * Does it fix vte using the wrong
- * priority for fallback styles? Yes*/
- GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
-
- style_manager = hdy_style_manager_get_default ();
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (self->provider),
+ /* Is this stupid? Yes
+ * Does it fix vte using the wrong
+ * priority for fallback styles? Yes*/
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
+
+ style_manager = adw_style_manager_get_default ();
g_signal_connect_swapped (style_manager, "notify::dark", G_CALLBACK (update_styles), self);
g_signal_connect_swapped (style_manager, "notify::high-contrast", G_CALLBACK (update_styles), self);
update_styles (self);
@@ -872,16 +865,16 @@ focus_activated (GSimpleAction *action,
gpointer data)
{
KgxApplication *self = KGX_APPLICATION (data);
- GtkWidget *window;
+ GtkRoot *root;
KgxPages *pages;
KgxTab *page;
page = kgx_application_lookup_page (self, g_variant_get_uint32 (parameter));
pages = kgx_tab_get_pages (page);
kgx_pages_focus_page (pages, page);
- window = gtk_widget_get_toplevel (GTK_WIDGET (pages));
+ root = gtk_widget_get_root (GTK_WIDGET (pages));
- gtk_window_present_with_time (GTK_WINDOW (window), GDK_CURRENT_TIME);
+ gtk_window_present_with_time (GTK_WINDOW (root), GDK_CURRENT_TIME);
}
diff --git a/src/kgx-application.h b/src/kgx-application.h
index 5b3162e..cfcf7e7 100644
--- a/src/kgx-application.h
+++ b/src/kgx-application.h
@@ -77,7 +77,7 @@ struct ProcessWatch {
struct _KgxApplication
{
/*< private >*/
- GtkApplication parent_instance;
+ AdwApplication parent_instance;
/*< public >*/
KgxTheme theme;
@@ -97,7 +97,7 @@ struct _KgxApplication
GtkCssProvider *provider;
};
-G_DECLARE_FINAL_TYPE (KgxApplication, kgx_application, KGX, APPLICATION, GtkApplication)
+G_DECLARE_FINAL_TYPE (KgxApplication, kgx_application, KGX, APPLICATION, AdwApplication)
void kgx_application_add_watch (KgxApplication *self,
diff --git a/src/kgx-close-dialog.c b/src/kgx-close-dialog.c
index 16f0359..375e181 100644
--- a/src/kgx-close-dialog.c
+++ b/src/kgx-close-dialog.c
@@ -30,7 +30,7 @@
#include "kgx-config.h"
#include "kgx-close-dialog.h"
#include "kgx-process.h"
-#include <handy.h>
+#include <adwaita.h>
GtkWidget *
kgx_close_dialog_new (KgxCloseDialogContext context,
@@ -65,13 +65,11 @@ kgx_close_dialog_new (KgxCloseDialogContext context,
KgxProcess *process = g_ptr_array_index (commands, i);
GtkWidget *row;
- row = g_object_new (HDY_TYPE_ACTION_ROW,
- "visible", TRUE,
- "can-focus", FALSE,
+ row = g_object_new (ADW_TYPE_ACTION_ROW,
"title", kgx_process_get_exec (process),
NULL);
- gtk_container_add (GTK_CONTAINER (list), row);
+ gtk_list_box_append (GTK_LIST_BOX (list), row);
}
return dialog;
diff --git a/src/kgx-close-dialog.ui b/src/kgx-close-dialog.ui
index 0f07381..7c9c501 100644
--- a/src/kgx-close-dialog.ui
+++ b/src/kgx-close-dialog.ui
@@ -1,13 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.20"/>
+ <requires lib="gtk" version="4.0"/>
<object class="GtkMessageDialog" id="dialog">
<property name="modal">True</property>
<child internal-child="message_area">
<object class="GtkBox">
<child>
<object class="GtkListBox" id="list">
- <property name="visible">True</property>
<property name="can-focus">False</property>
<property name="selection-mode">none</property>
<property name="width-request">300</property>
@@ -22,15 +21,12 @@
<child type="action">
<object class="GtkButton" id="button-cancel">
<property name="label" translatable="yes">_Cancel</property>
- <property name="visible">True</property>
- <property name="can-default">True</property>
<property name="use-underline">True</property>
</object>
</child>
<child type="action">
<object class="GtkButton" id="button-ok">
<property name="label" translatable="yes">C_lose</property>
- <property name="visible">True</property>
<property name="use-underline">True</property>
<style>
<class name="destructive-action"/>
diff --git a/src/kgx-pages.c b/src/kgx-pages.c
index da7db1e..930fc59 100644
--- a/src/kgx-pages.c
+++ b/src/kgx-pages.c
@@ -21,7 +21,7 @@
* @title: KgxPages
* @short_description: Container of #KgxTab s
*
- * The container of open #KgxTab (uses #HdyTabView internally)
+ * The container of open #KgxTab (uses #AdwTabView internally)
*/
#include <glib/gi18n.h>
@@ -69,11 +69,11 @@ struct _KgxPagesPrivate {
gboolean opaque;
gint64 scrollback_lines;
- HdyTabPage *action_page;
+ AdwTabPage *action_page;
};
-G_DEFINE_TYPE_WITH_PRIVATE (KgxPages, kgx_pages, GTK_TYPE_BIN)
+G_DEFINE_TYPE_WITH_PRIVATE (KgxPages, kgx_pages, ADW_TYPE_BIN)
enum {
@@ -134,7 +134,7 @@ kgx_pages_get_property (GObject *object,
switch (property_id) {
case PROP_TAB_COUNT:
- g_value_set_uint (value, hdy_tab_view_get_n_pages (HDY_TAB_VIEW (priv->view)));
+ g_value_set_uint (value, adw_tab_view_get_n_pages (ADW_TAB_VIEW (priv->view)));
break;
case PROP_TAB_VIEW:
g_value_set_object (value, priv->view);
@@ -260,7 +260,7 @@ size_changed (KgxTab *tab,
priv->last_cols = cols;
priv->last_rows = rows;
- if (gtk_window_is_maximized (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))))) {
+ if (gtk_window_is_maximized (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))))) {
// Don't show when maximised as it isn't very interesting
return;
}
@@ -281,17 +281,17 @@ static void
page_changed (GObject *object, GParamSpec *pspec, KgxPages *self)
{
KgxPagesPrivate *priv;
- HdyTabPage *page = NULL;
+ AdwTabPage *page = NULL;
KgxTab *tab;
priv = kgx_pages_get_instance_private (self);
- page = hdy_tab_view_get_selected_page (HDY_TAB_VIEW (priv->view));
+ page = adw_tab_view_get_selected_page (ADW_TAB_VIEW (priv->view));
if (!page) {
return;
}
- tab = KGX_TAB (hdy_tab_page_get_child (page));
+ tab = KGX_TAB (adw_tab_page_get_child (page));
g_clear_signal_handler (&priv->size_watcher, priv->active_page);
priv->size_watcher = g_signal_connect (tab,
@@ -339,12 +339,12 @@ died (KgxTab *page,
KgxPages *self)
{
KgxPagesPrivate *priv;
- HdyTabPage *tab_page;
+ AdwTabPage *tab_page;
gboolean close_on_quit;
int tab_count;
priv = kgx_pages_get_instance_private (self);
- tab_page = hdy_tab_view_get_page (HDY_TAB_VIEW (priv->view), GTK_WIDGET (page));
+ tab_page = adw_tab_view_get_page (ADW_TAB_VIEW (priv->view), GTK_WIDGET (page));
g_object_get (page, "close-on-quit", &close_on_quit, NULL);
@@ -358,7 +358,7 @@ died (KgxTab *page,
return;
}
- hdy_tab_view_close_page (HDY_TAB_VIEW (priv->view), tab_page);
+ adw_tab_view_close_page (ADW_TAB_VIEW (priv->view), tab_page);
}
@@ -372,16 +372,16 @@ zoom (KgxTab *tab,
static void
-page_attached (HdyTabView *view,
- HdyTabPage *page,
+page_attached (AdwTabView *view,
+ AdwTabPage *page,
int position,
KgxPages *self)
{
KgxTab *tab;
- g_return_if_fail (HDY_IS_TAB_PAGE (page));
+ g_return_if_fail (ADW_IS_TAB_PAGE (page));
- tab = KGX_TAB (hdy_tab_page_get_child (page));
+ tab = KGX_TAB (adw_tab_page_get_child (page));
g_object_connect (tab,
"signal::died", G_CALLBACK (died), self,
@@ -393,18 +393,18 @@ page_attached (HdyTabView *view,
static void
-page_detached (HdyTabView *view,
- HdyTabPage *page,
+page_detached (AdwTabView *view,
+ AdwTabPage *page,
int position,
KgxPages *self)
{
KgxTab *tab;
KgxPagesPrivate *priv;
- GtkWidget *toplevel;
+ GtkRoot *root;
- g_return_if_fail (HDY_IS_TAB_PAGE (page));
+ g_return_if_fail (ADW_IS_TAB_PAGE (page));
- tab = KGX_TAB (hdy_tab_page_get_child (page));
+ tab = KGX_TAB (adw_tab_page_get_child (page));
priv = kgx_pages_get_instance_private (self);
@@ -412,12 +412,12 @@ page_detached (HdyTabView *view,
g_signal_handlers_disconnect_by_data (tab, self);
- if (hdy_tab_view_get_n_pages (HDY_TAB_VIEW (priv->view)) == 0) {
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+ if (adw_tab_view_get_n_pages (ADW_TAB_VIEW (priv->view)) == 0) {
+ root = gtk_widget_get_root (GTK_WIDGET (self));
- if (GTK_IS_WINDOW (toplevel)) {
+ if (GTK_IS_WINDOW (root)) {
/* Not a massive fan, would prefer it if window observed pages is empty */
- gtk_window_close (GTK_WINDOW (toplevel));
+ gtk_window_close (GTK_WINDOW (root));
}
priv->active_page = NULL;
@@ -426,8 +426,8 @@ page_detached (HdyTabView *view,
}
-static HdyTabView *
-create_window (HdyTabView *view,
+static AdwTabView *
+create_window (AdwTabView *view,
KgxPages *self)
{
/* Perhaps this should be handled via KgxWindow? */
@@ -438,7 +438,7 @@ create_window (HdyTabView *view,
KgxPagesPrivate *priv;
int width, height;
- window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self)));
+ window = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)));
app = gtk_window_get_application (window);
kgx_window_get_size (KGX_WINDOW (window), &width, &height);
@@ -452,49 +452,48 @@ create_window (HdyTabView *view,
new_pages = kgx_window_get_pages (new_window);
priv = kgx_pages_get_instance_private (new_pages);
- gtk_window_set_position (GTK_WINDOW (new_window), GTK_WIN_POS_MOUSE);
gtk_window_present (GTK_WINDOW (new_window));
- return HDY_TAB_VIEW (priv->view);
+ return ADW_TAB_VIEW (priv->view);
}
static void
close_response (GtkWidget *dlg,
int response,
- HdyTabPage *page)
+ AdwTabPage *page)
{
- KgxTab *tab = KGX_TAB (hdy_tab_page_get_child (page));
+ KgxTab *tab = KGX_TAB (adw_tab_page_get_child (page));
KgxPages *self = kgx_tab_get_pages (tab);
KgxPagesPrivate *priv = kgx_pages_get_instance_private (self);
- gtk_widget_destroy (dlg);
+ gtk_window_destroy (GTK_WINDOW (dlg));
- hdy_tab_view_close_page_finish (HDY_TAB_VIEW (priv->view), page,
+ adw_tab_view_close_page_finish (ADW_TAB_VIEW (priv->view), page,
response == GTK_RESPONSE_OK);
}
static gboolean
-close_page (HdyTabView *view,
- HdyTabPage *page,
+close_page (AdwTabView *view,
+ AdwTabPage *page,
KgxPages *self)
{
GtkWidget *dlg;
g_autoptr (GPtrArray) children = NULL;
- GtkWidget *toplevel;
+ GtkRoot *root;
- children = kgx_tab_get_children (KGX_TAB (hdy_tab_page_get_child (page)));
+ children = kgx_tab_get_children (KGX_TAB (adw_tab_page_get_child (page)));
if (children->len < 1) {
return FALSE; // Aka no, I don’t want to block closing
}
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
+ root = gtk_widget_get_root (GTK_WIDGET (self));
dlg = kgx_close_dialog_new (KGX_CONTEXT_TAB, children);
- gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (toplevel));
+ gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (root));
g_signal_connect (dlg, "response", G_CALLBACK (close_response), page);
@@ -505,8 +504,8 @@ close_page (HdyTabView *view,
static void
-setup_menu (HdyTabView *view,
- HdyTabPage *page,
+setup_menu (AdwTabView *view,
+ AdwTabPage *page,
KgxPages *self)
{
KgxPagesPrivate *priv = kgx_pages_get_instance_private (self);
@@ -557,13 +556,13 @@ kgx_pages_class_init (KgxPagesClass *klass)
/**
* KgxPages:tab-view:
*
- * The #HdyTabView
+ * The #AdwTabView
*
* Stability: Private
*/
pspecs[PROP_TAB_VIEW] =
g_param_spec_object ("tab-view", "Tab View", "The tab view",
- HDY_TYPE_TAB_VIEW,
+ ADW_TYPE_TAB_VIEW,
G_PARAM_READABLE);
/**
@@ -720,6 +719,14 @@ kgx_pages_init (KgxPages *self)
priv->opaque = FALSE;
gtk_widget_init_template (GTK_WIDGET (self));
+
+ adw_tab_view_remove_shortcuts (ADW_TAB_VIEW (priv->view),
+ ADW_TAB_VIEW_SHORTCUT_CONTROL_HOME |
+ ADW_TAB_VIEW_SHORTCUT_CONTROL_END |
+ ADW_TAB_VIEW_SHORTCUT_CONTROL_SHIFT_PAGE_UP |
+ ADW_TAB_VIEW_SHORTCUT_CONTROL_SHIFT_PAGE_DOWN |
+ ADW_TAB_VIEW_SHORTCUT_CONTROL_SHIFT_HOME |
+ ADW_TAB_VIEW_SHORTCUT_CONTROL_SHIFT_END);
}
@@ -728,7 +735,7 @@ kgx_pages_add_page (KgxPages *self,
KgxTab *tab)
{
KgxPagesPrivate *priv;
- HdyTabPage *page;
+ AdwTabPage *page;
g_return_if_fail (KGX_IS_PAGES (self));
@@ -736,7 +743,7 @@ kgx_pages_add_page (KgxPages *self,
kgx_tab_set_initial_title (tab, priv->title, priv->path);
- page = hdy_tab_view_add_page (HDY_TAB_VIEW (priv->view), GTK_WIDGET (tab), NULL);
+ page = adw_tab_view_add_page (ADW_TAB_VIEW (priv->view), GTK_WIDGET (tab), NULL);
g_object_bind_property (tab, "tab-title", page, "title", G_BINDING_SYNC_CREATE);
g_object_bind_property (tab, "tab-tooltip", page, "tooltip", G_BINDING_SYNC_CREATE);
g_object_bind_property (tab, "needs-attention", page, "needs-attention", G_BINDING_SYNC_CREATE);
@@ -750,7 +757,7 @@ kgx_pages_remove_page (KgxPages *self,
KgxTab *page)
{
KgxPagesPrivate *priv;
- HdyTabPage *tab_page;
+ AdwTabPage *tab_page;
g_return_if_fail (KGX_IS_PAGES (self));
@@ -758,15 +765,15 @@ kgx_pages_remove_page (KgxPages *self,
if (!page)
{
- tab_page = hdy_tab_view_get_selected_page (HDY_TAB_VIEW (priv->view));
- hdy_tab_view_close_page (HDY_TAB_VIEW (priv->view), tab_page);
+ tab_page = adw_tab_view_get_selected_page (ADW_TAB_VIEW (priv->view));
+ adw_tab_view_close_page (ADW_TAB_VIEW (priv->view), tab_page);
return;
}
g_return_if_fail (KGX_IS_TAB (page));
- tab_page = hdy_tab_view_get_page (HDY_TAB_VIEW (priv->view), GTK_WIDGET (page));
- hdy_tab_view_close_page (HDY_TAB_VIEW (priv->view), tab_page);
+ tab_page = adw_tab_view_get_page (ADW_TAB_VIEW (priv->view), GTK_WIDGET (page));
+ adw_tab_view_close_page (ADW_TAB_VIEW (priv->view), tab_page);
}
@@ -782,19 +789,19 @@ kgx_pages_focus_page (KgxPages *self,
KgxTab *page)
{
KgxPagesPrivate *priv;
- HdyTabPage *index;
+ AdwTabPage *index;
g_return_if_fail (KGX_IS_PAGES (self));
g_return_if_fail (KGX_IS_TAB (page));
priv = kgx_pages_get_instance_private (self);
- index = hdy_tab_view_get_page (HDY_TAB_VIEW (priv->view),
+ index = adw_tab_view_get_page (ADW_TAB_VIEW (priv->view),
GTK_WIDGET (page));
g_return_if_fail (index != NULL);
- hdy_tab_view_set_selected_page (HDY_TAB_VIEW (priv->view), index);
+ adw_tab_view_set_selected_page (ADW_TAB_VIEW (priv->view), index);
gtk_widget_grab_focus (GTK_WIDGET (page));
}
@@ -834,7 +841,7 @@ kgx_pages_count (KgxPages *self)
priv = kgx_pages_get_instance_private (self);
- return hdy_tab_view_get_n_pages (HDY_TAB_VIEW (priv->view));
+ return adw_tab_view_get_n_pages (ADW_TAB_VIEW (priv->view));
}
@@ -860,13 +867,13 @@ kgx_pages_get_children (KgxPages *self)
children = g_ptr_array_new_full (10, (GDestroyNotify) kgx_process_unref);
- n = hdy_tab_view_get_n_pages (HDY_TAB_VIEW (priv->view));
+ n = adw_tab_view_get_n_pages (ADW_TAB_VIEW (priv->view));
for (guint i = 0; i < n; i++) {
- HdyTabPage *page = hdy_tab_view_get_nth_page (HDY_TAB_VIEW (priv->view), i);
+ AdwTabPage *page = adw_tab_view_get_nth_page (ADW_TAB_VIEW (priv->view), i);
g_autoptr (GPtrArray) page_children = NULL;
- page_children = kgx_tab_get_children (KGX_TAB (hdy_tab_page_get_child (page)));
+ page_children = kgx_tab_get_children (KGX_TAB (adw_tab_page_get_child (page)));
for (int j = 0; j < page_children->len; j++) {
g_ptr_array_add (children, g_ptr_array_steal_index (page_children, j));
@@ -879,44 +886,11 @@ kgx_pages_get_children (KgxPages *self)
}
-void
-kgx_pages_set_shortcut_widget (KgxPages *self,
- GtkWidget *widget)
-{
- KgxPagesPrivate *priv;
-
- g_return_if_fail (KGX_IS_PAGES (self));
- g_return_if_fail (GTK_IS_WIDGET (widget) || widget == NULL);
-
- priv = kgx_pages_get_instance_private (self);
-
- hdy_tab_view_set_shortcut_widget (HDY_TAB_VIEW (priv->view), widget);
-}
-
-
-gboolean
-kgx_pages_key_press_event (KgxPages *self,
- GdkEvent *event)
-{
- KgxPagesPrivate *priv;
-
- g_return_val_if_fail (KGX_IS_PAGES (self), GDK_EVENT_PROPAGATE);
- g_return_val_if_fail (event != NULL, GDK_EVENT_PROPAGATE);
-
- priv = kgx_pages_get_instance_private (self);
-
- if (!priv->active_page)
- return GDK_EVENT_PROPAGATE;
-
- return kgx_tab_key_press_event (priv->active_page, event);
-}
-
-
void
kgx_pages_close_page (KgxPages *self)
{
KgxPagesPrivate *priv;
- HdyTabPage *page;
+ AdwTabPage *page;
g_return_if_fail (KGX_IS_PAGES (self));
@@ -924,9 +898,9 @@ kgx_pages_close_page (KgxPages *self)
page = priv->action_page;
if (!page)
- page = hdy_tab_view_get_selected_page (HDY_TAB_VIEW (priv->view));
+ page = adw_tab_view_get_selected_page (ADW_TAB_VIEW (priv->view));
- hdy_tab_view_close_page (HDY_TAB_VIEW (priv->view), page);
+ adw_tab_view_close_page (ADW_TAB_VIEW (priv->view), page);
}
@@ -934,8 +908,8 @@ void
kgx_pages_detach_page (KgxPages *self)
{
KgxPagesPrivate *priv;
- HdyTabPage *page;
- HdyTabView *new_view;
+ AdwTabPage *page;
+ AdwTabView *new_view;
g_return_if_fail (KGX_IS_PAGES (self));
@@ -943,8 +917,8 @@ kgx_pages_detach_page (KgxPages *self)
page = priv->action_page;
if (!page)
- page = hdy_tab_view_get_selected_page (HDY_TAB_VIEW (priv->view));
+ page = adw_tab_view_get_selected_page (ADW_TAB_VIEW (priv->view));
- new_view = create_window (HDY_TAB_VIEW (priv->view), self);
- hdy_tab_view_transfer_page (HDY_TAB_VIEW (priv->view), page, new_view, 0);
+ new_view = create_window (ADW_TAB_VIEW (priv->view), self);
+ adw_tab_view_transfer_page (ADW_TAB_VIEW (priv->view), page, new_view, 0);
}
diff --git a/src/kgx-pages.h b/src/kgx-pages.h
index 9a03c77..11b58b0 100644
--- a/src/kgx-pages.h
+++ b/src/kgx-pages.h
@@ -19,6 +19,7 @@
#pragma once
#include <gtk/gtk.h>
+#include <adwaita.h>
#include "kgx-tab.h"
@@ -32,13 +33,13 @@ G_BEGIN_DECLS
struct _KgxPagesClass
{
/*< private >*/
- GtkBinClass parent;
+ AdwBinClass parent;
/*< public >*/
};
-G_DECLARE_DERIVABLE_TYPE (KgxPages, kgx_pages, KGX, PAGES, GtkBin)
+G_DECLARE_DERIVABLE_TYPE (KgxPages, kgx_pages, KGX, PAGES, AdwBin)
void kgx_pages_add_page (KgxPages *self,
@@ -50,10 +51,6 @@ GPtrArray *kgx_pages_get_children (KgxPages *self);
void kgx_pages_focus_page (KgxPages *self,
KgxTab *page);
KgxStatus kgx_pages_current_status (KgxPages *self);
-void kgx_pages_set_shortcut_widget (KgxPages *self,
- GtkWidget *widget);
-gboolean kgx_pages_key_press_event (KgxPages *self,
- GdkEvent *event);
void kgx_pages_close_page (KgxPages *self);
void kgx_pages_detach_page (KgxPages *self);
diff --git a/src/kgx-pages.ui b/src/kgx-pages.ui
index 2023914..591dcf2 100644
--- a/src/kgx-pages.ui
+++ b/src/kgx-pages.ui
@@ -1,14 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.20"/>
- <template class="KgxPages" parent="GtkBin">
- <property name="visible">True</property>
- <child>
+ <requires lib="gtk" version="4.0"/>
+ <template class="KgxPages" parent="AdwBin">
+ <property name="child">
<object class="GtkOverlay">
- <property name="visible">True</property>
<child>
- <object class="HdyTabView" id="view">
- <property name="visible">True</property>
+ <object class="AdwTabView" id="view">
<property name="menu-model">tab-menu</property>
<property name="default-icon">view_default_icon</property>
<signal name="notify::selected-page" handler="page_changed" swapped="no"/>
@@ -21,25 +18,23 @@
</child>
<child type="overlay">
<object class="GtkRevealer" id="status_revealer">
- <property name="visible">False</property>
<property name="halign">end</property>
<property name="valign">end</property>
<property name="transition-type">crossfade</property>
<signal name="notify::child-revealed" handler="check_revealer" swapped="no"/>
- <child>
+ <property name="child">
<object class="GtkLabel" id="status">
- <property name="visible">True</property>
<property name="label">WxH</property>
<style>
<class name="floating-bar"/>
<class name="numeric"/>
</style>
</object>
- </child>
+ </property>
</object>
</child>
</object>
- </child>
+ </property>
</template>
<menu id="tab-menu">
<section>
diff --git a/src/kgx-simple-tab.ui b/src/kgx-simple-tab.ui
index bd22edf..e5bc986 100644
--- a/src/kgx-simple-tab.ui
+++ b/src/kgx-simple-tab.ui
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.20"/>
+ <requires lib="gtk" version="4.0"/>
<template class="KgxSimpleTab" parent="KgxTab">
- <property name="visible">1</property>
<child type="content">
<object class="GtkScrolledWindow">
- <property name="visible">1</property>
<property name="vexpand">1</property>
<property name="propagate-natural-width">1</property>
<property name="propagate-natural-height">1</property>
@@ -13,13 +11,13 @@
<style>
<class name="terminal"/>
</style>
- <child>
+ <property name="child">
<object class="KgxTerminal" id="terminal">
- <property name="visible">True</property>
+ <property name="vexpand">True</property>
<property name="allow-hyperlink">True</property>
<signal name="notify::path" handler="path_changed" swapped="no"/>
</object>
- </child>
+ </property>
</object>
</child>
</template>
diff --git a/src/kgx-tab-button.c b/src/kgx-tab-button.c
index 6891253..232ffec 100644
--- a/src/kgx-tab-button.c
+++ b/src/kgx-tab-button.c
@@ -18,12 +18,12 @@
*/
/**
- * SECTION:hdy-tab-button
- * @short_description: A button that displays the number of #HdyTabView pages
+ * SECTION:kgx-tab-button
+ * @short_description: A button that displays the number of #AdwTabView pages
* @title: KgxTabButton
*
* The #KgxTabButton widget is a #GtkButton subclass that displays the number
- * of pages in a given #HdyTabView.
+ * of pages in a given #AdwTabView.
*
* It can be used to open a tab switcher view in a mobile UI.
*
@@ -50,7 +50,7 @@ struct _KgxTabButton {
GtkLabel *label;
GtkImage *icon;
- HdyTabView *view;
+ AdwTabView *view;
};
@@ -107,7 +107,7 @@ update_icon (KgxTabButton *self)
GtkStyleContext *context;
if (self->view) {
- guint n_pages = hdy_tab_view_get_n_pages (self->view);
+ guint n_pages = adw_tab_view_get_n_pages (self->view);
small_label = n_pages >= 10;
@@ -129,7 +129,7 @@ update_icon (KgxTabButton *self)
gtk_widget_set_visible (GTK_WIDGET (self->label), display_label);
gtk_label_set_text (self->label, label_text);
- gtk_image_set_from_icon_name (self->icon, icon_name, GTK_ICON_SIZE_BUTTON);
+ gtk_image_set_from_icon_name (self->icon, icon_name);
}
@@ -193,13 +193,13 @@ kgx_tab_button_class_init (KgxTabButtonClass *klass)
/**
* KgxTabButton:view:
*
- * The #HdyTabView the tab button displays.
+ * The #AdwTabView the tab button displays.
*/
pspecs[PROP_VIEW] =
g_param_spec_object ("view",
"View",
"The view the tab button displays.",
- HDY_TYPE_TAB_VIEW,
+ ADW_TYPE_TAB_VIEW,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
@@ -248,11 +248,11 @@ kgx_tab_button_new (void)
* kgx_tab_button_get_view:
* @self: a #KgxTabButton
*
- * Gets the #HdyTabView @self displays.
+ * Gets the #AdwTabView @self displays.
*
- * Returns: (transfer none) (nullable): the #HdyTabView @self displays
+ * Returns: (transfer none) (nullable): the #AdwTabView @self displays
*/
-HdyTabView *
+AdwTabView *
kgx_tab_button_get_view (KgxTabButton *self)
{
g_return_val_if_fail (KGX_IS_TAB_BUTTON (self), NULL);
@@ -264,16 +264,16 @@ kgx_tab_button_get_view (KgxTabButton *self)
/**
* kgx_tab_button_set_view:
* @self: a #KgxTabButton
- * @view: (nullable): a #HdyTabView
+ * @view: (nullable): a #AdwTabView
*
- * Sets the #HdyTabView @self displays.
+ * Sets the #AdwTabView @self displays.
*/
void
kgx_tab_button_set_view (KgxTabButton *self,
- HdyTabView *view)
+ AdwTabView *view)
{
g_return_if_fail (KGX_IS_TAB_BUTTON (self));
- g_return_if_fail (view == NULL || HDY_IS_TAB_VIEW (view));
+ g_return_if_fail (view == NULL || ADW_IS_TAB_VIEW (view));
if (self->view == view) {
return;
diff --git a/src/kgx-tab-button.h b/src/kgx-tab-button.h
index 7d157e2..b2d34bf 100644
--- a/src/kgx-tab-button.h
+++ b/src/kgx-tab-button.h
@@ -18,7 +18,7 @@
#pragma once
-#include <handy.h>
+#include <adwaita.h>
G_BEGIN_DECLS
@@ -28,8 +28,8 @@ G_DECLARE_FINAL_TYPE (KgxTabButton, kgx_tab_button, KGX, TAB_BUTTON, GtkButton)
GtkWidget *kgx_tab_button_new (void);
-HdyTabView *kgx_tab_button_get_view (KgxTabButton *self);
+AdwTabView *kgx_tab_button_get_view (KgxTabButton *self);
void kgx_tab_button_set_view (KgxTabButton *self,
- HdyTabView *view);
+ AdwTabView *view);
G_END_DECLS
diff --git a/src/kgx-tab-button.ui b/src/kgx-tab-button.ui
index 4bd298e..359c298 100644
--- a/src/kgx-tab-button.ui
+++ b/src/kgx-tab-button.ui
@@ -1,22 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.24"/>
+ <requires lib="gtk" version="4.0"/>
<template class="KgxTabButton" parent="GtkButton">
<property name="tooltip_text" translatable="yes">View Open Tabs</property>
<style>
<class name="tab-button"/>
+ <class name="image-button"/>
</style>
- <child>
+ <property name="child">
<object class="GtkOverlay">
- <property name="visible">True</property>
<child>
- <object class="GtkImage" id="icon">
- <property name="visible">True</property>
- </object>
+ <object class="GtkImage" id="icon"/>
</child>
<child type="overlay">
<object class="GtkLabel" id="label">
- <property name="visible">True</property>
<property name="halign">center</property>
<property name="justify">center</property>
<property name="width-chars">2</property>
@@ -24,11 +21,8 @@
<attribute name="font-features" value="tnum=1"/>
</attributes>
</object>
- <packing>
- <property name="pass_through">True</property>
- </packing>
</child>
</object>
- </child>
+ </property>
</template>
</interface>
diff --git a/src/kgx-tab-switcher-row.c b/src/kgx-tab-switcher-row.c
index 8ba6ba0..fc243a5 100644
--- a/src/kgx-tab-switcher-row.c
+++ b/src/kgx-tab-switcher-row.c
@@ -32,8 +32,8 @@ struct _KgxTabSwitcherRow {
GtkImage *indicator_icon;
GtkWidget *close_btn;
- HdyTabPage *page;
- HdyTabView *view;
+ AdwTabPage *page;
+ AdwTabView *view;
};
@@ -68,22 +68,22 @@ static void
update_pinned (KgxTabSwitcherRow *self)
{
set_style_class (GTK_WIDGET (self), "pinned",
- hdy_tab_page_get_pinned (self->page));
+ adw_tab_page_get_pinned (self->page));
}
static void
update_icon (KgxTabSwitcherRow *self)
{
- GIcon *gicon = hdy_tab_page_get_icon (self->page);
- gboolean loading = hdy_tab_page_get_loading (self->page);
+ GIcon *gicon = adw_tab_page_get_icon (self->page);
+ gboolean loading = adw_tab_page_get_loading (self->page);
const char *name = loading ? "spinner" : "icon";
if (!gicon) {
- gicon = hdy_tab_view_get_default_icon (self->view);
+ gicon = adw_tab_view_get_default_icon (self->view);
}
- gtk_image_set_from_gicon (self->icon, gicon, GTK_ICON_SIZE_BUTTON);
+ gtk_image_set_from_gicon (self->icon, gicon);
gtk_stack_set_visible_child_name (self->icon_stack, name);
}
@@ -91,7 +91,7 @@ update_icon (KgxTabSwitcherRow *self)
static void
update_spinner (KgxTabSwitcherRow *self)
{
- gboolean loading = self->page && hdy_tab_page_get_loading (self->page);
+ gboolean loading = self->page && adw_tab_page_get_loading (self->page);
gboolean mapped = gtk_widget_get_mapped (GTK_WIDGET (self));
/* Don't use CPU when not needed */
@@ -109,17 +109,17 @@ update_loading (KgxTabSwitcherRow *self)
update_icon (self);
update_spinner (self);
set_style_class (GTK_WIDGET (self), "loading",
- hdy_tab_page_get_loading (self->page));
+ adw_tab_page_get_loading (self->page));
}
static void
update_indicator (KgxTabSwitcherRow *self)
{
- GIcon *indicator = hdy_tab_page_get_indicator_icon (self->page);
- gboolean activatable = hdy_tab_page_get_indicator_activatable (self->page);
+ GIcon *indicator = adw_tab_page_get_indicator_icon (self->page);
+ gboolean activatable = adw_tab_page_get_indicator_activatable (self->page);
- gtk_image_set_from_gicon (self->indicator_icon, indicator, GTK_ICON_SIZE_BUTTON);
+ gtk_image_set_from_gicon (self->indicator_icon, indicator);
gtk_widget_set_visible (GTK_WIDGET (self->indicator_btn), indicator != NULL);
gtk_widget_set_sensitive (GTK_WIDGET (self->indicator_btn), activatable);
}
@@ -129,7 +129,7 @@ static void
update_needs_attention (KgxTabSwitcherRow *self)
{
set_style_class (GTK_WIDGET (self), "needs-attention",
- hdy_tab_page_get_needs_attention (self->page));
+ adw_tab_page_get_needs_attention (self->page));
}
@@ -151,7 +151,18 @@ close_clicked_cb (KgxTabSwitcherRow *self)
return;
}
- hdy_tab_view_close_page (self->view, self->page);
+ adw_tab_view_close_page (self->view, self->page);
+}
+
+
+static void
+destroy_cb (KgxTabSwitcherRow *self)
+{
+ GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (self));
+
+ g_assert (GTK_IS_LIST_BOX (parent));
+
+ gtk_list_box_remove (GTK_LIST_BOX (parent), GTK_WIDGET (self));
}
@@ -280,14 +291,14 @@ kgx_tab_switcher_row_class_init (KgxTabSwitcherRowClass *klass)
g_param_spec_object ("page",
"Page",
"The page the row displays.",
- HDY_TYPE_TAB_PAGE,
+ ADW_TYPE_TAB_PAGE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
pspecs[PROP_VIEW] =
g_param_spec_object ("view",
"View",
"The view containing the page.",
- HDY_TYPE_TAB_VIEW,
+ ADW_TYPE_TAB_VIEW,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, LAST_PROP, pspecs);
@@ -317,11 +328,11 @@ kgx_tab_switcher_row_init (KgxTabSwitcherRow *self)
GtkWidget *
-kgx_tab_switcher_row_new (HdyTabPage *page,
- HdyTabView *view)
+kgx_tab_switcher_row_new (AdwTabPage *page,
+ AdwTabView *view)
{
- g_return_val_if_fail (HDY_IS_TAB_PAGE (page), NULL);
- g_return_val_if_fail (HDY_IS_TAB_VIEW (view), NULL);
+ g_return_val_if_fail (ADW_IS_TAB_PAGE (page), NULL);
+ g_return_val_if_fail (ADW_IS_TAB_VIEW (view), NULL);
return g_object_new (KGX_TYPE_TAB_SWITCHER_ROW,
"page", page,
@@ -330,7 +341,7 @@ kgx_tab_switcher_row_new (HdyTabPage *page,
}
-HdyTabPage *
+AdwTabPage *
kgx_tab_switcher_row_get_page (KgxTabSwitcherRow *self)
{
g_return_val_if_fail (KGX_IS_TAB_SWITCHER_ROW (self), NULL);
@@ -359,7 +370,7 @@ kgx_tab_switcher_row_animate_close (KgxTabSwitcherRow *self)
self->page = NULL;
g_signal_connect_swapped (self->revealer, "notify::child-revealed",
- G_CALLBACK (gtk_widget_destroy), self);
+ G_CALLBACK (destroy_cb), self);
gtk_revealer_set_reveal_child (self->revealer, FALSE);
}
diff --git a/src/kgx-tab-switcher-row.h b/src/kgx-tab-switcher-row.h
index eb3e487..dee0238 100644
--- a/src/kgx-tab-switcher-row.h
+++ b/src/kgx-tab-switcher-row.h
@@ -18,7 +18,7 @@
#pragma once
-#include <handy.h>
+#include <adwaita.h>
G_BEGIN_DECLS
@@ -26,10 +26,10 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (KgxTabSwitcherRow, kgx_tab_switcher_row, KGX, TAB_SWITCHER_ROW, GtkListBoxRow)
-GtkWidget *kgx_tab_switcher_row_new (HdyTabPage *page,
- HdyTabView *view);
+GtkWidget *kgx_tab_switcher_row_new (AdwTabPage *page,
+ AdwTabView *view);
-HdyTabPage *kgx_tab_switcher_row_get_page (KgxTabSwitcherRow *self);
+AdwTabPage *kgx_tab_switcher_row_get_page (KgxTabSwitcherRow *self);
gboolean kgx_tab_switcher_row_is_animating (KgxTabSwitcherRow *self);
diff --git a/src/kgx-tab-switcher-row.ui b/src/kgx-tab-switcher-row.ui
index 47604bf..41c0668 100644
--- a/src/kgx-tab-switcher-row.ui
+++ b/src/kgx-tab-switcher-row.ui
@@ -1,46 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.24"/>
+ <requires lib="gtk" version="4.0"/>
<template class="KgxTabSwitcherRow" parent="GtkListBoxRow">
- <child>
+ <property name="child">
<object class="GtkRevealer" id="revealer">
- <property name="visible">True</property>
<property name="transition-type">slide-up</property>
- <child>
+ <property name="child">
<object class="GtkBox">
- <property name="visible">True</property>
<property name="hexpand">False</property>
<style>
<class name="content"/>
</style>
<child>
<object class="GtkStack" id="icon_stack">
- <property name="visible">True</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="valign">center</property>
<child>
- <object class="GtkImage" id="icon">
- <property name="visible">True</property>
- <property name="pixel-size">16</property>
- </object>
- <packing>
+ <object class="GtkStackPage">
<property name="name">icon</property>
- </packing>
+ <property name="child">
+ <object class="GtkImage" id="icon">
+ <property name="pixel-size">16</property>
+ </object>
+ </property>
+ </object>
</child>
<child>
- <object class="GtkSpinner" id="spinner">
- <property name="visible">True</property>
- </object>
- <packing>
+ <object class="GtkStackPage">
<property name="name">spinner</property>
- </packing>
+ <property name="child">
+ <object class="GtkSpinner" id="spinner"/>
+ </property>
+ </object>
</child>
</object>
</child>
<child>
<object class="GtkLabel" id="title">
- <property name="visible">True</property>
<property name="margin-start">4</property>
<property name="hexpand">True</property>
<property name="valign">center</property>
@@ -50,43 +47,36 @@
</child>
<child>
<object class="GtkButton" id="indicator_btn">
- <property name="visible">False</property>
<property name="can-focus">False</property>
<property name="valign">center</property>
<signal name="clicked" handler="indicator_clicked_cb" swapped="true" />
<style>
<class name="flat"/>
+ <class name="image-button"/>
<class name="indicator-btn"/>
</style>
- <child>
+ <property name="child">
<object class="GtkImage" id="indicator_icon">
- <property name="visible">True</property>
<property name="pixel-size">16</property>
</object>
- </child>
+ </property>
</object>
</child>
<child>
<object class="GtkButton" id="close_btn">
- <property name="visible">True</property>
<property name="can-focus">False</property>
<property name="valign">center</property>
+ <property name="icon-name">window-close-symbolic</property>
<signal name="clicked" handler="close_clicked_cb" swapped="true" />
<style>
<class name="flat"/>
<class name="close-btn"/>
</style>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="icon-name">window-close-symbolic</property>
- </object>
- </child>
</object>
</child>
</object>
- </child>
+ </property>
</object>
- </child>
+ </property>
</template>
</interface>
diff --git a/src/kgx-tab-switcher.c b/src/kgx-tab-switcher.c
index fa94758..e1b0031 100644
--- a/src/kgx-tab-switcher.c
+++ b/src/kgx-tab-switcher.c
@@ -18,12 +18,12 @@
/**
* SECTION:kgx-tab-switcher
- * @short_description: A mobile tab switcher for HdyTabView
+ * @short_description: A mobile tab switcher for AdwTabView
* @title: KgxTabSwitcher
*
- * The #KgxTabSwitcher widget is a mobile tab switcher for HdyTabView. It's
+ * The #KgxTabSwitcher widget is a mobile tab switcher for AdwTabView. It's
* supposed to be used in conjunction with #KgxTabButton to open it, and a
- * #HdyTabBar to provide UI for larger screens.
+ * #AdwTabBar to provide UI for larger screens.
*/
#include "kgx-config.h"
@@ -32,26 +32,26 @@
struct _KgxTabSwitcher {
- GtkBin parent_instance;
+ GtkWidget parent_instance;
- HdyFlap *flap;
+ AdwFlap *flap;
GtkListBox *list;
GtkGesture *click_gesture;
GtkGesture *long_press_gesture;
- GtkMenu *context_menu;
- GtkPopover *touch_menu;
+ GtkPopover *context_menu;
- HdyTabView *view;
+ AdwTabView *view;
gboolean narrow;
};
-G_DEFINE_TYPE (KgxTabSwitcher, kgx_tab_switcher, GTK_TYPE_BIN)
+G_DEFINE_TYPE (KgxTabSwitcher, kgx_tab_switcher, GTK_TYPE_WIDGET)
enum {
PROP_0,
+ PROP_CHILD,
PROP_VIEW,
PROP_NARROW,
LAST_PROP
@@ -75,9 +75,9 @@ reset_setup_menu_cb (KgxTabSwitcher *self)
static void
-touch_menu_notify_visible_cb (KgxTabSwitcher *self)
+context_menu_notify_visible_cb (KgxTabSwitcher *self)
{
- if (!self->touch_menu || gtk_widget_get_visible (GTK_WIDGET (self->touch_menu))) {
+ if (!self->context_menu || gtk_widget_get_visible (GTK_WIDGET (self->context_menu))) {
return;
}
@@ -86,18 +86,14 @@ touch_menu_notify_visible_cb (KgxTabSwitcher *self)
static void
-destroy_cb (KgxTabSwitcher *self)
-{
- self->touch_menu = NULL;
-}
-
-
-static void
-do_touch_popup (KgxTabSwitcher *self,
- KgxTabSwitcherRow *row)
+do_popup (KgxTabSwitcher *self,
+ KgxTabSwitcherRow *row,
+ double x,
+ double y)
{
- GMenuModel *model = hdy_tab_view_get_menu_model (self->view);
- HdyTabPage *page = kgx_tab_switcher_row_get_page (row);
+ GMenuModel *model = adw_tab_view_get_menu_model (self->view);
+ AdwTabPage *page = kgx_tab_switcher_row_get_page (row);
+ GdkRectangle rect;
if (!G_IS_MENU_MODEL (model)) {
return;
@@ -105,97 +101,68 @@ do_touch_popup (KgxTabSwitcher *self,
g_signal_emit_by_name (self->view, "setup-menu", page);
- if (!self->touch_menu) {
- self->touch_menu = GTK_POPOVER (gtk_popover_new_from_model (GTK_WIDGET (row), model));
- gtk_popover_set_constrain_to (self->touch_menu, GTK_POPOVER_CONSTRAINT_WINDOW);
-
- g_signal_connect_object (self->touch_menu, "notify::visible",
- G_CALLBACK (touch_menu_notify_visible_cb), self,
- G_CONNECT_AFTER | G_CONNECT_SWAPPED);
-
- g_signal_connect_object (self->touch_menu, "destroy",
- G_CALLBACK (destroy_cb), self,
+ if (!self->context_menu) {
+ self->context_menu = GTK_POPOVER (gtk_popover_menu_new_from_model (model));
+ gtk_popover_set_position (self->context_menu, GTK_POS_BOTTOM);
+ gtk_popover_set_has_arrow (self->context_menu, FALSE);
+ gtk_widget_set_parent (GTK_WIDGET (self->context_menu) , GTK_WIDGET (self));
+
+ if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL) {
+ gtk_widget_set_halign (GTK_WIDGET (self->context_menu), GTK_ALIGN_END);
+ } else {
+ gtk_widget_set_halign (GTK_WIDGET (self->context_menu), GTK_ALIGN_START);
+ }
+
+ g_signal_connect_object (self->context_menu, "notify::visible",
+ G_CALLBACK (context_menu_notify_visible_cb), self,
G_CONNECT_AFTER | G_CONNECT_SWAPPED);
- } else {
- gtk_popover_set_relative_to (self->touch_menu, GTK_WIDGET (row));
}
- gtk_popover_popup (self->touch_menu);
-}
-
+ if (x >= 0 && y >= 0) {
+ graphene_rect_t bounds;
-static void
-popup_menu_detach (KgxTabSwitcher *self,
- GtkMenu *menu)
-{
- self->context_menu = NULL;
-}
+ g_assert (gtk_widget_compute_bounds (GTK_WIDGET (self->list),
+ GTK_WIDGET (self), &bounds));
+ rect.x = bounds.origin.x + x;
+ rect.y = bounds.origin.y + y;
+ } else {
+ graphene_rect_t bounds;
-static void
-popup_menu_deactivate_cb (KgxTabSwitcher *self)
-{
- g_idle_add (G_SOURCE_FUNC (reset_setup_menu_cb), self);
-}
-
+ g_assert (gtk_widget_compute_bounds (GTK_WIDGET (row),
+ GTK_WIDGET (self), &bounds));
-static void
-do_popup (KgxTabSwitcher *self,
- KgxTabSwitcherRow *row,
- GdkEvent *event)
-{
- GMenuModel *model = hdy_tab_view_get_menu_model (self->view);
- HdyTabPage *page = kgx_tab_switcher_row_get_page (row);
+ rect.x = bounds.origin.x;
+ rect.y = bounds.origin.y + bounds.size.height;
- if (!G_IS_MENU_MODEL (model)) {
- return;
+ if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL) {
+ rect.x += bounds.size.width;
+ }
}
- g_signal_emit_by_name (self->view, "setup-menu", page);
+ rect.width = 0;
+ rect.height = 0;
- if (!self->context_menu) {
- self->context_menu = GTK_MENU (gtk_menu_new_from_model (model));
- gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self->context_menu)),
- GTK_STYLE_CLASS_CONTEXT_MENU);
-
- g_signal_connect_object (self->context_menu,
- "deactivate",
- G_CALLBACK (popup_menu_deactivate_cb),
- self,
- G_CONNECT_SWAPPED);
+ gtk_popover_set_pointing_to (self->context_menu, &rect);
- gtk_menu_attach_to_widget (self->context_menu, GTK_WIDGET (self),
- (GtkMenuDetachFunc) popup_menu_detach);
- }
-
- if (event && gdk_event_triggers_context_menu (event)) {
- gtk_menu_popup_at_pointer (self->context_menu, event);
- } else {
- gtk_menu_popup_at_widget (self->context_menu,
- GTK_WIDGET (row),
- GDK_GRAVITY_SOUTH_WEST,
- GDK_GRAVITY_NORTH_WEST,
- event);
-
- gtk_menu_shell_select_first (GTK_MENU_SHELL (self->context_menu), FALSE);
- }
+ gtk_popover_popup (self->context_menu);
}
static void
reveal_flap_cb (KgxTabSwitcher *self)
{
- HdyTabPage *page;
+ AdwTabPage *page;
GtkWidget *child;
gtk_widget_set_sensitive (GTK_WIDGET (self->view),
- !hdy_flap_get_reveal_flap (self->flap));
+ !adw_flap_get_reveal_flap (self->flap));
- if (hdy_flap_get_reveal_flap (self->flap)) {
+ if (adw_flap_get_reveal_flap (self->flap)) {
gtk_widget_grab_focus (GTK_WIDGET (self->list));
} else {
- page = hdy_tab_view_get_selected_page (self->view);
- child = hdy_tab_page_get_child (page);
+ page = adw_tab_view_get_selected_page (self->view);
+ child = adw_tab_page_get_child (page);
gtk_widget_grab_focus (GTK_WIDGET (child));
}
@@ -222,7 +189,7 @@ static void
row_selected_cb (KgxTabSwitcher *self,
KgxTabSwitcherRow *row)
{
- HdyTabPage *page;
+ AdwTabPage *page;
if (!row) {
return;
@@ -235,7 +202,7 @@ row_selected_cb (KgxTabSwitcher *self,
}
page = kgx_tab_switcher_row_get_page (row);
- hdy_tab_view_set_selected_page (self->view, page);
+ adw_tab_view_set_selected_page (self->view, page);
}
@@ -280,7 +247,7 @@ pages_changed_cb (KgxTabSwitcher *self,
}
for (i = 0; i < added; i++) {
- g_autoptr (HdyTabPage) page = g_list_model_get_item (pages, position + i);
+ g_autoptr (AdwTabPage) page = g_list_model_get_item (pages, position + i);
GtkWidget *row = kgx_tab_switcher_row_new (page, self->view);
gtk_list_box_insert (self->list, row, position + i);
@@ -290,16 +257,16 @@ pages_changed_cb (KgxTabSwitcher *self,
static void
-notify_selected_page_cb (KgxTabSwitcher *self)
+selection_changed_cb (KgxTabSwitcher *self)
{
- HdyTabPage *page = NULL;
+ AdwTabPage *page = NULL;
if (self->view) {
- page = hdy_tab_view_get_selected_page (self->view);
+ page = adw_tab_view_get_selected_page (self->view);
}
if (page) {
- int index = hdy_tab_view_get_page_position (self->view, page);
+ int index = adw_tab_view_get_page_position (self->view, page);
KgxTabSwitcherRow *row = find_nth_alive_row (self, index);
gtk_list_box_select_row (self->list, GTK_LIST_BOX_ROW (row));
@@ -315,9 +282,10 @@ click_pressed_cb (KgxTabSwitcher *self,
double x,
double y)
{
- g_autoptr (GdkEvent) event = NULL;
+ GdkEventSequence *sequence;
+ GdkEvent *event;
GtkListBoxRow *row;
- HdyTabPage *page;
+ AdwTabPage *page;
guint button;
if (n_press > 1) {
@@ -334,20 +302,21 @@ click_pressed_cb (KgxTabSwitcher *self,
return;
}
- event = gtk_get_current_event ();
+ sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (self->click_gesture));
+ event = gtk_gesture_get_last_event (self->click_gesture, sequence);
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (self->click_gesture));
page = kgx_tab_switcher_row_get_page (KGX_TAB_SWITCHER_ROW (row));
if (event && gdk_event_triggers_context_menu (event)) {
gtk_gesture_set_state (self->click_gesture, GTK_EVENT_SEQUENCE_CLAIMED);
- do_popup (self, KGX_TAB_SWITCHER_ROW (row), event);
+ do_popup (self, KGX_TAB_SWITCHER_ROW (row), x, y);
return;
}
if (button == GDK_BUTTON_MIDDLE) {
gtk_gesture_set_state (self->click_gesture, GTK_EVENT_SEQUENCE_CLAIMED);
- hdy_tab_view_close_page (self->view, page);
+ adw_tab_view_close_page (self->view, page);
return;
}
@@ -369,12 +338,21 @@ long_press_cb (KgxTabSwitcher *self,
return;
}
- do_touch_popup (self, KGX_TAB_SWITCHER_ROW (row));
+ do_popup (self, KGX_TAB_SWITCHER_ROW (row), -1, -1);
gtk_gesture_set_state (self->long_press_gesture, GTK_EVENT_SEQUENCE_CLAIMED);
}
+static void
+popup_menu_cb (KgxTabSwitcher *self)
+{
+ GtkListBoxRow *row = gtk_list_box_get_selected_row (self->list);
+
+ do_popup (self, KGX_TAB_SWITCHER_ROW (row), -1, -1);
+}
+
+
static void
set_narrow (KgxTabSwitcher *self,
gboolean narrow)
@@ -400,8 +378,10 @@ kgx_tab_switcher_dispose (GObject *object)
kgx_tab_switcher_set_view (self, NULL);
- g_clear_object (&self->click_gesture);
- g_clear_object (&self->long_press_gesture);
+ g_clear_pointer ((GtkWidget **) &self->flap, gtk_widget_unparent);
+ g_clear_pointer ((GtkWidget **) &self->context_menu, gtk_widget_unparent);
+ self->click_gesture = NULL;
+ self->long_press_gesture = NULL;
G_OBJECT_CLASS (kgx_tab_switcher_parent_class)->dispose (object);
}
@@ -416,6 +396,9 @@ kgx_tab_switcher_get_property (GObject *object,
KgxTabSwitcher *self = KGX_TAB_SWITCHER (object);
switch (prop_id) {
+ case PROP_CHILD:
+ g_value_set_object (value, kgx_tab_switcher_get_child (self));
+ break;
case PROP_VIEW:
g_value_set_object (value, kgx_tab_switcher_get_view (self));
break;
@@ -437,6 +420,9 @@ kgx_tab_switcher_set_property (GObject *object,
KgxTabSwitcher *self = KGX_TAB_SWITCHER (object);
switch (prop_id) {
+ case PROP_CHILD:
+ kgx_tab_switcher_set_child (self, g_value_get_object (value));
+ break;
case PROP_VIEW:
kgx_tab_switcher_set_view (self, g_value_get_object (value));
break;
@@ -447,133 +433,91 @@ kgx_tab_switcher_set_property (GObject *object,
static void
-kgx_tab_switcher_destroy (GtkWidget *widget)
-{
- gtk_container_forall (GTK_CONTAINER (widget), (GtkCallback) gtk_widget_destroy, NULL);
-
- GTK_WIDGET_CLASS (kgx_tab_switcher_parent_class)->destroy (widget);
-}
-
-
-static gboolean
-kgx_tab_switcher_popup_menu (GtkWidget *widget)
+kgx_tab_switcher_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *min,
+ int *nat,
+ int *min_baseline,
+ int *nat_baseline)
{
KgxTabSwitcher *self = KGX_TAB_SWITCHER (widget);
- GtkListBoxRow *row = gtk_list_box_get_selected_row (self->list);
- if (row) {
- do_popup (self, KGX_TAB_SWITCHER_ROW (row), NULL);
-
- return GDK_EVENT_STOP;
- }
-
- return GDK_EVENT_PROPAGATE;
+ gtk_widget_measure (GTK_WIDGET (self->flap), orientation, for_size,
+ min, nat, min_baseline, nat_baseline);
}
static void
-kgx_tab_switcher_size_allocate (GtkWidget *widget,
- GtkAllocation *alloc)
+kgx_tab_switcher_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
{
KgxTabSwitcher *self = KGX_TAB_SWITCHER (widget);
- set_narrow (self, alloc->width < 400);
-
- GTK_WIDGET_CLASS (kgx_tab_switcher_parent_class)->size_allocate (widget, alloc);
-}
-
-
-static void
-kgx_tab_switcher_add (GtkContainer *container,
- GtkWidget *widget)
-{
- KgxTabSwitcher *self = KGX_TAB_SWITCHER (container);
-
- if (!self->flap) {
- GTK_CONTAINER_CLASS (kgx_tab_switcher_parent_class)->add (container, widget);
-
- return;
- }
-
- hdy_flap_set_content (self->flap, widget);
-}
+ set_narrow (self, width < 400);
-
-static void
-kgx_tab_switcher_remove (GtkContainer *container,
- GtkWidget *widget)
-{
- KgxTabSwitcher *self = KGX_TAB_SWITCHER (container);
-
- if (widget == GTK_WIDGET (self->flap)) {
- GTK_CONTAINER_CLASS (kgx_tab_switcher_parent_class)->remove (container, widget);
-
- return;
+ if (self->context_menu) {
+ gtk_popover_present (self->context_menu);
}
- hdy_flap_set_content (self->flap, NULL);
+ gtk_widget_allocate (GTK_WIDGET (self->flap), width, height, baseline, NULL);
}
static void
-kgx_tab_switcher_forall (GtkContainer *container,
- gboolean include_internals,
- GtkCallback callback,
- gpointer callback_data)
+kgx_tab_switcher_direction_changed (GtkWidget *widget,
+ GtkTextDirection previous_direction)
{
- KgxTabSwitcher *self = KGX_TAB_SWITCHER (container);
- GtkWidget *content;
-
- if (include_internals) {
- GTK_CONTAINER_CLASS (kgx_tab_switcher_parent_class)->forall (container,
- include_internals,
- callback,
- callback_data);
-
- return;
- }
+ KgxTabSwitcher *self = KGX_TAB_SWITCHER (widget);
- if (!self->flap) {
+ if (gtk_widget_get_direction (widget) == previous_direction) {
return;
}
- content = hdy_flap_get_content (self->flap);
-
- if (content) {
- callback (content, callback_data);
+ if (self->context_menu) {
+ if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL) {
+ gtk_widget_set_halign (GTK_WIDGET (self->context_menu), GTK_ALIGN_END);
+ } else {
+ gtk_widget_set_halign (GTK_WIDGET (self->context_menu), GTK_ALIGN_START);
+ }
}
}
+
static void
kgx_tab_switcher_class_init (KgxTabSwitcherClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
object_class->dispose = kgx_tab_switcher_dispose;
object_class->get_property = kgx_tab_switcher_get_property;
object_class->set_property = kgx_tab_switcher_set_property;
- widget_class->destroy = kgx_tab_switcher_destroy;
- widget_class->popup_menu = kgx_tab_switcher_popup_menu;
+ widget_class->measure = kgx_tab_switcher_measure;
widget_class->size_allocate = kgx_tab_switcher_size_allocate;
+ widget_class->direction_changed = kgx_tab_switcher_direction_changed;
- container_class->add = kgx_tab_switcher_add;
- container_class->remove = kgx_tab_switcher_remove;
- container_class->forall = kgx_tab_switcher_forall;
+ pspecs[PROP_CHILD] =
+ g_param_spec_object ("child",
+ "Child",
+ "The tab switcher child",
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
/**
* KgxTabSwitcher:view:
*
- * The #HdyTabView the tab switcher controls;
+ * The #AdwTabView the tab switcher controls;
*/
pspecs[PROP_VIEW] =
g_param_spec_object ("view",
"View",
"The view the tab switcher controls.",
- HDY_TYPE_TAB_VIEW,
+ ADW_TYPE_TAB_VIEW,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
pspecs[PROP_NARROW] =
@@ -605,6 +549,11 @@ kgx_tab_switcher_class_init (KgxTabSwitcherClass *klass)
gtk_widget_class_bind_template_callback (widget_class, new_tab_cb);
gtk_widget_class_bind_template_callback (widget_class, row_selected_cb);
gtk_widget_class_bind_template_callback (widget_class, row_activated_cb);
+
+ gtk_widget_class_install_action (widget_class, "menu.popup", NULL, (GtkWidgetActionActivateFunc)
popup_menu_cb);
+
+ gtk_widget_class_add_binding_action (widget_class, GDK_KEY_F10, GDK_SHIFT_MASK, "menu.popup", NULL);
+ gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Menu, 0, "menu.popup", NULL);
}
@@ -615,13 +564,15 @@ kgx_tab_switcher_init (KgxTabSwitcher *self)
gtk_widget_init_template (GTK_WIDGET (self));
- self->click_gesture = gtk_gesture_multi_press_new (GTK_WIDGET (self->list));
+ self->click_gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (self->click_gesture), 0);
g_signal_connect_swapped (self->click_gesture, "pressed", G_CALLBACK (click_pressed_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self->list), GTK_EVENT_CONTROLLER (self->click_gesture));
- self->long_press_gesture = gtk_gesture_long_press_new (GTK_WIDGET (self->list));
+ self->long_press_gesture = gtk_gesture_long_press_new ();
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (self->long_press_gesture), TRUE);
g_signal_connect_swapped (self->long_press_gesture, "pressed", G_CALLBACK (long_press_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self->list), GTK_EVENT_CONTROLLER (self->long_press_gesture));
}
@@ -639,15 +590,41 @@ kgx_tab_switcher_new (void)
}
+GtkWidget *
+kgx_tab_switcher_get_child (KgxTabSwitcher *self)
+{
+ g_return_val_if_fail (KGX_IS_TAB_SWITCHER (self), NULL);
+
+ return adw_flap_get_content (self->flap);
+}
+
+
+void
+kgx_tab_switcher_set_child (KgxTabSwitcher *self,
+ GtkWidget *child)
+{
+ g_return_if_fail (KGX_IS_TAB_SWITCHER (self));
+ g_return_if_fail (child == NULL || GTK_IS_WIDGET (child));
+
+ if (child == kgx_tab_switcher_get_child (self)) {
+ return;
+ }
+
+ adw_flap_set_content (self->flap, child);
+
+ g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_CHILD]);
+}
+
+
/**
* kgx_tab_switcher_get_view:
* @self: a #KgxTabSwitcher
*
- * Gets the #HdyTabView @self controls.
+ * Gets the #AdwTabView @self controls.
*
- * Returns: (transfer none) (nullable): the #HdyTabView @self controls
+ * Returns: (transfer none) (nullable): the #AdwTabView @self controls
*/
-HdyTabView *
+AdwTabView *
kgx_tab_switcher_get_view (KgxTabSwitcher *self)
{
g_return_val_if_fail (KGX_IS_TAB_SWITCHER (self), NULL);
@@ -659,43 +636,43 @@ kgx_tab_switcher_get_view (KgxTabSwitcher *self)
/**
* kgx_tab_switcher_set_view:
* @self: a #KgxTabSwitcher
- * @view: (nullable): a #HdyTabView
+ * @view: (nullable): a #AdwTabView
*
- * Sets the #HdyTabView @self controls.
+ * Sets the #AdwTabView @self controls.
*/
void
kgx_tab_switcher_set_view (KgxTabSwitcher *self,
- HdyTabView *view)
+ AdwTabView *view)
{
g_return_if_fail (KGX_IS_TAB_SWITCHER (self));
- g_return_if_fail (view == NULL || HDY_IS_TAB_VIEW (view));
+ g_return_if_fail (view == NULL || ADW_IS_TAB_VIEW (view));
if (self->view == view) {
return;
}
if (self->view) {
- GListModel *pages = hdy_tab_view_get_pages (self->view);
+ GtkSelectionModel *pages = adw_tab_view_get_pages (self->view);
- g_signal_handlers_disconnect_by_func (self->view, G_CALLBACK (notify_selected_page_cb), self);
+ g_signal_handlers_disconnect_by_func (pages, G_CALLBACK (selection_changed_cb), self);
g_signal_handlers_disconnect_by_func (pages, G_CALLBACK (pages_changed_cb), self);
}
g_set_object (&self->view, view);
if (self->view) {
- GListModel *pages = hdy_tab_view_get_pages (self->view);
+ GtkSelectionModel *pages = adw_tab_view_get_pages (self->view);
g_signal_connect_object (pages, "items-changed",
G_CALLBACK (pages_changed_cb), self,
G_CONNECT_SWAPPED);
- g_signal_connect_object (self->view, "notify::selected-page",
- G_CALLBACK (notify_selected_page_cb), self,
+ g_signal_connect_object (pages, "selection-changed",
+ G_CALLBACK (selection_changed_cb), self,
G_CONNECT_SWAPPED);
}
- notify_selected_page_cb (self);
+ selection_changed_cb (self);
g_object_notify_by_pspec (G_OBJECT (self), pspecs[PROP_VIEW]);
}
@@ -706,7 +683,7 @@ kgx_tab_switcher_open (KgxTabSwitcher *self)
{
g_return_if_fail (KGX_IS_TAB_SWITCHER (self));
- hdy_flap_set_reveal_flap (self->flap, TRUE);
+ adw_flap_set_reveal_flap (self->flap, TRUE);
}
@@ -715,7 +692,7 @@ kgx_tab_switcher_close (KgxTabSwitcher *self)
{
g_return_if_fail (KGX_IS_TAB_SWITCHER (self));
- hdy_flap_set_reveal_flap (self->flap, FALSE);
+ adw_flap_set_reveal_flap (self->flap, FALSE);
}
diff --git a/src/kgx-tab-switcher.h b/src/kgx-tab-switcher.h
index b120f63..8473f53 100644
--- a/src/kgx-tab-switcher.h
+++ b/src/kgx-tab-switcher.h
@@ -18,19 +18,23 @@
#pragma once
-#include <handy.h>
+#include <adwaita.h>
G_BEGIN_DECLS
#define KGX_TYPE_TAB_SWITCHER (kgx_tab_switcher_get_type())
-G_DECLARE_FINAL_TYPE (KgxTabSwitcher, kgx_tab_switcher, KGX, TAB_SWITCHER, GtkBin)
+G_DECLARE_FINAL_TYPE (KgxTabSwitcher, kgx_tab_switcher, KGX, TAB_SWITCHER, GtkWidget)
GtkWidget *kgx_tab_switcher_new (void);
-HdyTabView *kgx_tab_switcher_get_view (KgxTabSwitcher *self);
+GtkWidget *kgx_tab_switcher_get_child (KgxTabSwitcher *self);
+void kgx_tab_switcher_set_child (KgxTabSwitcher *self,
+ GtkWidget *child);
+
+AdwTabView *kgx_tab_switcher_get_view (KgxTabSwitcher *self);
void kgx_tab_switcher_set_view (KgxTabSwitcher *self,
- HdyTabView *view);
+ AdwTabView *view);
void kgx_tab_switcher_open (KgxTabSwitcher *self);
void kgx_tab_switcher_close (KgxTabSwitcher *self);
diff --git a/src/kgx-tab-switcher.ui b/src/kgx-tab-switcher.ui
index faa3b4b..7e22615 100644
--- a/src/kgx-tab-switcher.ui
+++ b/src/kgx-tab-switcher.ui
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.24"/>
- <template class="KgxTabSwitcher" parent="GtkBin">
+ <requires lib="gtk" version="4.0"/>
+ <template class="KgxTabSwitcher" parent="GtkWidget">
<child>
- <object class="HdyFlap" id="flap">
- <property name="visible">True</property>
+ <object class="AdwFlap" id="flap">
<property name="orientation">vertical</property>
<property name="swipe-to-open">False</property>
<property name="swipe-to-close">False</property>
@@ -12,70 +11,64 @@
<property name="flap-position">end</property>
<property name="fold-policy">always</property>
<signal name="notify::reveal-flap" handler="reveal_flap_cb" swapped="true"/>
- <child type="flap">
+ <property name="flap">
<object class="GtkOverlay">
- <property name="visible">True</property>
<style>
<class name="tab-switcher"/>
</style>
- <child>
+ <property name="child">
<object class="GtkScrolledWindow">
- <property name="visible">True</property>
<property name="hscrollbar-policy">never</property>
<property name="propagate-natural-width">True</property>
<property name="propagate-natural-height">True</property>
<style>
<class name="view"/>
</style>
- <child>
+ <property name="child">
<object class="GtkListBox" id="list">
- <property name="visible">True</property>
<property name="selection-mode">single</property>
<signal name="row-selected" handler="row_selected_cb" swapped="true"/>
<signal name="row-activated" handler="row_activated_cb" swapped="true"/>
+ <style>
+ <class name="navigation-sidebar"/>
+ </style>
</object>
- </child>
+ </property>
</object>
- </child>
+ </property>
<child type="overlay">
<object class="GtkButton">
- <property name="visible">True</property>
<property name="halign">center</property>
<property name="valign">start</property>
<property name="can-focus">False</property>
<signal name="clicked" handler="collapse_cb" swapped="true" />
<style>
+ <class name="flat"/>
<class name="collapse-button"/>
+ <class name="image-button"/>
</style>
- <child>
+ <property name="child">
<object class="GtkImage">
- <property name="visible">True</property>
<property name="pixel-size">24</property>
<property name="icon-name">tab-switcher-collapse-symbolic</property>
</object>
- </child>
+ </property>
</object>
</child>
<child type="overlay">
<object class="GtkButton">
- <property name="visible">True</property>
<property name="halign">end</property>
<property name="valign">end</property>
+ <property name="icon-name">list-add-symbolic</property>
<signal name="clicked" handler="new_tab_cb" swapped="true" />
<style>
<class name="suggested-action"/>
<class name="new-tab-button"/>
</style>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="icon-name">list-add-symbolic</property>
- </object>
- </child>
</object>
</child>
</object>
- </child>
+ </property>
</object>
</child>
</template>
diff --git a/src/kgx-tab.c b/src/kgx-tab.c
index 706400c..16d0ec5 100644
--- a/src/kgx-tab.c
+++ b/src/kgx-tab.c
@@ -201,14 +201,14 @@ search_enabled (GObject *object,
{
KgxTabPrivate *priv = kgx_tab_get_instance_private (self);
- if (!hdy_search_bar_get_search_mode (HDY_SEARCH_BAR (priv->search_bar))) {
+ if (!gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (priv->search_bar))) {
gtk_widget_grab_focus (GTK_WIDGET (self));
}
}
static void
-search_changed (HdySearchBar *bar,
+search_changed (GtkSearchBar *bar,
KgxTab *self)
{
KgxTabPrivate *priv = kgx_tab_get_instance_private (self);
@@ -218,7 +218,7 @@ search_changed (HdySearchBar *bar,
gboolean narrowing_down;
guint32 flags = PCRE2_MULTILINE;
- search = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
+ search = gtk_editable_get_text (GTK_EDITABLE (priv->search_entry));
if (search) {
g_autofree char *lowercase = g_utf8_strdown (search, -1);
@@ -271,7 +271,7 @@ search_changed (HdySearchBar *bar,
static void
-search_next (HdySearchBar *bar,
+search_next (GtkSearchBar *bar,
KgxTab *self)
{
KgxTabPrivate *priv = kgx_tab_get_instance_private (self);
@@ -281,7 +281,7 @@ search_next (HdySearchBar *bar,
static void
-search_prev (HdySearchBar *bar,
+search_prev (GtkSearchBar *bar,
KgxTab *self)
{
KgxTabPrivate *priv = kgx_tab_get_instance_private (self);
@@ -474,48 +474,17 @@ kgx_tab_set_property (GObject *object,
static gboolean
-kgx_tab_draw (GtkWidget *widget,
- cairo_t *cr)
+drop (GtkDropTarget *target,
+ const GValue *value,
+ KgxTab *self)
{
- GtkStateFlags flags;
+ kgx_tab_accept_drop (self, value);
- GTK_WIDGET_CLASS (kgx_tab_parent_class)->draw (widget, cr);
-
- flags = gtk_widget_get_state_flags (widget);
-
- /* FIXME this is a workaround for the fact GTK3 css outline is used for focus
- * only by default. This can be removed in GTK4 as it just works there. */
- if (flags & GTK_STATE_FLAG_DROP_ACTIVE) {
- GtkStyleContext *context = gtk_widget_get_style_context (widget);
- int width = gtk_widget_get_allocated_width (widget);
- int height = gtk_widget_get_allocated_height (widget);
-
- gtk_render_focus (context, cr, 0, 0, width, height);
- }
-
- return GDK_EVENT_PROPAGATE;
-}
-
-
-static void
-kgx_tab_drag_data_received (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- GtkSelectionData *selection_data,
- guint info,
- guint time)
-{
- KgxTab *self = KGX_TAB (widget);
- GdkDragAction action = gdk_drag_context_get_selected_action (context);
-
- kgx_tab_accept_drop (self, selection_data);
-
- gtk_drag_finish (context, TRUE, action == GDK_ACTION_COPY, time);
+ return TRUE;
}
-static void
+static gboolean
kgx_tab_grab_focus (GtkWidget *widget)
{
KgxTab *self = KGX_TAB (widget);
@@ -523,10 +492,10 @@ kgx_tab_grab_focus (GtkWidget *widget)
if (priv->terminal) {
gtk_widget_grab_focus (GTK_WIDGET (priv->terminal));
- return;
+ return GDK_EVENT_STOP;
}
- GTK_WIDGET_CLASS (kgx_tab_parent_class)->grab_focus (widget);
+ return GTK_WIDGET_CLASS (kgx_tab_parent_class)->grab_focus (widget);
}
@@ -561,8 +530,6 @@ kgx_tab_class_init (KgxTabClass *klass)
object_class->get_property = kgx_tab_get_property;
object_class->set_property = kgx_tab_set_property;
- widget_class->draw = kgx_tab_draw;
- widget_class->drag_data_received = kgx_tab_drag_data_received;
widget_class->grab_focus = kgx_tab_grab_focus;
tab_class->start = kgx_tab_real_start;
@@ -769,8 +736,8 @@ kgx_tab_add_child (GtkBuildable *buildable,
if (type && g_str_equal (type, "content")) {
g_set_weak_pointer (&priv->content, GTK_WIDGET (child));
gtk_stack_add_named (GTK_STACK (priv->stack), GTK_WIDGET (child), "content");
- } else {
- gtk_container_add (GTK_CONTAINER (self), GTK_WIDGET (child));
+ } else if (GTK_IS_WIDGET (child)) {
+ gtk_box_append (GTK_BOX (self), GTK_WIDGET (child));
}
}
@@ -789,7 +756,6 @@ died (KgxTab *self,
gboolean success)
{
KgxTabPrivate *priv;
- GtkStyleContext *context;
g_return_if_fail (KGX_IS_TAB (self));
@@ -797,12 +763,10 @@ died (KgxTab *self,
gtk_label_set_markup (GTK_LABEL (priv->label), message);
- context = gtk_widget_get_style_context (GTK_WIDGET (priv->revealer));
-
if (type == GTK_MESSAGE_ERROR) {
- gtk_style_context_add_class (context, "error");
+ gtk_widget_add_css_class (priv->revealer, "error");
} else {
- gtk_style_context_remove_class (context, "error");
+ gtk_widget_remove_css_class (priv->revealer, "error");
}
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->revealer), TRUE);
@@ -818,6 +782,7 @@ kgx_tab_init (KgxTab *self)
{
static guint last_id = 0;
KgxTabPrivate *priv = kgx_tab_get_instance_private (self);
+ GtkDropTarget *target;
last_id++;
@@ -834,13 +799,12 @@ kgx_tab_init (KgxTab *self)
g_signal_connect (self, "died", G_CALLBACK (died), NULL);
- hdy_search_bar_connect_entry (HDY_SEARCH_BAR (priv->search_bar),
- GTK_ENTRY (priv->search_entry));
+ gtk_search_bar_connect_entry (GTK_SEARCH_BAR (priv->search_bar),
+ GTK_EDITABLE (priv->search_entry));
- gtk_drag_dest_set (GTK_WIDGET (self), GTK_DEST_DEFAULT_ALL, NULL, 0,
- GDK_ACTION_COPY);
- gtk_drag_dest_add_uri_targets (GTK_WIDGET (self));
- gtk_drag_dest_add_text_targets (GTK_WIDGET (self));
+ target = gtk_drop_target_new (G_TYPE_STRING, GDK_ACTION_COPY);
+ g_signal_connect (target, "drop", G_CALLBACK (drop), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (target));
}
@@ -907,45 +871,6 @@ kgx_tab_connect_terminal (KgxTab *self,
}
-void
-kgx_tab_set_pages (KgxTab *self,
- KgxPages *pages)
-{
- KgxTabPrivate *priv;
-
- g_return_if_fail (KGX_IS_TAB (self));
- g_return_if_fail (KGX_IS_PAGES (pages) || !pages);
-
- priv = kgx_tab_get_instance_private (self);
-
- g_clear_object (&priv->pages_font_bind);
- g_clear_object (&priv->pages_zoom_bind);
- g_clear_object (&priv->pages_theme_bind);
- g_clear_object (&priv->pages_opaque_bind);
- g_clear_object (&priv->pages_scrollback_bind);
-
- if (pages == NULL) {
- return;
- }
-
- priv->pages_font_bind = g_object_bind_property (pages, "font",
- self, "font",
- G_BINDING_SYNC_CREATE);
- priv->pages_zoom_bind = g_object_bind_property (pages, "zoom",
- self, "zoom",
- G_BINDING_SYNC_CREATE);
- priv->pages_theme_bind = g_object_bind_property (pages, "theme",
- self, "theme",
- G_BINDING_SYNC_CREATE);
- priv->pages_opaque_bind = g_object_bind_property (pages, "opaque",
- self, "opaque",
- G_BINDING_SYNC_CREATE);
- priv->pages_scrollback_bind = g_object_bind_property (pages, "scrollback-lines",
- self, "scrollback-lines",
- G_BINDING_SYNC_CREATE);
-}
-
-
void
kgx_tab_start (KgxTab *self,
GAsyncReadyCallback callback,
@@ -1226,33 +1151,22 @@ kgx_tab_get_children (KgxTab *self)
void
-kgx_tab_accept_drop (KgxTab *self,
- GtkSelectionData *selection_data)
+kgx_tab_accept_drop (KgxTab *self,
+ const GValue *value)
{
KgxTabPrivate *priv;
- GdkAtom selection_data_target;
g_autofree char *text = NULL;
+ g_auto (GStrv) uris = NULL;
g_return_if_fail (KGX_IS_TAB (self));
priv = kgx_tab_get_instance_private (self);
- selection_data_target = gtk_selection_data_get_target (selection_data);
-
- if (gtk_selection_data_get_length (selection_data) < 0)
- return;
-
- if (gtk_targets_include_uri (&selection_data_target, 1)) {
- g_auto (GStrv) uris = NULL;
-
- uris = gtk_selection_data_get_uris (selection_data);
+ uris = g_strsplit (g_value_get_string (value), "\n", 0);
- kgx_util_transform_uris_to_quoted_fuse_paths (uris);
+ kgx_util_transform_uris_to_quoted_fuse_paths (uris);
- text = kgx_util_concat_uris (uris, NULL);
- } else {
- text = (char *) gtk_selection_data_get_text (selection_data);
- }
+ text = kgx_util_concat_uris (uris, NULL);
if (priv->terminal) {
kgx_terminal_accept_paste (KGX_TERMINAL (priv->terminal), text);
@@ -1281,26 +1195,40 @@ kgx_tab_set_initial_title (KgxTab *self,
}
-gboolean
-kgx_tab_key_press_event (KgxTab *self,
- GdkEvent *event)
+void
+kgx_tab_set_pages (KgxTab *self,
+ KgxPages *pages)
{
KgxTabPrivate *priv;
- GtkWidget *toplevel, *focus;
- g_return_val_if_fail (KGX_IS_TAB (self), GDK_EVENT_PROPAGATE);
- g_return_val_if_fail (event != NULL, GDK_EVENT_PROPAGATE);
+ g_return_if_fail (KGX_IS_TAB (self));
+ g_return_if_fail (KGX_IS_PAGES (pages) || !pages);
priv = kgx_tab_get_instance_private (self);
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
-
- if (!GTK_IS_WINDOW (toplevel))
- return GDK_EVENT_PROPAGATE;
- focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
+ g_clear_object (&priv->pages_font_bind);
+ g_clear_object (&priv->pages_zoom_bind);
+ g_clear_object (&priv->pages_theme_bind);
+ g_clear_object (&priv->pages_opaque_bind);
+ g_clear_object (&priv->pages_scrollback_bind);
- if (focus == GTK_WIDGET (priv->terminal))
- return gtk_widget_event (GTK_WIDGET (priv->terminal), event);
+ if (pages == NULL) {
+ return;
+ }
- return GDK_EVENT_PROPAGATE;
+ priv->pages_font_bind = g_object_bind_property (pages, "font",
+ self, "font",
+ G_BINDING_SYNC_CREATE);
+ priv->pages_zoom_bind = g_object_bind_property (pages, "zoom",
+ self, "zoom",
+ G_BINDING_SYNC_CREATE);
+ priv->pages_theme_bind = g_object_bind_property (pages, "theme",
+ self, "theme",
+ G_BINDING_SYNC_CREATE);
+ priv->pages_opaque_bind = g_object_bind_property (pages, "opaque",
+ self, "opaque",
+ G_BINDING_SYNC_CREATE);
+ priv->pages_scrollback_bind = g_object_bind_property (pages, "scrollback-lines",
+ self, "scrollback-lines",
+ G_BINDING_SYNC_CREATE);
}
diff --git a/src/kgx-tab.h b/src/kgx-tab.h
index fdf0eae..77f8604 100644
--- a/src/kgx-tab.h
+++ b/src/kgx-tab.h
@@ -100,11 +100,9 @@ void kgx_tab_pop_child (KgxTab *self,
gboolean kgx_tab_is_active (KgxTab *self);
GPtrArray *kgx_tab_get_children (KgxTab *self);
void kgx_tab_accept_drop (KgxTab *self,
- GtkSelectionData *selection_data);
+ const GValue *value);
void kgx_tab_set_initial_title (KgxTab *self,
const char *title,
GFile *path);
-gboolean kgx_tab_key_press_event (KgxTab *self,
- GdkEvent *event);
G_END_DECLS
diff --git a/src/kgx-tab.ui b/src/kgx-tab.ui
index 2888104..9f82414 100644
--- a/src/kgx-tab.ui
+++ b/src/kgx-tab.ui
@@ -1,27 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.20"/>
+ <requires lib="gtk" version="4.0"/>
<template class="KgxTab" parent="GtkBox">
- <property name="visible">True</property>
<property name="orientation">vertical</property>
<style>
<class name="tab"/>
</style>
<child>
- <object class="HdySearchBar" id="search_bar">
- <property name="visible">1</property>
+ <object class="GtkSearchBar" id="search_bar">
<property name="search-mode-enabled" bind-source="KgxTab" bind-property="search-mode-enabled"
bind-flags="sync-create|bidirectional"/>
<signal name="notify::search-mode-enabled" handler="search_enabled" swapped="no"/>
<child>
- <object class="HdyClamp">
- <property name="visible">1</property>
+ <object class="AdwClamp">
+ <property name="hexpand">1</property>
<property name="maximum-size">500</property>
- <child>
+ <property name="child">
<object class="GtkBox">
- <property name="visible">1</property>
+ <property name="spacing">6</property>
<child>
<object class="GtkSearchEntry" id="search_entry">
- <property name="visible">1</property>
<property name="hexpand">1</property>
<signal name="next-match" handler="search_next" swapped="no"/>
<signal name="previous-match" handler="search_prev" swapped="no"/>
@@ -30,35 +27,20 @@
</child>
<child>
<object class="GtkButton">
- <property name="visible">1</property>
<property name="receives-default">1</property>
- <child>
- <object class="GtkImage">
- <property name="visible">1</property>
- <property name="icon-name">go-down-symbolic</property>
- </object>
- </child>
+ <property name="icon-name">go-down-symbolic</property>
<signal name="clicked" handler="search_next" swapped="no"/>
</object>
</child>
<child>
<object class="GtkButton">
- <property name="visible">1</property>
<property name="receives-default">1</property>
- <child>
- <object class="GtkImage">
- <property name="visible">1</property>
- <property name="icon-name">go-up-symbolic</property>
- </object>
- </child>
+ <property name="icon-name">go-up-symbolic</property>
<signal name="clicked" handler="search_prev" swapped="no"/>
</object>
</child>
- <style>
- <class name="linked"/>
- </style>
</object>
- </child>
+ </property>
</object>
</child>
<style>
@@ -68,27 +50,23 @@
</child>
<child>
<object class="GtkStack" id="stack">
- <property name="vexpand">True</property>
<property name="visible">True</property>
<child>
<object class="GtkBox">
- <property name="visible">True</property>
<style>
<class name="empty-state"/>
</style>
<child>
<object class="GtkRevealer" id="spinner_revealer">
- <property name="visible">True</property>
<property name="hexpand">True</property>
<property name="transition-type">crossfade</property>
<property name="transition-duration">1000</property>
- <child>
+ <property name="child">
<object class="GtkSpinner">
- <property name="visible">True</property>
<signal name="map" handler="spinner_mapped" swapped="no"/>
<signal name="unmap" handler="spinner_unmapped" swapped="no"/>
</object>
- </child>
+ </property>
</object>
</child>
</object>
@@ -97,21 +75,16 @@
</child>
<child>
<object class="GtkRevealer" id="revealer">
- <property name="visible">True</property>
- <property name="valign">end</property>
+ <property name="can_focus">False</property>
<property name="transition_type">slide-up</property>
- <child>
+ <property name="child">
<object class="GtkBox">
- <property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
- <object class="GtkSeparator">
- <property name="visible">True</property>
- </object>
+ <object class="GtkSeparator"/>
</child>
<child>
<object class="GtkLabel" id="label">
- <property name="visible">True</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
<property name="xalign">0</property>
@@ -121,11 +94,8 @@
<class name="exit-info"/>
</style>
</object>
- </child>
+ </property>
</object>
- <packing>
- <property name="pack_type">end</property>
- </packing>
</child>
</template>
</interface>
diff --git a/src/kgx-terminal.c b/src/kgx-terminal.c
index d51020b..d307c9b 100644
--- a/src/kgx-terminal.c
+++ b/src/kgx-terminal.c
@@ -26,7 +26,7 @@
*/
#include <glib/gi18n.h>
-#include <handy.h>
+#include <adwaita.h>
#include <vte/vte.h>
#define PCRE2_CODE_UNIT_WIDTH 0
#include <pcre2.h>
@@ -90,17 +90,7 @@ kgx_terminal_dispose (GObject *object)
g_clear_object (&self->actions);
g_clear_pointer (&self->current_url, g_free);
- g_clear_object (&self->long_press_gesture);
-
- if (self->menu) {
- gtk_menu_detach (GTK_MENU (self->menu));
- self->menu = NULL;
- }
-
- if (self->touch_menu) {
- gtk_popover_set_relative_to (GTK_POPOVER (self->touch_menu), NULL);
- self->touch_menu = NULL;
- }
+ g_clear_pointer (&self->popup_menu, gtk_widget_unparent);
G_OBJECT_CLASS (kgx_terminal_parent_class)->dispose (object);
}
@@ -134,9 +124,9 @@ update_terminal_colors (KgxTerminal *self)
};
if (self->theme == KGX_THEME_AUTO) {
- HdyStyleManager *manager = hdy_style_manager_get_default ();
+ AdwStyleManager *manager = adw_style_manager_get_default ();
- if (hdy_style_manager_get_dark (manager)) {
+ if (adw_style_manager_get_dark (manager)) {
resolved_theme = KGX_THEME_NIGHT;
} else {
resolved_theme = KGX_THEME_DAY;
@@ -247,7 +237,9 @@ kgx_terminal_get_property (GObject *object,
static gboolean
-have_url_under_pointer (KgxTerminal *self, GdkEvent *event)
+have_url_under_pointer (KgxTerminal *self,
+ double x,
+ double y)
{
g_autofree char *hyperlink = NULL;
g_autofree char *match = NULL;
@@ -255,14 +247,12 @@ have_url_under_pointer (KgxTerminal *self, GdkEvent *event)
g_clear_pointer (&self->current_url, g_free);
- hyperlink = vte_terminal_hyperlink_check_event (VTE_TERMINAL (self), event);
+ hyperlink = vte_terminal_check_hyperlink_at (VTE_TERMINAL (self), x, y);
if (G_UNLIKELY (hyperlink)) {
self->current_url = g_steal_pointer (&hyperlink);
} else {
- match = vte_terminal_match_check_event (VTE_TERMINAL (self),
- event,
- &match_id);
+ match = vte_terminal_check_match_at (VTE_TERMINAL (self), x, y, &match_id);
for (int i = 0; i < KGX_TERMINAL_N_LINK_REGEX; i++) {
if (self->match_id[i] == match_id) {
@@ -277,123 +267,121 @@ have_url_under_pointer (KgxTerminal *self, GdkEvent *event)
static void
-context_menu_detach (KgxTerminal *self,
- GtkMenu *menu)
+update_menu_position (KgxTerminal *self)
{
- self->menu = NULL;
+ if (!self->popup_menu)
+ return;
+
+ gtk_popover_set_position (GTK_POPOVER (self->popup_menu),
+ self->popup_is_touch ? GTK_POS_TOP : GTK_POS_BOTTOM);
+
+ gtk_popover_set_has_arrow (GTK_POPOVER (self->popup_menu), self->popup_is_touch);
+
+ if (self->popup_is_touch) {
+ gtk_widget_set_halign (self->popup_menu, GTK_ALIGN_FILL);
+ } else if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL) {
+ gtk_widget_set_halign (self->popup_menu, GTK_ALIGN_END);
+ } else {
+ gtk_widget_set_halign (self->popup_menu, GTK_ALIGN_START);
+ }
}
static void
-context_menu (GtkWidget *widget,
- int x,
- int y,
- gboolean touch,
- GdkEvent *event)
+context_menu (KgxTerminal *self,
+ double x,
+ double y,
+ gboolean touch)
{
- KgxTerminal *self = KGX_TERMINAL (widget);
GAction *act;
GtkApplication *app;
- GMenu *model;
gboolean value;
- value = have_url_under_pointer (self, event);
+ value = have_url_under_pointer (self, x, y);
act = g_action_map_lookup_action (G_ACTION_MAP (self->actions), "open-link");
g_simple_action_set_enabled (G_SIMPLE_ACTION (act), value);
act = g_action_map_lookup_action (G_ACTION_MAP (self->actions), "copy-link");
g_simple_action_set_enabled (G_SIMPLE_ACTION (act), value);
- if (touch) {
- GdkRectangle rect = {x, y, 1, 1};
-
- if (!self->touch_menu) {
- app = GTK_APPLICATION (g_application_get_default ());
- model = gtk_application_get_menu_by_id (app, "context-menu");
+ app = GTK_APPLICATION (g_application_get_default ());
- self->touch_menu = gtk_popover_new_from_model (widget, G_MENU_MODEL (model));
- }
+ if (!self->popup_menu) {
+ GMenu *model = gtk_application_get_menu_by_id (app, "context-menu");
- gtk_popover_set_pointing_to (GTK_POPOVER (self->touch_menu), &rect);
- gtk_popover_popup (GTK_POPOVER (self->touch_menu));
- } else {
- if (!self->menu) {
- app = GTK_APPLICATION (g_application_get_default ());
- model = gtk_application_get_menu_by_id (app, "context-menu");
+ self->popup_menu = gtk_popover_menu_new_from_model (G_MENU_MODEL (model));
- self->menu = gtk_menu_new_from_model (G_MENU_MODEL (model));
- gtk_style_context_add_class (gtk_widget_get_style_context (self->menu),
- GTK_STYLE_CLASS_CONTEXT_MENU);
+ gtk_widget_set_parent (self->popup_menu, GTK_WIDGET (self));
+ }
- gtk_menu_attach_to_widget (GTK_MENU (self->menu), widget,
- (GtkMenuDetachFunc) context_menu_detach);
- }
+ self->popup_is_touch = touch;
- if (event && gdk_event_triggers_context_menu (event)) {
- gtk_menu_popup_at_pointer (GTK_MENU (self->menu), event);
- } else {
- gtk_menu_popup_at_widget (GTK_MENU (self->menu),
- widget,
- GDK_GRAVITY_SOUTH_WEST,
- GDK_GRAVITY_NORTH_WEST,
- event);
+ update_menu_position (self);
- gtk_menu_shell_select_first (GTK_MENU_SHELL (self->menu), FALSE);
- }
+ if (x > -1 && y > -1) {
+ GdkRectangle rect = { x, y, 1, 1 };
+ gtk_popover_set_pointing_to (GTK_POPOVER (self->popup_menu), &rect);
+ } else {
+ gtk_popover_set_pointing_to (GTK_POPOVER (self->popup_menu), NULL);
}
+
+ gtk_popover_popup (GTK_POPOVER (self->popup_menu));
}
-static gboolean
-kgx_terminal_popup_menu (GtkWidget *self)
+static void
+menu_popup_activated (GtkWidget *self,
+ const char *action_name,
+ GVariant *parameters)
{
- context_menu (self, 1, 1, FALSE, NULL);
-
- return TRUE;
+ context_menu (KGX_TERMINAL (self), 1, 1, FALSE);
}
static void
open_link (KgxTerminal *self, guint32 timestamp)
{
- g_autoptr (GError) error = NULL;
-
- gtk_show_uri_on_window (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
- self->current_url,
- timestamp,
- &error);
-
- if (error) {
- g_warning ("Failed to open link %s", error->message);
- }
+ gtk_show_uri (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
+ self->current_url,
+ timestamp);
}
-static gboolean
-kgx_terminal_button_press_event (GtkWidget *widget, GdkEventButton *event)
+static void
+kgx_terminal_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
{
+ int rows;
+ int cols;
KgxTerminal *self = KGX_TERMINAL (widget);
- GdkModifierType state;
+ VteTerminal *term = VTE_TERMINAL (self);
- if (gdk_event_triggers_context_menu ((GdkEvent *) event) &&
- event->type == GDK_BUTTON_PRESS) {
- context_menu (widget, event->x, event->y, FALSE, (GdkEvent *) event);
+ if (self->popup_menu)
+ gtk_popover_present (GTK_POPOVER (self->popup_menu));
- return TRUE;
- }
+ GTK_WIDGET_CLASS (kgx_terminal_parent_class)->size_allocate (widget, width, height, baseline);
+
+ rows = vte_terminal_get_row_count (term);
+ cols = vte_terminal_get_column_count (term);
- state = event->state & gtk_accelerator_get_default_mod_mask ();
+ g_signal_emit (self, signals[SIZE_CHANGED], 0, rows, cols);
+}
- if (have_url_under_pointer (self, (GdkEvent *) event) &&
- (event->button == 1 || event->button == 2) &&
- state & GDK_CONTROL_MASK) {
- open_link (self, event->time);
- return GDK_EVENT_STOP;
- }
+static void
+kgx_terminal_direction_changed (GtkWidget *widget,
+ GtkTextDirection previous_direction)
+{
+ KgxTerminal *self = KGX_TERMINAL (widget);
+
+ GTK_WIDGET_CLASS (kgx_terminal_parent_class)->direction_changed (widget, previous_direction);
- return GTK_WIDGET_CLASS (kgx_terminal_parent_class)->button_press_event (widget,
- event);
+ if (gtk_widget_get_direction (widget) == previous_direction)
+ return;
+
+ update_menu_position (self);
}
@@ -407,8 +395,8 @@ kgx_terminal_class_init (KgxTerminalClass *klass)
object_class->set_property = kgx_terminal_set_property;
object_class->get_property = kgx_terminal_get_property;
- widget_class->popup_menu = kgx_terminal_popup_menu;
- widget_class->button_press_event = kgx_terminal_button_press_event;
+ widget_class->size_allocate = kgx_terminal_size_allocate;
+ widget_class->direction_changed = kgx_terminal_direction_changed;
/**
* KgxTerminal:theme:
@@ -461,6 +449,25 @@ kgx_terminal_class_init (KgxTerminalClass *klass)
2,
G_TYPE_UINT,
G_TYPE_UINT);
+
+ /**
+ * KgxTerminal|menu.popup:
+ *
+ * Opens the context menu.
+ */
+ gtk_widget_class_install_action (widget_class,
+ "menu.popup",
+ NULL,
+ menu_popup_activated);
+
+ gtk_widget_class_add_binding_action (widget_class,
+ GDK_KEY_F10, GDK_SHIFT_MASK,
+ "menu.popup",
+ NULL);
+ gtk_widget_class_add_binding_action (widget_class,
+ GDK_KEY_Menu, 0,
+ "menu.popup",
+ NULL);
}
@@ -478,12 +485,10 @@ copy_link_activated (GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
- GtkClipboard *cb;
KgxTerminal *self = KGX_TERMINAL (data);
+ GdkClipboard *cb = gtk_widget_get_clipboard (GTK_WIDGET (self));
- cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
-
- gtk_clipboard_set_text (cb, self->current_url, -1);
+ gdk_clipboard_set_text (cb, self->current_url);
}
static void
@@ -491,7 +496,10 @@ copy_activated (GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
- vte_terminal_copy_clipboard_format (VTE_TERMINAL (data), VTE_FORMAT_TEXT);
+ GdkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (data));
+ g_autofree char *text = vte_terminal_get_text_selected (VTE_TERMINAL (data),
+ VTE_FORMAT_TEXT);
+ gdk_clipboard_set_text (clipboard, text);
}
@@ -522,7 +530,7 @@ paste_response (GtkDialog *dlg,
g_autoptr (PasteData) paste = data;
if (dlg && GTK_IS_DIALOG (dlg)) {
- gtk_widget_destroy (GTK_WIDGET (dlg));
+ gtk_window_destroy (GTK_WINDOW (dlg));
}
if (response == GTK_RESPONSE_ACCEPT) {
@@ -532,11 +540,20 @@ paste_response (GtkDialog *dlg,
static void
-got_text (GtkClipboard *clipboard,
- const char *text,
- gpointer data)
+got_text (GdkClipboard *cb,
+ GAsyncResult *result,
+ KgxTerminal *self)
{
- kgx_terminal_accept_paste (KGX_TERMINAL (data), text);
+ g_autofree char *text = NULL;
+ g_autoptr (GError) error = NULL;
+
+ /* Get the resulting text of the read operation */
+ text = gdk_clipboard_read_text_finish (cb, result, &error);
+
+ if (error)
+ g_critical ("Couldn't paste text: %s\n", error->message);
+
+ kgx_terminal_accept_paste (self, text);
}
@@ -545,11 +562,9 @@ paste_activated (GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
- GtkClipboard *cb;
-
- cb = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+ GdkClipboard *cb = gtk_widget_get_clipboard (GTK_WIDGET (data));
- gtk_clipboard_request_text (cb, got_text, data);
+ gdk_clipboard_read_text_async (cb, NULL, (GAsyncReadyCallback) got_text, data);
}
static void
@@ -628,13 +643,57 @@ static GActionEntry term_entries[] = {
};
+static void
+pressed (GtkGestureClick *gesture,
+ int n_presses,
+ double x,
+ double y,
+ KgxTerminal *self)
+{
+ GdkEvent *event;
+ GdkModifierType state;
+ guint button;
+
+ if (n_presses > 1) {
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
+ return;
+ }
+
+ event = gtk_event_controller_get_current_event (GTK_EVENT_CONTROLLER (gesture));
+
+ if (gdk_event_triggers_context_menu (event)) {
+ context_menu (self, x, y, FALSE);
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
+
+ return;
+ }
+
+ state = gtk_event_controller_get_current_event_state (GTK_EVENT_CONTROLLER (gesture));
+ button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
+
+ if (have_url_under_pointer (self, x, y) &&
+ (button == GDK_BUTTON_PRIMARY || button == GDK_BUTTON_MIDDLE) &&
+ state & GDK_CONTROL_MASK) {
+ guint32 time = gtk_event_controller_get_current_event_time (GTK_EVENT_CONTROLLER (gesture));
+
+ open_link (self, time);
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
+
+ return;
+ }
+
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
+}
+
+
static void
long_pressed (GtkGestureLongPress *gesture,
- gdouble x,
- gdouble y,
+ double x,
+ double y,
KgxTerminal *self)
{
- context_menu (GTK_WIDGET (self), (int) x, (int) y, TRUE, NULL);
+ context_menu (self, x, y, TRUE);
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
}
@@ -667,22 +726,6 @@ location_changed (KgxTerminal *self)
}
-static void
-size_changed (GtkWidget *widget,
- GdkRectangle *allocation)
-{
- int rows;
- int cols;
- KgxTerminal *self = KGX_TERMINAL (widget);
- VteTerminal *term = VTE_TERMINAL (self);
-
- rows = vte_terminal_get_row_count (term);
- cols = vte_terminal_get_column_count (term);
-
- g_signal_emit (self, signals[SIZE_CHANGED], 0, rows, cols);
-}
-
-
static void
dark_changed (KgxTerminal *self)
{
@@ -707,12 +750,15 @@ kgx_terminal_init (KgxTerminal *self)
"term",
G_ACTION_GROUP (self->actions));
- gesture = gtk_gesture_long_press_new (GTK_WIDGET (self));
+ gesture = gtk_gesture_click_new ();
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
+ g_signal_connect (gesture, "pressed", G_CALLBACK (pressed), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
+
+ gesture = gtk_gesture_long_press_new ();
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture), TRUE);
- gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
- GTK_PHASE_TARGET);
g_signal_connect (gesture, "pressed", G_CALLBACK (long_pressed), self);
- self->long_press_gesture = gesture;
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
act = g_action_map_lookup_action (self->actions, "open-link");
g_simple_action_set_enabled (G_SIMPLE_ACTION (act), FALSE);
@@ -735,8 +781,6 @@ kgx_terminal_init (KgxTerminal *self)
G_CALLBACK (location_changed), NULL);
g_signal_connect (self, "current-file-uri-changed",
G_CALLBACK (location_changed), NULL);
- g_signal_connect (self, "size-allocate",
- G_CALLBACK (size_changed), NULL);
for (int i = 0; i < KGX_TERMINAL_N_LINK_REGEX; i++) {
g_autoptr (VteRegex) regex = NULL;
@@ -758,7 +802,7 @@ kgx_terminal_init (KgxTerminal *self)
"pointer");
}
- g_signal_connect_object (hdy_style_manager_get_default (),
+ g_signal_connect_object (adw_style_manager_get_default (),
"notify::dark", G_CALLBACK (dark_changed),
self, G_CONNECT_SWAPPED);
@@ -786,7 +830,7 @@ kgx_terminal_accept_paste (KgxTerminal *self,
if (g_strstr_len (striped, len, "sudo") != NULL &&
g_strstr_len (striped, len, "\n") != NULL) {
GtkWidget *accept = NULL;
- GtkWidget *dlg = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))),
+ GtkWidget *dlg = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))),
GTK_DIALOG_MODAL,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_NONE,
@@ -806,8 +850,8 @@ kgx_terminal_accept_paste (KgxTerminal *self,
accept = gtk_dialog_add_button (GTK_DIALOG (dlg),
_("_Paste"),
GTK_RESPONSE_ACCEPT);
- gtk_style_context_add_class (gtk_widget_get_style_context (accept),
- "destructive-action");
+ gtk_widget_add_css_class (accept, "destructive-action");
+
gtk_widget_show (dlg);
} else {
paste_response (NULL, GTK_RESPONSE_ACCEPT, g_steal_pointer (&paste));
diff --git a/src/kgx-terminal.h b/src/kgx-terminal.h
index 73dd53f..72e11d6 100644
--- a/src/kgx-terminal.h
+++ b/src/kgx-terminal.h
@@ -101,17 +101,13 @@ struct _KgxTerminal {
KgxTheme theme;
gboolean opaque;
GActionMap *actions;
+ GtkWidget *popup_menu;
/* Hyperlinks */
char *current_url;
int match_id[KGX_TERMINAL_N_LINK_REGEX];
- /* Gestures */
- GtkGesture *long_press_gesture;
-
- /* Menus */
- GtkWidget *menu;
- GtkWidget *touch_menu;
+ gboolean popup_is_touch;
};
G_DECLARE_FINAL_TYPE (KgxTerminal, kgx_terminal, KGX, TERMINAL, VteTerminal)
diff --git a/src/kgx-theme-switcher.c b/src/kgx-theme-switcher.c
index 7594ddb..04d2f62 100644
--- a/src/kgx-theme-switcher.c
+++ b/src/kgx-theme-switcher.c
@@ -23,10 +23,11 @@
struct _KgxThemeSwitcher {
- GtkBin parent_instance;
+ GtkWidget parent_instance;
KgxTheme theme;
+ GtkWidget *box;
GtkWidget *system_selector;
GtkWidget *light_selector;
GtkWidget *dark_selector;
@@ -34,7 +35,7 @@ struct _KgxThemeSwitcher {
};
-G_DEFINE_TYPE (KgxThemeSwitcher, kgx_theme_switcher, GTK_TYPE_BIN)
+G_DEFINE_TYPE (KgxThemeSwitcher, kgx_theme_switcher, GTK_TYPE_WIDGET)
enum {
@@ -47,13 +48,13 @@ static GParamSpec *pspecs[LAST_PROP] = { NULL, };
static void
-theme_radio_active_changed (KgxThemeSwitcher *self)
+theme_check_active_changed (KgxThemeSwitcher *self)
{
KgxTheme theme;
- if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->system_selector))) {
+ if (gtk_check_button_get_active (GTK_CHECK_BUTTON (self->system_selector))) {
theme = KGX_THEME_AUTO;
- } else if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->light_selector))) {
+ } else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (self->light_selector))) {
theme = KGX_THEME_DAY;
} else {
theme = KGX_THEME_NIGHT;
@@ -77,15 +78,15 @@ set_theme (KgxThemeSwitcher *self,
switch (theme) {
case KGX_THEME_AUTO:
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->system_selector), TRUE);
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->system_selector), TRUE);
break;
case KGX_THEME_DAY:
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->light_selector), TRUE);
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->light_selector), TRUE);
break;
case KGX_THEME_NIGHT:
case KGX_THEME_HACKER:
default:
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->dark_selector), TRUE);
+ gtk_check_button_set_active (GTK_CHECK_BUTTON (self->dark_selector), TRUE);
break;
}
@@ -136,6 +137,18 @@ kgx_theme_switcher_set_property (GObject *object,
}
+static void
+kgx_theme_switcher_dispose (GObject *object)
+{
+ KgxThemeSwitcher *self = KGX_THEME_SWITCHER (object);
+
+ if (self->box)
+ gtk_widget_unparent (self->box);
+
+ G_OBJECT_CLASS (kgx_theme_switcher_parent_class)->dispose (object);
+}
+
+
static void
kgx_theme_switcher_class_init (KgxThemeSwitcherClass *klass)
{
@@ -144,6 +157,7 @@ kgx_theme_switcher_class_init (KgxThemeSwitcherClass *klass)
object_class->get_property = kgx_theme_switcher_get_property;
object_class->set_property = kgx_theme_switcher_set_property;
+ object_class->dispose = kgx_theme_switcher_dispose;
pspecs[PROP_THEME] =
g_param_spec_enum ("theme",
@@ -165,13 +179,15 @@ kgx_theme_switcher_class_init (KgxThemeSwitcherClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
KGX_APPLICATION_PATH "kgx-theme-switcher.ui");
+ gtk_widget_class_bind_template_child (widget_class, KgxThemeSwitcher, box);
gtk_widget_class_bind_template_child (widget_class, KgxThemeSwitcher, system_selector);
gtk_widget_class_bind_template_child (widget_class, KgxThemeSwitcher, light_selector);
gtk_widget_class_bind_template_child (widget_class, KgxThemeSwitcher, dark_selector);
- gtk_widget_class_bind_template_callback (widget_class, theme_radio_active_changed);
+ gtk_widget_class_bind_template_callback (widget_class, theme_check_active_changed);
gtk_widget_class_set_css_name (widget_class, "themeswitcher");
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
}
diff --git a/src/kgx-theme-switcher.h b/src/kgx-theme-switcher.h
index 848b2f7..2acf158 100644
--- a/src/kgx-theme-switcher.h
+++ b/src/kgx-theme-switcher.h
@@ -24,6 +24,6 @@ G_BEGIN_DECLS
#define KGX_TYPE_THEME_SWITCHER (kgx_theme_switcher_get_type())
-G_DECLARE_FINAL_TYPE (KgxThemeSwitcher, kgx_theme_switcher, KGX, THEME_SWITCHER, GtkBin)
+G_DECLARE_FINAL_TYPE (KgxThemeSwitcher, kgx_theme_switcher, KGX, THEME_SWITCHER, GtkWidget)
G_END_DECLS
diff --git a/src/kgx-theme-switcher.ui b/src/kgx-theme-switcher.ui
index aa06b6d..7e1abc4 100644
--- a/src/kgx-theme-switcher.ui
+++ b/src/kgx-theme-switcher.ui
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.20"/>
- <template class="KgxThemeSwitcher" parent="GtkBin">
+ <requires lib="gtk" version="4.0"/>
+ <template class="KgxThemeSwitcher" parent="GtkWidget">
<child>
- <object class="GtkBox">
- <property name="visible">True</property>
+ <object class="GtkBox" id="box">
<property name="orientation">horizontal</property>
<property name="homogeneous">True</property>
<property name="spacing">18</property>
@@ -13,10 +12,10 @@
<property name="visible" bind-source="KgxThemeSwitcher" bind-property="show-system"
bind-flags="sync-create"/>
<property name="halign">center</property>
<child>
- <object class="GtkRadioButton" id="system_selector">
- <property name="visible">True</property>
+ <object class="GtkCheckButton" id="system_selector">
<property name="tooltip-text" translatable="yes">Use System Colors</property>
- <signal name="notify::active" handler="theme_radio_active_changed" swapped="yes"/>
+ <property name="active">True</property>
+ <signal name="notify::active" handler="theme_check_active_changed" swapped="yes"/>
<style>
<class name="system"/>
</style>
@@ -38,14 +37,12 @@
</child>
<child>
<object class="GtkOverlay">
- <property name="visible">True</property>
<property name="halign">center</property>
<child>
- <object class="GtkRadioButton" id="light_selector">
- <property name="visible">True</property>
+ <object class="GtkCheckButton" id="light_selector">
<property name="group">system_selector</property>
<property name="tooltip-text" translatable="yes">Use Light Colors</property>
- <signal name="notify::active" handler="theme_radio_active_changed" swapped="yes"/>
+ <signal name="notify::active" handler="theme_check_active_changed" swapped="yes"/>
<style>
<class name="light"/>
</style>
@@ -67,15 +64,13 @@
</child>
<child>
<object class="GtkOverlay">
- <property name="visible">True</property>
<property name="halign">center</property>
<child>
- <object class="GtkRadioButton" id="dark_selector">
- <property name="visible">True</property>
+ <object class="GtkCheckButton" id="dark_selector">
<property name="group">system_selector</property>
<property name="tooltip-text" translatable="yes">Use Dark Colors</property>
<property name="halign">center</property>
- <signal name="notify::active" handler="theme_radio_active_changed" swapped="yes"/>
+ <signal name="notify::active" handler="theme_check_active_changed" swapped="yes"/>
<style>
<class name="dark"/>
</style>
diff --git a/src/kgx-window.c b/src/kgx-window.c
index d8fe17a..1970bff 100644
--- a/src/kgx-window.c
+++ b/src/kgx-window.c
@@ -21,7 +21,7 @@
* @title: KgxWindow
* @short_description: Window
*
- * The main #HdyApplicationWindow that acts as the terminal
+ * The main #AdwApplicationWindow that acts as the terminal
*/
#include "kgx-config.h"
@@ -29,7 +29,7 @@
#include <glib/gi18n.h>
#include <vte/vte.h>
#include <math.h>
-#include <handy.h>
+#include <adwaita.h>
#include "rgba.h"
@@ -42,7 +42,7 @@
#include "kgx-tab-switcher.h"
#include "kgx-theme-switcher.h"
-G_DEFINE_TYPE (KgxWindow, kgx_window, HDY_TYPE_APPLICATION_WINDOW)
+G_DEFINE_TYPE (KgxWindow, kgx_window, ADW_TYPE_APPLICATION_WINDOW)
enum {
PROP_0,
@@ -84,12 +84,12 @@ kgx_window_constructed (GObject *object)
{
KgxWindow *self = KGX_WINDOW (object);
GtkApplication *application = NULL;
- HdyStyleManager *style_manager;
+ AdwStyleManager *style_manager;
G_OBJECT_CLASS (kgx_window_parent_class)->constructed (object);
application = gtk_window_get_application (GTK_WINDOW (self));
- style_manager = hdy_style_manager_get_default ();
+ style_manager = adw_style_manager_get_default ();
g_object_bind_property (application, "theme",
self->pages, "theme",
@@ -179,21 +179,20 @@ delete_response (GtkWidget *dlg,
int response,
KgxWindow *self)
{
- gtk_widget_destroy (dlg);
+ gtk_window_destroy (GTK_WINDOW (dlg));
if (response == GTK_RESPONSE_OK) {
self->close_anyway = TRUE;
- gtk_widget_destroy (GTK_WIDGET (self));
+ gtk_window_destroy (GTK_WINDOW (self));
}
}
static gboolean
-kgx_window_delete_event (GtkWidget *widget,
- GdkEventAny *event)
+kgx_window_close_request (GtkWindow *window)
{
- KgxWindow *self = KGX_WINDOW (widget);
+ KgxWindow *self = KGX_WINDOW (window);
GtkWidget *dlg;
g_autoptr (GPtrArray) children = NULL;
@@ -230,51 +229,32 @@ active_changed (GObject *object, GParamSpec *pspec, gpointer data)
}
-static gboolean
-key_press_event (GtkWidget *widget,
- GdkEventKey *event,
- KgxWindow *self)
+static void
+state_or_size_changed (KgxWindow *self)
{
- GdkModifierType default_modifiers = gtk_accelerator_get_default_mod_mask ();
- guint keyval;
- GdkModifierType state;
- GdkModifierType consumed;
- GdkKeymap *keymap;
-
- gdk_event_get_state ((GdkEvent *) event, &state);
-
- keymap = gdk_keymap_get_for_display (gtk_widget_get_display (widget));
+ GdkSurface *surface = gtk_native_get_surface (GTK_NATIVE (self));
+ GdkToplevelState state = gdk_toplevel_get_state (GDK_TOPLEVEL (surface));
- gdk_keymap_translate_keyboard_state (keymap,
- event->hardware_keycode,
- state,
- event->group,
- &keyval, NULL, NULL, &consumed);
+ self->is_maximized_or_tiled =
+ (state & (GDK_TOPLEVEL_STATE_FULLSCREEN |
+ GDK_TOPLEVEL_STATE_MAXIMIZED |
+ GDK_TOPLEVEL_STATE_TILED |
+ GDK_TOPLEVEL_STATE_TOP_TILED |
+ GDK_TOPLEVEL_STATE_RIGHT_TILED |
+ GDK_TOPLEVEL_STATE_BOTTOM_TILED |
+ GDK_TOPLEVEL_STATE_LEFT_TILED)) > 0;
- state &= ~consumed & default_modifiers;
+ g_object_set (self->pages, "opaque", self->is_maximized_or_tiled, NULL);
- /* Override some shortcuts from HdyTabView:shortcut-widget back, as they are
- * needed for terminal apps. This should be fixed on libhandy side, but would
- * likely require API changes, so carry this for now.
- *
- * See https://gitlab.gnome.org/GNOME/libhandy/-/issues/422
- */
- if ((((keyval == GDK_KEY_Page_Up ||
- keyval == GDK_KEY_KP_Page_Up ||
- keyval == GDK_KEY_Page_Down ||
- keyval == GDK_KEY_KP_Page_Down) &&
- kgx_pages_count (KGX_PAGES (self->pages)) <= 1) ||
- keyval == GDK_KEY_Home ||
- keyval == GDK_KEY_KP_Home ||
- keyval == GDK_KEY_End ||
- keyval == GDK_KEY_KP_End) &&
- (state == GDK_CONTROL_MASK ||
- state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))) {
- return kgx_pages_key_press_event (KGX_PAGES (self->pages),
- (GdkEvent *) event);
+ if (self->is_maximized_or_tiled) {
+ gtk_widget_add_css_class (GTK_WIDGET (self), "opaque");
+ } else {
+ gtk_widget_remove_css_class (GTK_WIDGET (self), "opaque");
}
- return GDK_EVENT_PROPAGATE;
+ gtk_window_get_default_size (GTK_WINDOW (self),
+ &self->current_width,
+ &self->current_height);
}
@@ -304,39 +284,33 @@ static void
status_changed (GObject *object, GParamSpec *pspec, gpointer data)
{
KgxWindow *self = KGX_WINDOW (object);
- GtkStyleContext *context;
KgxStatus status;
- context = gtk_widget_get_style_context (GTK_WIDGET (self));
-
status = kgx_pages_current_status (KGX_PAGES (self->pages));
if (status & KGX_REMOTE) {
- gtk_style_context_add_class (context, KGX_WINDOW_STYLE_REMOTE);
+ gtk_widget_add_css_class (GTK_WIDGET (self), KGX_WINDOW_STYLE_REMOTE);
} else {
- gtk_style_context_remove_class (context, KGX_WINDOW_STYLE_REMOTE);
+ gtk_widget_remove_css_class (GTK_WIDGET (self), KGX_WINDOW_STYLE_REMOTE);
}
if (status & KGX_PRIVILEGED) {
- gtk_style_context_add_class (context, KGX_WINDOW_STYLE_ROOT);
+ gtk_widget_add_css_class (GTK_WIDGET (self), KGX_WINDOW_STYLE_ROOT);
} else {
- gtk_style_context_remove_class (context, KGX_WINDOW_STYLE_ROOT);
+ gtk_widget_remove_css_class (GTK_WIDGET (self), KGX_WINDOW_STYLE_ROOT);
}
}
static void
-extra_drag_data_received (HdyTabBar *bar,
- HdyTabPage *page,
- GdkDragContext *context,
- GtkSelectionData *selection_data,
- guint info,
- guint time,
- KgxWindow *self)
+extra_drag_drop (AdwTabBar *bar,
+ AdwTabPage *page,
+ GValue *value,
+ KgxWindow *self)
{
- KgxTab *tab = KGX_TAB (hdy_tab_page_get_child (page));
+ KgxTab *tab = KGX_TAB (adw_tab_page_get_child (page));
- kgx_tab_accept_drop (tab, selection_data);
+ kgx_tab_accept_drop (tab, value);
}
@@ -353,44 +327,41 @@ new_tab_cb (KgxTabSwitcher *switcher,
}
-static gboolean
-kgx_window_window_state_event (GtkWidget *widget,
- GdkEventWindowState *event)
+static void
+kgx_window_realize (GtkWidget *widget)
{
KgxWindow *self = KGX_WINDOW (widget);
+ GdkSurface *surface;
- self->is_maximized_or_tiled =
- (event->new_window_state & (GDK_WINDOW_STATE_FULLSCREEN |
- GDK_WINDOW_STATE_MAXIMIZED |
- GDK_WINDOW_STATE_TILED |
- GDK_WINDOW_STATE_TOP_TILED |
- GDK_WINDOW_STATE_RIGHT_TILED |
- GDK_WINDOW_STATE_BOTTOM_TILED |
- GDK_WINDOW_STATE_LEFT_TILED)) > 0;
+ GTK_WIDGET_CLASS (kgx_window_parent_class)->realize (widget);
- g_object_set (self->pages, "opaque", self->is_maximized_or_tiled, NULL);
+ surface = gtk_native_get_surface (GTK_NATIVE (self));
- if (self->is_maximized_or_tiled)
- gtk_style_context_add_class (gtk_widget_get_style_context (widget), "opaque");
- else
- gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "opaque");
+ g_signal_connect_swapped (surface, "notify::state",
+ G_CALLBACK (state_or_size_changed), self);
+ g_signal_connect_swapped (self, "notify::default-width",
+ G_CALLBACK (state_or_size_changed), self);
+ g_signal_connect_swapped (self, "notify::default-height",
+ G_CALLBACK (state_or_size_changed), self);
- return GTK_WIDGET_CLASS (kgx_window_parent_class)->window_state_event (widget, event);
+ state_or_size_changed (self);
}
static void
-kgx_window_size_allocate (GtkWidget *widget,
- GtkAllocation *alloc)
+kgx_window_unrealize (GtkWidget *widget)
{
KgxWindow *self = KGX_WINDOW (widget);
+ GdkSurface *surface = gtk_native_get_surface (GTK_NATIVE (self));
- GTK_WIDGET_CLASS (kgx_window_parent_class)->size_allocate (widget, alloc);
+ g_signal_handlers_disconnect_by_func (surface,
+ G_CALLBACK (state_or_size_changed),
+ self);
+ g_signal_handlers_disconnect_by_func (self,
+ G_CALLBACK (state_or_size_changed),
+ self);
- if (!self->is_maximized_or_tiled)
- gtk_window_get_size (GTK_WINDOW (self),
- &self->current_width,
- &self->current_height);
+ GTK_WIDGET_CLASS (kgx_window_parent_class)->unrealize (widget);
}
@@ -399,15 +370,17 @@ kgx_window_class_init (KgxWindowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkWindowClass *window_class = GTK_WINDOW_CLASS (klass);
object_class->constructed = kgx_window_constructed;
object_class->dispose = kgx_window_dispose;
object_class->set_property = kgx_window_set_property;
object_class->get_property = kgx_window_get_property;
- widget_class->delete_event = kgx_window_delete_event;
- widget_class->window_state_event = kgx_window_window_state_event;
- widget_class->size_allocate = kgx_window_size_allocate;
+ widget_class->realize = kgx_window_realize;
+ widget_class->unrealize = kgx_window_unrealize;
+
+ window_class->close_request = kgx_window_close_request;
/**
* KgxWindow:application:
@@ -426,7 +399,7 @@ kgx_window_class_init (KgxWindowClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
KGX_APPLICATION_PATH "kgx-window.ui");
- gtk_widget_class_bind_template_child (widget_class, KgxWindow, header_bar);
+ gtk_widget_class_bind_template_child (widget_class, KgxWindow, window_title);
gtk_widget_class_bind_template_child (widget_class, KgxWindow, exit_info);
gtk_widget_class_bind_template_child (widget_class, KgxWindow, exit_message);
gtk_widget_class_bind_template_child (widget_class, KgxWindow, theme_switcher);
@@ -435,13 +408,13 @@ kgx_window_class_init (KgxWindowClass *klass)
gtk_widget_class_bind_template_child (widget_class, KgxWindow, tab_button);
gtk_widget_class_bind_template_child (widget_class, KgxWindow, tab_switcher);
gtk_widget_class_bind_template_child (widget_class, KgxWindow, pages);
+ gtk_widget_class_bind_template_child (widget_class, KgxWindow, primary_menu);
gtk_widget_class_bind_template_callback (widget_class, active_changed);
- gtk_widget_class_bind_template_callback (widget_class, key_press_event);
gtk_widget_class_bind_template_callback (widget_class, zoom);
gtk_widget_class_bind_template_callback (widget_class, status_changed);
- gtk_widget_class_bind_template_callback (widget_class, extra_drag_data_received);
+ gtk_widget_class_bind_template_callback (widget_class, extra_drag_drop);
gtk_widget_class_bind_template_callback (widget_class, new_tab_cb);
}
@@ -625,11 +598,7 @@ static void
kgx_window_init (KgxWindow *self)
{
g_autoptr (GtkWindowGroup) group = NULL;
- g_autoptr (GtkTargetList) target_list = NULL;
g_autoptr (GPropertyAction) pact = NULL;
- #ifdef IS_DEVEL
- GtkStyleContext *context;
- #endif
g_type_ensure (KGX_TYPE_TAB_BUTTON);
g_type_ensure (KGX_TYPE_TAB_SWITCHER);
@@ -648,8 +617,7 @@ kgx_window_init (KgxWindow *self)
g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (pact));
#ifdef IS_DEVEL
- context = gtk_widget_get_style_context (GTK_WIDGET (self));
- gtk_style_context_add_class (context, "devel");
+ gtk_widget_add_css_class (GTK_WIDGET (self), "devel");
#endif
g_object_bind_property_full (self->pages, "title",
@@ -659,11 +627,11 @@ kgx_window_init (KgxWindow *self)
NULL, NULL, NULL);
g_object_bind_property (self, "title",
- self->header_bar, "title",
+ self->window_title, "title",
G_BINDING_SYNC_CREATE);
g_object_bind_property_full (self->pages, "path",
- self->header_bar, "subtitle",
+ self->window_title, "subtitle",
G_BINDING_SYNC_CREATE,
update_subtitle,
NULL, NULL, NULL);
@@ -678,17 +646,13 @@ kgx_window_init (KgxWindow *self)
self->tab_switcher, "view",
G_BINDING_SYNC_CREATE);
- target_list = gtk_target_list_new (NULL, 0);
- gtk_target_list_add_text_targets (target_list, 0);
-
- hdy_tab_bar_set_extra_drag_dest_targets (HDY_TAB_BAR (self->tab_bar),
- target_list);
+ adw_tab_bar_setup_extra_drop_target (ADW_TAB_BAR (self->tab_bar),
+ GDK_ACTION_COPY,
+ (GType[1]) { G_TYPE_STRING }, 1);
group = gtk_window_group_new ();
gtk_window_group_add_window (group, GTK_WINDOW (self));
- kgx_pages_set_shortcut_widget (KGX_PAGES (self->pages), GTK_WIDGET (self));
-
self->tab_actions = G_ACTION_MAP (g_simple_action_group_new ());
g_action_map_add_action_entries (self->tab_actions,
tab_entries,
diff --git a/src/kgx-window.h b/src/kgx-window.h
index c79661c..94bff51 100644
--- a/src/kgx-window.h
+++ b/src/kgx-window.h
@@ -19,7 +19,7 @@
#pragma once
#include <gtk/gtk.h>
-#include "handy.h"
+#include <adwaita.h>
#include "kgx-terminal.h"
#include "kgx-process.h"
@@ -61,7 +61,7 @@ typedef enum /*< enum,prefix=KGX >*/
* @last_rows: the row count last time we received #GtkWidget::size-allocate
* @timeout: the id of the #GSource used to hide the statusbar
* @close_anyway: ignore running children and close without prompt
- * @header_bar: the #HdyHeaderBar that the styles are applied to
+ * @header_bar: the #GtkHeaderBar that the styles are applied to
* @search_entry: the #GtkSearchEntry inside @search_bar
* @search_bar: the windows #GtkSearchBar
* @exit_info: the #GtkRevealer hat wraps @exit_message
@@ -73,7 +73,7 @@ typedef enum /*< enum,prefix=KGX >*/
struct _KgxWindow
{
/*< private >*/
- HdyApplicationWindow parent_instance;
+ AdwApplicationWindow parent_instance;
/*< public >*/
KgxTheme theme;
@@ -86,16 +86,16 @@ struct _KgxWindow
gboolean close_anyway;
/* Template widgets */
- GtkWidget *header_bar;
+ GtkWidget *window_title;
GtkWidget *exit_info;
GtkWidget *exit_message;
GtkWidget *theme_switcher;
GtkWidget *zoom_level;
- GtkWidget *about_item;
GtkWidget *tab_bar;
GtkWidget *tab_button;
GtkWidget *tab_switcher;
GtkWidget *pages;
+ GMenu *primary_menu;
int current_width;
int current_height;
@@ -104,7 +104,7 @@ struct _KgxWindow
GActionMap *tab_actions;
};
-G_DECLARE_FINAL_TYPE (KgxWindow, kgx_window, KGX, WINDOW, HdyApplicationWindow)
+G_DECLARE_FINAL_TYPE (KgxWindow, kgx_window, KGX, WINDOW, AdwApplicationWindow)
GFile *kgx_window_get_working_dir (KgxWindow *self);
void kgx_window_show_status (KgxWindow *self,
diff --git a/src/kgx-window.ui b/src/kgx-window.ui
index be7ad83..b3ad88d 100644
--- a/src/kgx-window.ui
+++ b/src/kgx-window.ui
@@ -1,199 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.20"/>
- <object class="GtkPopoverMenu" id="popover">
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="margin">10</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="KgxThemeSwitcher" id="theme_switcher">
- <property name="visible">True</property>
- <property name="margin-bottom">12</property>
- </object>
- </child>
- <child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="orientation">horizontal</property>
- <property name="margin-bottom">6</property>
- <property name="homogeneous">True</property>
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <property name="action-name">app.zoom-out</property>
- <property name="tooltip-text" translatable="yes">Shrink Text</property>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="icon-name">zoom-out-symbolic</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <property name="action-name">app.zoom-normal</property>
- <property name="tooltip-text" translatable="yes">Reset Size</property>
- <child>
- <object class="GtkLabel" id="zoom_level">
- <property name="visible">True</property>
- <property name="width_chars">5</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkButton">
- <property name="visible">True</property>
- <property name="action-name">app.zoom-in</property>
- <property name="tooltip-text" translatable="yes">Enlarge Text</property>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="icon-name">zoom-in-symbolic</property>
- </object>
- </child>
- </object>
- </child>
- <style>
- <class name="linked"/>
- </style>
- </object>
- </child>
- <child>
- <object class="GtkSeparator">
- <property name="visible">True</property>
- </object>
- </child>
- <child>
- <object class="GtkModelButton">
- <property name="visible">True</property>
- <property name="text" translatable="yes">_New Window</property>
- <property name="action-name">win.new-window</property>
- </object>
- </child>
- <child>
- <object class="GtkSeparator">
- <property name="visible">True</property>
- </object>
- </child>
- <child>
- <object class="GtkModelButton">
- <property name="visible">True</property>
- <property name="text" translatable="yes">_Keyboard Shortcuts</property>
- <property name="action-name">win.show-help-overlay</property>
- </object>
- </child>
- <child>
- <object class="GtkModelButton" id="about_item">
- <property name="visible">True</property>
- <property name="text" translatable="yes">_About Console</property>
- <property name="tooltip-text" translatable="yes">About this Program</property>
- <property name="action-name">win.about</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- <template class="KgxWindow" parent="HdyApplicationWindow">
+ <requires lib="gtk" version="4.0"/>
+ <menu id="primary_menu">
+ <section>
+ <item>
+ <attribute name="custom">theme-switcher</attribute>
+ </item>
+ <item>
+ <attribute name="custom">zoom-controls</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_New Window</attribute>
+ <attribute name="action">win.new-window</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">_About Console</attribute>
+ <attribute name="action">win.about</attribute>
+ </item>
+ </section>
+ </menu>
+ <template class="KgxWindow" parent="AdwApplicationWindow">
<signal name="notify::is-active" handler="active_changed" swapped="no"/>
- <signal name="key-press-event" handler="key_press_event" swapped="no"/>
- <child>
+ <property name="content">
<object class="KgxTabSwitcher" id="tab_switcher">
- <property name="visible">1</property>
<signal name="new-tab" handler="new_tab_cb" swapped="no"/>
- <child>
+ <property name="child">
<object class="GtkBox">
- <property name="visible">1</property>
<property name="orientation">vertical</property>
<child>
- <object class="HdyHeaderBar" id="header_bar">
- <property name="visible">1</property>
- <property name="title" translatable="yes">King’s Cross</property>
- <property name="show-close-button">1</property>
- <child>
+ <object class="GtkHeaderBar" id="header_bar">
+ <property name="title-widget">
+ <object class="AdwWindowTitle" id="window_title">
+ <property name="title" translatable="yes">King’s Cross</property>
+ </object>
+ </property>
+ <child type="start">
<object class="GtkToggleButton">
- <property name="visible">1</property>
<property name="can-focus">0</property>
<property name="receives-default">0</property>
<property name="action-name">win.find</property>
<property name="tooltip-text" translatable="yes">Find in Terminal</property>
- <child>
- <object class="GtkImage">
- <property name="visible">1</property>
- <property name="icon-name">edit-find-symbolic</property>
- </object>
- </child>
+ <property name="icon-name">edit-find-symbolic</property>
</object>
- <packing>
- <property name="pack-type">start</property>
- </packing>
</child>
- <child>
+ <child type="end">
<object class="GtkMenuButton">
- <property name="visible">1</property>
<property name="can-focus">0</property>
<property name="receives-default">1</property>
- <property name="popover">popover</property>
<property name="tooltip-text" translatable="yes">Menu</property>
- <child>
- <object class="GtkImage">
- <property name="visible">1</property>
- <property name="icon-name">open-menu-symbolic</property>
+ <property name="icon-name">open-menu-symbolic</property>
+ <property name="popover">
+ <object class="GtkPopoverMenu">
+ <property name="menu-model">primary_menu</property>
+ <child type="theme-switcher">
+ <object class="KgxThemeSwitcher" id="theme_switcher">
+ <property name="margin-bottom">6</property>
+ </object>
+ </child>
+ <child type="zoom-controls">
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <object class="GtkButton">
+ <property name="action-name">app.zoom-out</property>
+ <property name="icon-name">zoom-out-symbolic</property>
+ <property name="tooltip-text" translatable="yes">Shrink Text</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="action-name">app.zoom-normal</property>
+ <property name="tooltip-text" translatable="yes">Reset Size</property>
+ <child>
+ <object class="GtkLabel" id="zoom_level">
+ <property name="width_chars">5</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="action-name">app.zoom-in</property>
+ <property name="icon-name">zoom-in-symbolic</property>
+ <property name="tooltip-text" translatable="yes">Enlarge Text</property>
+ </object>
+ </child>
+ <style>
+ <class name="linked"/>
+ </style>
+ </object>
+ </child>
</object>
- </child>
+ </property>
</object>
- <packing>
- <property name="pack-type">end</property>
- </packing>
</child>
- <child>
+ <child type="end">
<object class="KgxTabButton" id="tab_button">
<property name="visible" bind-source="tab_switcher" bind-property="narrow"
bind-flags="sync-create"/>
<property name="action-name">win.tab-switcher</property>
</object>
- <packing>
- <property name="pack-type">end</property>
- </packing>
</child>
- <child>
+ <child type="end">
<object class="GtkButton">
<property name="visible" bind-source="tab_switcher" bind-property="narrow"
bind-flags="sync-create|invert-boolean"/>
<property name="can-focus">0</property>
<property name="receives-default">0</property>
<property name="action-name">win.new-tab</property>
<property name="tooltip-text" translatable="yes">New Tab</property>
- <child>
- <object class="GtkImage">
- <property name="visible">1</property>
- <property name="icon-name">tab-new-symbolic</property>
- </object>
- </child>
+ <property name="icon-name">tab-new-symbolic</property>
</object>
- <packing>
- <property name="pack-type">end</property>
- </packing>
</child>
</object>
</child>
<child>
<object class="GtkRevealer">
- <property name="visible">1</property>
<property name="reveal-child" bind-source="tab_switcher" bind-property="narrow"
bind-flags="sync-create|invert-boolean"/>
- <child>
- <object class="HdyTabBar" id="tab_bar">
- <property name="visible">1</property>
- <signal name="extra-drag-data-received" handler="extra_drag_data_received" swapped="no"/>
+ <property name="child">
+ <object class="AdwTabBar" id="tab_bar">
+ <signal name="extra-drag-drop" handler="extra_drag_drop" swapped="no"/>
</object>
- </child>
+ </property>
</object>
</child>
<child>
<object class="KgxPages" id="pages">
- <property name="visible">1</property>
<property name="is-active" bind-source="KgxWindow" bind-property="is-active"
bind-flags="sync-create" />
<signal name="zoom" handler="zoom" swapped="no"/>
<signal name="notify::status" handler="status_changed" swapped="yes" />
@@ -201,15 +140,13 @@
</child>
<child>
<object class="GtkRevealer" id="exit_info">
- <property name="visible">1</property>
<property name="reveal_child">False</property>
- <child>
+ <property name="child">
<object class="GtkBox">
- <property name="visible">1</property>
+ <property name="can_focus">False</property>
<property name="valign">end</property>
<child>
<object class="GtkLabel" id="exit_message">
- <property name="visible">True</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
</object>
@@ -218,13 +155,13 @@
<class name="exit-info"/>
</style>
</object>
- </child>
+ </property>
</object>
</child>
</object>
- </child>
+ </property>
</object>
- </child>
+ </property>
<style>
<class name="terminal-window"/>
</style>
diff --git a/src/kgx.gresource.xml.in b/src/kgx.gresource.xml.in
index c5b0414..bb82543 100644
--- a/src/kgx.gresource.xml.in
+++ b/src/kgx.gresource.xml.in
@@ -12,8 +12,6 @@
<file compressed="true">kgx-simple-tab.ui</file>
<file compressed="true">styles-light.css</file>
<file compressed="true">styles-dark.css</file>
- <file compressed="true">styles-hc.css</file>
- <file compressed="true">styles-hc-dark.css</file>
<file compressed="true">logo.txt</file>
<file preprocess="xml-stripblanks">icons/scalable/status/status-privileged-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/scalable/status/status-regular-symbolic.svg</file>
diff --git a/src/menus.ui b/src/menus.ui
index 53d115a..fd6ff18 100644
--- a/src/menus.ui
+++ b/src/menus.ui
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="3.20"/>
+ <requires lib="gtk" version="4.0"/>
<menu id="context-menu">
<section>
<item>
diff --git a/src/meson.build b/src/meson.build
index f1a16be..0820d73 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -35,9 +35,9 @@ kgx_sources = [
kgx_deps = [
dependency('gio-2.0', version: '>= 2.66'),
- dependency('gtk+-3.0', version: '>= 3.24'),
- dependency('libhandy-1', version: '>= 1.5', fallback: ['handy', 'libhandy_dep']),
- dependency('vte-2.91', version: '>= 0.67', fallback: ['vte', 'libvte_gtk3_dep']),
+ dependency('gtk4'),
+ dependency('libadwaita-1', version: '>= 1.2.alpha', fallback: ['adwaita', 'libadwaita_dep']),
+ dependency('vte-2.91-gtk4', version: '>= 0.69.91', fallback: ['vte', 'libvte_gtk4_dep']),
dependency('libgtop-2.0'),
dependency('libpcre2-8', version: '>= 10.32'),
dependency('gsettings-desktop-schemas'),
@@ -66,8 +66,14 @@ kgx_enums = gnome.mkenums_simple('kgx-enums',
'kgx-tab.h'
])
+kgx_cargs = [
+ '-DGDK_VERSION_MIN_REQUIRED=@0@'.format(gtk_ver),
+ '-DGDK_VERSION_MAX_ALLOWED=@0@'.format(gtk_ver)
+]
+
kgx_lib = static_library (bin_name,
kgx_sources + kgx_enums,
+ c_args: kgx_cargs,
dependencies: kgx_deps,
)
kgx_inc = include_directories('.')
@@ -80,5 +86,6 @@ kgx_dep = declare_dependency (sources: [config_h, kgx_enums],
executable( bin_name,
'main.c',
dependencies: kgx_dep,
+ c_args: kgx_cargs,
install: true,
)
diff --git a/src/styles/_styles.scss b/src/styles/_styles.scss
index 049ecb2..b582dcd 100644
--- a/src/styles/_styles.scss
+++ b/src/styles/_styles.scss
@@ -1,56 +1,52 @@
-@import 'definitions';
-@import 'drawing';
+@function themecolor($s) {
+ @return unquote("@" + "#{$s}");
+}
+
+@function gtkalpha($c,$a) {
+ @return unquote("alpha(#{$c},#{$a})");
+}
+
+@mixin colored_header($bg, $fg, $backdrop) {
+ headerbar,
+ searchbar > revealer > box,
+ tabbar > revealer > box {
+ background-color: $bg;
+ color: $fg;
+
+ &:backdrop {
+ background-color: $backdrop;
+ }
+ }
+}
.terminal-window {
background: transparent;
&.root {
- $variant: 'dark';
- $window_color: darken(#a51d2d, 15%);
- @import 'recoloring';
+ @include colored_header(darken(#a51d2d, 15%), white, darken(#a51d2d, 18%));
}
&.remote {
- $variant: 'dark';
- $window_color: darken(#613583, 10%);
- @import 'recoloring';
- }
-
- scrolledwindow.terminal overshoot {
- $sides: "top", "bottom", "left", "right";
-
- @each $side in $sides {
- &.#{$side} {
- @include overshoot($side, normal, #cccccc);
-
- &:backdrop { @include overshoot($side, backdrop, #cccccc); }
- }
- }
+ @include colored_header(darken(#613583, 10%), white, darken(#613583, 13%));
}
}
// Taken from nautilus
.floating-bar {
padding: 6px;
- background-color: themecolor(theme_base_color);
- border-width: 1px;
- border-style: solid solid none;
- background-clip: padding-box;
- border-color: transparentize(black, if($variant == 'light', .8, .25));
- border-radius: 6px 6px 0 0;
-
- &:backdrop {
- background-color: themecolor(theme_unfocused_base_color);
- }
+ background-color: themecolor(view_bg_color);
+ color: themecolor(view_fg_color);
+ box-shadow: 0 0 0 1px themecolor(borders);
+ margin-top: 1px;
- &:dir(rtl) { // axes left border and border radius
- border-left-style: none;
- border-top-left-radius: 0;
+ &:dir(rtl) {
+ border-top-right-radius: 6px;
+ margin-right: 1px;
}
- &:dir(ltr) { // axes right border and border radius
- border-right-style: none;
- border-top-right-radius: 0;
+ &:dir(ltr) {
+ border-top-left-radius: 6px;
+ margin-left: 1px;
}
button {
@@ -81,33 +77,25 @@
background: rgba(13, 54, 104, 0.96);
color: #ffffff;
- label:backdrop {
- color: #ffffff;
- }
-
.error & {
border-top: 2px solid #ed333b;
background: rgba(104, 13, 13, 0.96);
}
}
-label.numeric {
- font-feature-settings: "tnum";
-}
-
box.tab:drop(active) {
- outline: 1px solid $drop_target_color;
+ outline: 1px solid themecolor(accent_bg_color);
outline-offset: -1px;
- -gtk-outline-radius: 0;
window:not(.tiled)
:not(.tiled-top)
:not(.tiled-bottom)
:not(.tiled-left)
:not(.tiled-right)
+ :not(.fullscreen)
:not(.maximized) & {
- -gtk-outline-bottom-left-radius: 8px;
- -gtk-outline-bottom-right-radius: 8px;
+ border-bottom-left-radius: 12px;
+ border-bottom-right-radius: 12px;
}
}
@@ -131,23 +119,8 @@ box.tab:drop(active) {
}
@mixin flat_round_button() {
- background: none;
- border: none;
- box-shadow: none;
- -gtk-icon-shadow: none;
- text-shadow: none;
border-radius: 99px;
- -gtk-outline-radius: 99px;
- color: inherit;
padding: 0;
-
- &:hover {
- background: gtkalpha(currentColor, .15);
-
- &:active {
- background: gtkalpha(black, .2);
- }
- }
}
.tab-switcher {
@@ -156,59 +129,32 @@ box.tab:drop(active) {
list {
padding-top: 48px;
padding-bottom: 84px;
+ background-color: themecolor(popover_bg_color);
+ color: themecolor(popover_fg_color);
row {
- background: none;
- border: none;
- box-shadow: none;
- padding: 0;
- outline-color: transparent;
- color: themecolor(theme_text_color);
-
- .content {
- min-height: 40px;
- margin-left: 5px;
- margin-right: 5px;
- margin-bottom: 2px;
- padding: 3px;
- border-radius: 5px;
- -gtk-outline-radius: 5px;
- border: none;
- box-shadow: none;
- transition: 200ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
-
- &:dir(ltr) { padding-left: 11px; }
- &:dir(rtl) { padding-right: 11px; }
- }
+ min-height: 40px;
+ padding: 3px;
- &:selected .content {
- background: gtkalpha(currentColor, .06);
- }
-
- &:hover .content {
- background: gtkalpha(currentColor, .1);
- }
-
- &:active .content {
- background: gtkalpha(black, .15);
- }
+ &:dir(ltr) { padding-left: 11px; }
+ &:dir(rtl) { padding-right: 11px; }
&.needs-attention {
- // Blue 4 | Blue 1
- color: if($variant == 'light', #1c71d8, #99c1f1);
+ color: themecolor(accent_color);
}
.close-btn,
.indicator-btn {
- @include flat_round_button();
min-width: 36px;
min-height: 36px;
+ border-radius: 99px;
+ padding: 0;
}
}
}
.collapse-button {
- @include flat_round_button();
+ border-radius: 99px;
padding: 6px 30px;
margin: 6px;
}
@@ -217,7 +163,6 @@ box.tab:drop(active) {
min-width: 48px;
min-height: 48px;
border-radius: 100%;
- -gtk-outline-radius: 100%;
padding: 0;
margin: 18px;
}
@@ -225,56 +170,48 @@ box.tab:drop(active) {
themeswitcher {
$_light_bg: white;
- $_light_fg: transparentize(black, .1);
- $_dark_bg: #2e3436;
+ $_light_fg: transparentize(black, .2);
+ $_dark_bg: #1e1e1e;
$_dark_fg: white;
- $_selected_color: #3584e4;
+
+ padding: 6px;
.check {
- background: $_selected_color;
+ background: themecolor(accent_bg_color);
color: white;
padding: 2px;
border-radius: 17px;
+ margin: 3px;
}
/* Adapted from
https://gitlab.gnome.org/GNOME/gnome-text-editor/-/blob/bf8c0c249f06a0be69e65aed3b786ba02a9f999e/src/TextEditor.css#L51
*/
- radiobutton {
- -gtk-outline-radius: 100px;
+ checkbutton {
outline-offset: 1px;
transition: none;
radio {
-gtk-icon-source: none;
background: none;
- box-shadow: none;
padding: 12px;
min-height: 24px;
min-width: 24px;
border: none;
outline-color: currentColor;
transition: none;
-
- @if $high_contrast {
- @if $variant == 'light' {
- box-shadow: inset 0 0 0 1px transparentize(black, .3);
- } @else {
- box-shadow: inset 0 0 0 1px transparentize(white, .7);
- }
- } @else {
- @if $variant == 'light' {
- box-shadow: inset 0 0 0 1px transparentize(black, .8);
- } @else {
- box-shadow: 0 0 0 1px transparentize(black, .3);
- }
- }
+ box-shadow: inset 0 0 0 1px themecolor(borders);
&:checked {
- box-shadow: inset 0 0 0 2px $_selected_color;
+ box-shadow: inset 0 0 0 2px themecolor(accent_bg_color);
}
}
&.system radio {
- color: $_light_fg;
+ @if $variant == 'dark' {
+ color: $_dark_fg;
+ } else {
+ color: $_light_fg;
+ }
+
background: linear-gradient(-45deg, $_dark_bg 49.99%, $_light_bg 50.01%);
}
diff --git a/src/styles/meson.build b/src/styles/meson.build
index 0b3fab6..0528c97 100644
--- a/src/styles/meson.build
+++ b/src/styles/meson.build
@@ -8,8 +8,6 @@ if sassc.found()
styles = [
'styles-light',
'styles-dark',
- 'styles-hc',
- 'styles-hc-dark',
]
style_deps = []
@@ -25,9 +23,6 @@ if sassc.found()
sassc, sassc_opts, '@INPUT@', '@OUTPUT@',
],
depend_files: files([
- '_definitions.scss',
- '_drawing.scss',
- '_recoloring.scss',
'_styles.scss',
]),
),
diff --git a/subprojects/adwaita.wrap b/subprojects/adwaita.wrap
new file mode 100644
index 0000000..c06fb07
--- /dev/null
+++ b/subprojects/adwaita.wrap
@@ -0,0 +1,4 @@
+[wrap-git]
+directory=adwaita
+url=https://gitlab.gnome.org/GNOME/libadwaita.git
+revision=origin/main
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]