summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.meson18
-rw-r--r--bindings/gir/meson.build2
-rw-r--r--bindings/glade/meson.build2
-rw-r--r--doc/reference/Makefile.docs511
-rw-r--r--doc/reference/gtk3/meson.build55
-rw-r--r--doc/reference/gtk4/meson.build55
-rw-r--r--doc/reference/meson.build93
-rw-r--r--doc/reference/version.xml.in1
-rw-r--r--doc/reference/vte-docs.xml14
-rw-r--r--doc/reference/vte-overrides.txt.in (renamed from doc/reference/vte-overrides.txt)0
-rw-r--r--doc/reference/vte-sections.txt.in (renamed from doc/reference/vte-sections.txt)12
-rw-r--r--doc/reference/vte.types.in (renamed from doc/reference/vte.types)0
-rw-r--r--meson.build36
-rw-r--r--po/POTFILES.skip6
-rw-r--r--src/app/app-gtk4.gresource.xml24
-rw-r--r--src/app/app.cc636
-rw-r--r--src/app/appmenu-gtk4.ui33
-rw-r--r--src/app/meson.build33
-rw-r--r--src/app/search-popover-gtk3.ui1
-rw-r--r--src/app/search-popover-gtk4.ui169
-rw-r--r--src/app/window-gtk3.ui1
-rw-r--r--src/app/window-gtk4.ui185
-rw-r--r--src/cairo-glue.hh4
-rw-r--r--src/clipboard-gtk.cc39
-rw-r--r--src/clipboard-gtk.hh4
-rw-r--r--src/debug.h6
-rw-r--r--src/fonts-pangocairo.cc32
-rw-r--r--src/fonts-pangocairo.hh5
-rw-r--r--src/graphene-glue.hh48
-rw-r--r--src/gtk-glue.hh6
-rw-r--r--src/keymap.h5
-rw-r--r--src/meson.build104
-rw-r--r--src/vte.cc360
-rw-r--r--src/vte/meson.build107
-rw-r--r--src/vte/vte.h4
-rw-r--r--src/vte/vtedeprecated.h24
-rw-r--r--src/vte/vtemacros.h20
-rw-r--r--src/vte/vtepty.h10
-rw-r--r--src/vte/vteregex.h2
-rw-r--r--src/vte/vteterminal.h41
-rw-r--r--src/vte/vtetypebuiltins.h28
-rw-r--r--src/vteaccess.h6
-rw-r--r--src/vtedefines.hh3
-rw-r--r--src/vtegtk.cc408
-rw-r--r--src/vteinternal.hh71
-rw-r--r--src/vteseq.cc5
-rw-r--r--src/widget.cc561
-rw-r--r--src/widget.hh111
48 files changed, 3322 insertions, 579 deletions
diff --git a/Makefile.meson b/Makefile.meson
index 4917fb23..40bbdb42 100644
--- a/Makefile.meson
+++ b/Makefile.meson
@@ -15,8 +15,7 @@
srcdir=@srcdir@
builddir=@builddir@
-vte_gtk3_api_version = @vte_gtk3_api_version@
-vte_gtk4_api_version = @vte_gtk4_api_version@
+vte_api_version = @vte_api_version@
#
@@ -29,6 +28,18 @@ NINJA = ninja $(NJOBS)
all:
$(NINJA)
+gtk3:
+ $(NINJA) src/app/vte-$(vte_api_version)
+
+gtk4:
+ $(NINJA) src/app/vte-$(vte_api_version)-gtk4
+
+doc-gtk3:
+ $(NINJA) doc/reference/gtk3/meson.stamp
+
+doc-gtk4:
+ $(NINJA) doc/reference/gtk4/meson.stamp
+
check:
MESON_TESTTHREADS=$(NTHREADS) $(NINJA) test
@@ -38,8 +49,7 @@ clean:
coverage:
$(NINJA) coverage
-doc:
- $(NINJA) vte-$(vte_gtk3_api_version)-doc
+doc: doc-gtk3 doc-gtk4
install:
$(NINJA) install
diff --git a/bindings/gir/meson.build b/bindings/gir/meson.build
index 3793a430..0507e330 100644
--- a/bindings/gir/meson.build
+++ b/bindings/gir/meson.build
@@ -29,7 +29,7 @@ if get_option('gtk3')
includes: libvte_gtk3_gir_includes,
dependencies: libvte_gtk3_dep,
extra_args: '-DVTE_COMPILATION',
- nsversion: vte_gtk3_api_version,
+ nsversion: vte_api_version,
namespace: 'Vte',
export_packages: vte_gtk3_api_name,
header: 'vte' / 'vte.h',
diff --git a/bindings/glade/meson.build b/bindings/glade/meson.build
index 90d4672e..6bca2aea 100644
--- a/bindings/glade/meson.build
+++ b/bindings/glade/meson.build
@@ -19,7 +19,7 @@ cataloguedir = gladedir / 'catalogs'
pixmapdir = gladedir / 'pixmaps'
catalog_conf = configuration_data()
-catalog_conf.set('VTE_API_VERSION', vte_gtk3_api_version)
+catalog_conf.set('VTE_API_VERSION', vte_api_version)
catalog_conf.set('VERSION', vte_version)
configure_file(
diff --git a/doc/reference/Makefile.docs b/doc/reference/Makefile.docs
new file mode 100644
index 00000000..22fe3865
--- /dev/null
+++ b/doc/reference/Makefile.docs
@@ -0,0 +1,511 @@
+
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this library. If not, see <https://www.gnu.org/licenses/>.
+
+NULL =
+V ?= 1
+
+abs_srcdir ?= $(srcdir)
+abs_builddir ?= $(builddir)
+top_srcdir ?= $(abs_top_srcdir)
+top_builddir ?= $(abs_top_builddir)
+
+datadir ?= /usr/share
+
+CPP = cpp
+CPPFLAGS =
+
+GREP ?= grep
+GREPFLAGS =
+
+LN_S = ln -s
+
+PACKAGE ?= vte
+PACKAGE_BUGREPORT ?= https://gitlab.gnome.org/GNOME/vte/issues/
+PACKAGE_NAME ?= vte
+PACKAGE_STRING ?= vte
+PACKAGE_TARNAME ?= vte
+PACKAGE_URL ?= https://gitlab.gnome.org/GNOME/vte/
+PACKAGE_VERSION ?= $(VERSION)
+
+DOC_MODULE = vte-gtk$(VTE_GTK)
+
+DOC_MODULE_VERSION = $(VTE_API_VERSION)
+
+DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.xml
+
+DOC_SOURCE_DIR = \
+ $(top_srcdir)/src \
+ $(top_srcdir)/src/vte \
+ $(top_builddir)/src \
+ $(top_builddir)/src/vte \
+ $(NULL)
+
+SCANGOBJ_OPTIONS =
+
+SCAN_OPTIONS = \
+ --deprecated-guards="VTE_DISABLE_DEPRECATED" \
+ --ignore-decorators='_VTE_GNUC_NONNULL()|_VTE_PUBLIC|_VTE_DEPRECATED|_VTE_CXX_NOEXCEPT' \
+ $(NULL)
+
+MKDB_OPTIONS = \
+ --source-suffixes=c,cc,h,hh \
+ --xml-mode \
+ --output-format=xml \
+ --name-space=vte \
+ $(NULL)
+
+MKTMPL_OPTIONS =
+
+MKHTML_OPTIONS = \
+ --path="$(abs_builddir)" \
+ $(NULL)
+
+MKPDF_OPTIONS = \
+ --path="$(abs_builddir)" \
+ $(NULL)
+
+FIXXREF_OPTIONS = \
+ --extra-dir=$(CAIRO_PREFIX)/share/gtk-doc/html/cairo \
+ --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/glib \
+ --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/gobject \
+ --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/gio \
+ --extra-dir=$(PANGO_PREFIX)/share/gtk-doc/html/pango \
+ $(NULL)
+
+ifeq ($(VTE_GTK),3)
+FIXXREF_OPTIONS += \
+ --extra-dir=$(GTK_PREFIX)/share/gtk-doc/html/gdk3 \
+ --extra-dir=$(GTK_PREFIX)/share/gtk-doc/html/gtk3 \
+ $(NULL)
+endif
+
+ifeq ($(VTE_GTK),4)
+FIXXREF_OPTIONS += \
+ --extra-dir=$(GTK_PREFIX)/share/gtk-doc/html/graphene \
+ --extra-dir=$(GTK_PREFIX)/share/gtk-doc/html/gdk4 \
+ --extra-dir=$(GTK_PREFIX)/share/gtk-doc/html/gsk4 \
+ --extra-dir=$(GTK_PREFIX)/share/gtk-doc/html/gtk4 \
+ $(NULL)
+endif
+
+HFILE_GLOB = \
+ $(top_builddir)/src/vte/*.h \
+ $(top_srcdir)/src/vte/*.h \
+ $(NULL)
+
+CFILE_GLOB = \
+ $(top_builddir)/src/*.c \
+ $(top_srcdir)/src/*.c \
+ $(top_srcdir)/src/*.cc \
+ $(NULL)
+
+EXTRA_HFILES =
+
+IGNORE_HFILES = \
+ buffer.h \
+ caps.hh \
+ cell.hh \
+ config.h \
+ debug.h \
+ keymap.h \
+ marshal.h \
+ modes.hh \
+ modes-ecma.hh \
+ modes-private.hh \
+ parser.hh \
+ parser-arg.hh \
+ parser-c01.hh \
+ parser-charset.hh \
+ parser-charset-tables.hh \
+ parser-cmd.hh \
+ parser-csi.hh \
+ parser-dcs.hh \
+ parser-esc.hh \
+ parser-glue.hh \
+ parser-osc.hh \
+ parser-reply.hh \
+ parser-string.hh \
+ ring.hh \
+ tabstops.hh \
+ vteconv.h \
+ vtedraw.h \
+ vteinternal.hh \
+ vterowdata.hh \
+ vtestream-base.h \
+ vtestream-file.h \
+ vtestream.h \
+ vtetypebuiltins.h \
+ vteunistr.h \
+ $(NULL)
+
+HTML_IMAGES =
+
+content_files =
+
+expand_content_files =
+
+GTKDOC_CFLAGS = \
+ -DVTE_COMPILATION \
+ $(shell pkg-config --cflags --libs glib-2.0 gobject-2.0) \
+ $(NULL)
+
+VTE_LIB_PATH = $(shell dirname $(VTE_LIB))
+
+ifeq ($(VTE_GTK),3)
+VTE_LIB_NAME = vte-$(VTE_API_VERSION)
+endif
+ifeq ($(VTE_GTK),4)
+VTE_LIB_NAME = vte-$(VTE_API_VERSION)-gtk4
+endif
+
+GTKDOC_LIBS = \
+ -L$(VTE_LIB_PATH) -l$(VTE_LIB_NAME) \
+ $(shell pkg-config --libs --libs glib-2.0 gobject-2.0) \
+ $(NULL)
+
+# Rules for building gtk3/4 versions of the gtk-doc inputs
+
+AM_V_at = $(AM_V_at_$(V))
+AM_V_at_0 = @
+AM_V_at_1 =
+
+AM_V_GEN = $(AM_V_GEN_$(V))
+AM_V_GEN_0 = @echo " GEN " $@;
+AM_V_GEN_1 =
+
+vte-gtk$(VTE_GTK)-sections.txt: $(srcdir)/../vte-sections.txt.in
+ $(AM_V_GEN)$(CPP) -E $(CPPFLAGS) -DVTE_GTK=$(VTE_GTK) $< | $(GREP) $(GREPFLAGS) -Ev '^\s*#|^$$' > $@
+
+vte-gtk$(VTE_GTK)-overrides.txt: $(srcdir)/../vte-overrides.txt.in
+ $(AM_V_GEN)$(CPP) -E $(CPPFLAGS) -DVTE_GTK=$(VTE_GTK) $< | $(GREP) $(GREPFLAGS) -Ev '^\s*#|^$$' > $@ || true
+
+vte-gtk$(VTE_GTK).types: $(srcdir)/../vte.types.in
+ $(AM_V_GEN)$(CPP) -E -fpreprocessed $(CPPFLAGS) -DVTE_GTK=$(VTE_GTK) $< | $(GREP) $(GREPFLAGS) -Ev '^\s*#|^$$' > $@
+
+$(DOC_MAIN_SGML_FILE): $(srcdir)/../vte-docs.xml
+ $(AM_V_GEN)cp -f $< $@
+
+# The following is copied from gtk-doc, and adapted to work with
+# plain make instead of requiring automake.
+#
+# Copyright (C) 2003 James Henstridge
+# 2004-2007 Damon Chaplin
+# 2007-2017 Stefan Sauer
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+####################################
+# Everything below here is generic #
+####################################
+
+CC ?= cc
+CFLAGS ?=
+
+INSTALL = install -c
+INSTALL_DATA = $(INSTALL) -m 644
+
+GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(CPPFLAGS) $(CFLAGS)
+GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(CFLAGS) $(LDFLAGS)
+GTKDOC_RUN =
+
+GTKDOC_CHECK_PATH = gtkdoc-check
+GTKDOC_REBASE = gtkdoc-rebase
+
+MKDIR_P ?= mkdir -p
+
+# We set GPATH here; this gives us semantics for GNU make
+# which are more like other make's VPATH, when it comes to
+# whether a source that is a target of one rule is then
+# searched for in VPATH/GPATH.
+#
+GPATH = $(srcdir)
+
+HTML_DIR = $(datadir)/gtk-doc/html
+
+TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)
+
+SETUP_FILES = \
+ $(content_files) \
+ $(expand_content_files) \
+ $(DOC_MAIN_SGML_FILE) \
+ $(DOC_MODULE)-sections.txt \
+ $(DOC_MODULE)-overrides.txt
+
+SETUP_FILES_GENERATED = \
+ $(DOC_MODULE)-sections.txt \
+ $(DOC_MODULE)-overrides.txt \
+ $(DOC_MODULE).types \
+ $(DOC_MAIN_SGML_FILE)
+
+EXTRA_DIST = \
+ $(HTML_IMAGES) \
+ $(SETUP_FILES)
+
+DOC_STAMPS=setup-build.stamp scan-build.stamp sgml-build.stamp \
+ html-build.stamp pdf-build.stamp \
+ sgml.stamp html.stamp pdf.stamp
+
+SCANOBJ_FILES = \
+ $(DOC_MODULE).actions \
+ $(DOC_MODULE).args \
+ $(DOC_MODULE).hierarchy \
+ $(DOC_MODULE).interfaces \
+ $(DOC_MODULE).prerequisites \
+ $(DOC_MODULE).signals
+
+REPORT_FILES = \
+ $(DOC_MODULE)-undocumented.txt \
+ $(DOC_MODULE)-undeclared.txt \
+ $(DOC_MODULE)-unused.txt
+
+gtkdoc-check.test:
+ $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \
+ echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \
+ chmod +x $@
+
+CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test
+
+HTML_BUILD_STAMP=html-build.stamp
+#PDF_BUILD_STAMP=pdf-build.stamp
+PDF_BUILD_STAMP=
+
+all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
+.PHONY: all-gtk-doc
+
+all-local: all-gtk-doc
+
+docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
+
+$(REPORT_FILES): sgml-build.stamp
+
+#### setup ####
+
+GTK_DOC_V_SETUP=$(GTK_DOC_V_SETUP_$(V))
+GTK_DOC_V_SETUP_0=@echo " DOC Preparing build";
+GTK_DOC_V_SETUP_1=
+
+setup-build.stamp: $(SETUP_FILES_GENERATED)
+ -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
+ files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \
+ if test "x$$files" != "x" ; then \
+ for file in $$files ; do \
+ destdir=`dirname $(abs_builddir)/$$file`; \
+ test -d "$$destdir" || $(MKDIR_P) "$$destdir"; \
+ test -f $(abs_srcdir)/$$file && \
+ cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \
+ done; \
+ fi; \
+ fi
+ $(AM_V_at)touch setup-build.stamp
+
+#### scan ####
+
+GTK_DOC_V_SCAN=$(GTK_DOC_V_SCAN_$(V))
+GTK_DOC_V_SCAN_0=@echo " DOC Scanning header files";
+GTK_DOC_V_SCAN_1=
+
+GTK_DOC_V_INTROSPECT=$(GTK_DOC_V_INTROSPECT_$(V))
+GTK_DOC_V_INTROSPECT_0=@echo " DOC Introspecting gobjects";
+GTK_DOC_V_INTROSPECT_1=
+
+scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB)
+ $(GTK_DOC_V_SCAN)_source_dir='' ; \
+ for i in $(DOC_SOURCE_DIR) ; do \
+ _source_dir="$${_source_dir} --source-dir=$$i" ; \
+ done ; \
+ gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES)
+ $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \
+ scanobj_options=""; \
+ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \
+ if test "$$?" = "0"; then \
+ if test "x$(V)" = "x1"; then \
+ scanobj_options="--verbose"; \
+ fi; \
+ fi; \
+ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" LD_LIBRARY_PATH="$(VTE_LIB_PATH)" \
+ gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \
+ else \
+ for i in $(SCANOBJ_FILES) ; do \
+ test -f $$i || touch $$i ; \
+ done \
+ fi
+ $(AM_V_at)touch scan-build.stamp
+
+$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES): scan-build.stamp
+ @true
+
+#### xml ####
+
+GTK_DOC_V_XML=$(GTK_DOC_V_XML_$(V))
+GTK_DOC_V_XML_0=@echo " DOC Building XML";
+GTK_DOC_V_XML_1=
+
+sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent $(DOC_MAIN_SGML_FILE)
+ $(GTK_DOC_V_XML)_source_dir='' ; \
+ for i in $(DOC_SOURCE_DIR) ; do \
+ _source_dir="$${_source_dir} --source-dir=$$i" ; \
+ done ; \
+ gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS)
+ $(AM_V_at)touch sgml-build.stamp
+
+sgml.stamp: sgml-build.stamp
+ @true
+
+xml/gtkdocentities.ent:
+ $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \
+ echo "<!ENTITY package \"$(PACKAGE)\">"; \
+ echo "<!ENTITY package_bugreport \"$(PACKAGE_BUGREPORT)\">"; \
+ echo "<!ENTITY package_name \"$(PACKAGE_NAME)\">"; \
+ echo "<!ENTITY package_string \"$(PACKAGE_STRING)\">"; \
+ echo "<!ENTITY package_tarname \"$(PACKAGE_TARNAME)\">"; \
+ echo "<!ENTITY package_url \"$(PACKAGE_URL)\">"; \
+ echo "<!ENTITY package_version \"$(PACKAGE_VERSION)\">"; \
+ ) > $@
+
+
+#### html ####
+
+GTK_DOC_V_HTML=$(GTK_DOC_V_HTML_$(V))
+GTK_DOC_V_HTML_0=@echo " DOC Building HTML";
+GTK_DOC_V_HTML_1=
+
+GTK_DOC_V_XREF=$(GTK_DOC_V_XREF_$(V))
+GTK_DOC_V_XREF_0=@echo " DOC Fixing cross-references";
+GTK_DOC_V_XREF_1=
+
+GTKDOC_MKHTML = gtkdoc-mkhtml
+
+html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files)
+ $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \
+ mkhtml_options=""; \
+ $(GTKDOC_MKHTML) 2>&1 --help | grep >/dev/null "\-\-verbose"; \
+ if test "$$?" = "0"; then \
+ if test "x$(V)" = "x1"; then \
+ mkhtml_options="$$mkhtml_options --verbose"; \
+ fi; \
+ fi; \
+ $(GTKDOC_MKHTML) 2>&1 --help | grep >/dev/null "\-\-path"; \
+ if test "$$?" = "0"; then \
+ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \
+ fi; \
+ cd html && $(GTKDOC_MKHTML) $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
+ -@test "x$(HTML_IMAGES)" = "x" || \
+ for file in $(HTML_IMAGES) ; do \
+ test -f $(abs_srcdir)/$$file && cp $(abs_srcdir)/$$file $(abs_builddir)/html; \
+ test -f $(abs_builddir)/$$file && cp $(abs_builddir)/$$file $(abs_builddir)/html; \
+ test -f $$file && cp $$file $(abs_builddir)/html; \
+ done;
+ $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
+ $(AM_V_at)touch html-build.stamp
+
+#### pdf ####
+
+GTK_DOC_V_PDF=$(GTK_DOC_V_PDF_$(V))
+GTK_DOC_V_PDF_0=@echo " DOC Building PDF";
+GTK_DOC_V_PDF_1=
+
+pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files)
+ $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \
+ mkpdf_options=""; \
+ gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \
+ if test "$$?" = "0"; then \
+ if test "x$(V)" = "x1"; then \
+ mkpdf_options="$$mkpdf_options --verbose"; \
+ fi; \
+ fi; \
+ if test "x$(HTML_IMAGES)" != "x"; then \
+ for img in $(HTML_IMAGES); do \
+ part=`dirname $$img`; \
+ echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \
+ if test $$? != 0; then \
+ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \
+ fi; \
+ done; \
+ fi; \
+ gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS)
+ $(AM_V_at)touch pdf-build.stamp
+
+##############
+
+clean-local:
+ @rm -f *~ *.bak
+ @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \
+ rm -f $(DOC_MODULE).types; \
+ fi
+ @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \
+ rm -f $(DOC_MODULE)-sections.txt; \
+ fi
+
+distclean-local:
+ @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \
+ $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
+ @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
+ rm -f $(SETUP_FILES) $(DOC_MODULE).types; \
+ fi
+
+maintainer-clean-local:
+ @rm -rf xml html
+
+install-data-local:
+ @installfiles=`echo $(builddir)/html/*`; \
+ if test "$$installfiles" = '$(builddir)/html/*'; \
+ then echo 1>&2 'Nothing to install' ; \
+ else \
+ if test -n "$(DOC_MODULE_VERSION)"; then \
+ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
+ else \
+ installdir="$(DESTDIR)$(TARGET_DIR)"; \
+ fi; \
+ $(MKDIR_P) $${installdir} ; \
+ for i in $$installfiles; do \
+ echo ' $(INSTALL_DATA) '$$i ; \
+ $(INSTALL_DATA) $$i $${installdir}; \
+ done; \
+ if test -n "$(DOC_MODULE_VERSION)"; then \
+ mv -f $${installdir}/$(DOC_MODULE).devhelp2 \
+ $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \
+ fi; \
+ $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \
+ fi
+
+uninstall-local:
+ @if test -n "$(DOC_MODULE_VERSION)"; then \
+ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
+ else \
+ installdir="$(DESTDIR)$(TARGET_DIR)"; \
+ fi; \
+ rm -rf $${installdir}
+
+dist-check-gtkdoc: docs
+
+dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local
+ @$(MKDIR_P) $(distdir)/html
+ @cp ./html/* $(distdir)/html
+ @-cp ./$(DOC_MODULE).pdf $(distdir)/
+ @-cp ./$(DOC_MODULE).types $(distdir)/
+ @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/
+ @cd $(distdir) && rm -f $(DISTCLEANFILES)
+ @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html
+
+.PHONY : dist-hook-local docs
+
+meson.stamp: docs
+ @touch meson.stamp
diff --git a/doc/reference/gtk3/meson.build b/doc/reference/gtk3/meson.build
new file mode 100644
index 00000000..f076098f
--- /dev/null
+++ b/doc/reference/gtk3/meson.build
@@ -0,0 +1,55 @@
+# Copyright © 2021 Christian Persch
+#
+# This library is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library. If not, see <https://www.gnu.org/licenses/>.
+
+make_args_gtk3 = [
+ '-f', meson.current_source_dir() / '..' / 'Makefile.docs',
+ '--directory', meson.current_build_dir(),
+ 'srcdir=' + meson.current_source_dir(),
+ 'builddir=' + meson.current_build_dir(),
+ 'abs_top_srcdir=' + meson.source_root(),
+ 'abs_top_builddir=' + meson.build_root(),
+ 'datadir=' + vte_prefix / vte_datadir,
+ 'CAIRO_PREFIX=' + cairo_dep.get_pkgconfig_variable('prefix'),
+ 'GLIB_PREFIX=' + glib_dep.get_pkgconfig_variable('prefix'),
+ 'GTK_PREFIX=' + gtk3_dep.get_pkgconfig_variable('prefix'),
+ 'PANGO_PREFIX=' + pango_dep.get_pkgconfig_variable('prefix'),
+ 'CC=' + ' '.join(cc.cmd_array()),
+ 'VERSION=' + meson.project_version(),
+ 'VTE_API_VERSION=' + vte_api_version,
+ 'VTE_GTK=3',
+ 'VTE_LIB=' + libvte_gtk3.full_path(),
+]
+
+stamp = custom_target(
+ 'meson.stamp',
+ build_by_default: true,
+ capture: false,
+ command: [make] + make_args_gtk3 + [
+ 'meson.stamp',
+ ],
+ depends: [
+ libvte_gtk3,
+ ],
+ install: false,
+ output: 'meson.stamp',
+)
+
+meson.add_install_script(
+ make,
+ make_args_gtk3,
+ 'install-data-local',
+)
+
+# Unfortunately, there's no way to hook up the 'clean-local' target
diff --git a/doc/reference/gtk4/meson.build b/doc/reference/gtk4/meson.build
new file mode 100644
index 00000000..34b8bb2b
--- /dev/null
+++ b/doc/reference/gtk4/meson.build
@@ -0,0 +1,55 @@
+# Copyright © 2021 Christian Persch
+#
+# This library is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this library. If not, see <https://www.gnu.org/licenses/>.
+
+make_args_gtk4 = [
+ '-f', meson.current_source_dir() / '..' / 'Makefile.docs',
+ '--directory', meson.current_build_dir(),
+ 'srcdir=' + meson.current_source_dir(),
+ 'builddir=' + meson.current_build_dir(),
+ 'abs_top_srcdir=' + meson.source_root(),
+ 'abs_top_builddir=' + meson.build_root(),
+ 'datadir=' + vte_prefix / vte_datadir,
+ 'CAIRO_PREFIX=' + cairo_dep.get_pkgconfig_variable('prefix'),
+ 'GLIB_PREFIX=' + glib_dep.get_pkgconfig_variable('prefix'),
+ 'GTK_PREFIX=' + gtk4_dep.get_pkgconfig_variable('prefix'),
+ 'PANGO_PREFIX=' + pango_dep.get_pkgconfig_variable('prefix'),
+ 'CC=' + ' '.join(cc.cmd_array()),
+ 'VERSION=' + meson.project_version(),
+ 'VTE_API_VERSION=' + vte_api_version,
+ 'VTE_GTK=4',
+ 'VTE_LIB=' + libvte_gtk4.full_path(),
+]
+
+stamp = custom_target(
+ 'meson.stamp',
+ build_by_default: true,
+ capture: false,
+ command: [make] + make_args_gtk4 + [
+ 'meson.stamp',
+ ],
+ depends: [
+ libvte_gtk4,
+ ],
+ install: false,
+ output: 'meson.stamp',
+)
+
+meson.add_install_script(
+ make,
+ make_args_gtk4,
+ 'install-data-local',
+)
+
+# Unfortunately, there's no way to hook up the 'clean-local' target
diff --git a/doc/reference/meson.build b/doc/reference/meson.build
index b47bc7ed..b3fc3370 100644
--- a/doc/reference/meson.build
+++ b/doc/reference/meson.build
@@ -1,4 +1,5 @@
# Copyright © 2018, 2019 Iñigo Martínez
+# Copyright © 2021 Christian Persch
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
@@ -13,96 +14,18 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see <https://www.gnu.org/licenses/>.
-# Meson insufficiency! Would be so much easier to just make this
-# (vte_gtk3_sources - vte_gtk3_public_headers).filter('.h'), but
-# but there is no array subtraction or filtering. Or just allow listing the
-# headers that we DO want to get scanned.
-# So instead just list all the headers here again... :-(
+# It turned out to be impossible to build gtk3 and gtk4 versions of the
+# docs from the same source using meson's gnome.gtkdoc(). Instead, build
+# using make with a gtk-doc.make-derived Makefile.
-private_headers = [
- 'buffer.h',
- 'caps.hh',
- 'cell.hh',
- 'config.h',
- 'debug.h',
- 'keymap.h',
- 'marshal.h',
- 'modes.hh',
- 'modes-ecma.hh',
- 'modes-private.hh',
- 'parser.hh',
- 'parser-arg.hh',
- 'parser-c01.hh',
- 'parser-charset.hh',
- 'parser-charset-tables.hh',
- 'parser-cmd.hh',
- 'parser-csi.hh',
- 'parser-dcs.hh',
- 'parser-esc.hh',
- 'parser-glue.hh',
- 'parser-osc.hh',
- 'parser-reply.hh',
- 'parser-string.hh',
- 'ring.hh',
- 'tabstops.hh',
- 'vteconv.h',
- 'vtedraw.h',
- 'vteinternal.hh',
- 'vterowdata.hh',
- 'vtestream-base.h',
- 'vtestream-file.h',
- 'vtestream.h',
- 'vtetypebuiltins.h',
- 'vteunistr.h',
-]
+make = find_program('gmake', 'make')
-scan_args = [
- '--deprecated-guards="VTE_DISABLE_DEPRECATED"',
- '--ignore-decorators=_VTE_GNUC_NONNULL\s*\([^)]*\)|_VTE_CXX_NOEXCEPT',
-]
-
-glib_prefix = glib_dep.get_pkgconfig_variable('prefix')
-
-version_conf = configuration_data()
-version_conf.set('VERSION', vte_version)
-
-content_files = configure_file(
- input: 'version.xml.in',
- output: '@BASENAME@',
- configuration: version_conf
-)
+cairo_dep = dependency('cairo')
if get_option('gtk3')
- gtk3_prefix = gtk3_dep.get_pkgconfig_variable('prefix')
-
- fixxref_args = [
- '--html-dir=' + (vte_prefix / gnome.gtkdoc_html_dir(vte_gtk3_api_name)),
- '--extra-dir=' + (glib_prefix / gnome.gtkdoc_html_dir('glib')),
- '--extra-dir=' + (glib_prefix / gnome.gtkdoc_html_dir('gio')),
- '--extra-dir=' + (gtk3_prefix / gnome.gtkdoc_html_dir('gdk')),
- '--extra-dir=' + (gtk3_prefix / gnome.gtkdoc_html_dir('gdk-pixbuf')),
- '--extra-dir=' + (gtk3_prefix / gnome.gtkdoc_html_dir('gtk')),
- ]
-
- gnome.gtkdoc(
- 'vte',
- main_xml: 'vte-docs.xml',
- module_version: vte_api_version,
- src_dir: [src_inc, vte_inc],
- ignore_headers: private_headers,
- include_directories: top_inc,
- dependencies: libvte_gtk3_dep,
- c_args: '-DVTE_COMPILATION',
- namespace: 'vte',
- scan_args: scan_args,
- mkdb_args: '--source-suffixes=h,hh,c,cc',
- fixxref_args: fixxref_args,
- gobject_typesfile: 'vte.types',
- content_files: content_files,
- install: true,
- )
+ subdir('gtk3')
endif
if get_option('gtk4')
- assert(false, 'not yet supported')
+ subdir('gtk4')
endif
diff --git a/doc/reference/version.xml.in b/doc/reference/version.xml.in
deleted file mode 100644
index d78bda93..00000000
--- a/doc/reference/version.xml.in
+++ /dev/null
@@ -1 +0,0 @@
-@VERSION@
diff --git a/doc/reference/vte-docs.xml b/doc/reference/vte-docs.xml
index e3cd5180..76296673 100644
--- a/doc/reference/vte-docs.xml
+++ b/doc/reference/vte-docs.xml
@@ -1,7 +1,9 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-<!ENTITY version SYSTEM "version.xml">
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"
+[
+ <!ENTITY % gtkdocentities SYSTEM "xml/gtkdocentities.ent">
+ %gtkdocentities;
]>
<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
<!--
@@ -24,7 +26,7 @@
<bookinfo>
<title>VTE Reference Manual</title>
<releaseinfo>
- Documentation for VTE version &version;.
+ Documentation for VTE version &package_version;.
The latest version of this documentation can be found on-line at the
<ulink role="online-location" url="http://library.gnome.org/devel/vte/">GNOME Library</ulink>.
</releaseinfo>
@@ -133,8 +135,12 @@
<title>Index of new symbols in 0.64</title>
<xi:include href="xml/api-index-0.64.xml"><xi:fallback /></xi:include>
</index>
+ <index id="api-index-0-66" role="0.66">
+ <title>Index of new symbols in 0.66</title>
+ <xi:include href="xml/api-index-0.66.xml"><xi:fallback /></xi:include>
+ </index>
- <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
+ <xi:include href="xml/annotation-glossary.xml"></xi:include>
<appendix id="licence">
<title>Licence</title>
diff --git a/doc/reference/vte-overrides.txt b/doc/reference/vte-overrides.txt.in
index e69de29b..e69de29b 100644
--- a/doc/reference/vte-overrides.txt
+++ b/doc/reference/vte-overrides.txt.in
diff --git a/doc/reference/vte-sections.txt b/doc/reference/vte-sections.txt.in
index c69181da..84afe8c3 100644
--- a/doc/reference/vte-sections.txt
+++ b/doc/reference/vte-sections.txt.in
@@ -71,12 +71,16 @@ vte_terminal_reset
vte_terminal_get_text
vte_terminal_get_text_range
vte_terminal_get_cursor_position
+#if VTE_GTK == 3
vte_terminal_hyperlink_check_event
+#endif
vte_terminal_match_add_regex
vte_terminal_match_remove
vte_terminal_match_remove_all
vte_terminal_match_check
+#if VTE_GTK == 3
vte_terminal_match_check_event
+#endif
vte_terminal_match_set_cursor_name
vte_terminal_set_cjk_ambiguous_width
vte_terminal_get_cjk_ambiguous_width
@@ -93,8 +97,10 @@ vte_terminal_search_get_regex
vte_terminal_search_get_wrap_around
vte_terminal_search_set_regex
vte_terminal_search_set_wrap_around
+#if VTE_GTK == 3
vte_terminal_event_check_regex_array
vte_terminal_event_check_regex_simple
+#endif /* VTE_GTK */
<SUBSECTION>
VteFeatureFlags
@@ -113,9 +119,11 @@ vte_terminal_set_pty
vte_terminal_pty_new_sync
vte_terminal_watch_child
+#if VTE_GTK == 3
<SUBSECTION>
vte_terminal_set_clear_background
vte_terminal_get_color_background_for_draw
+#endif /* VTE_GTK == 3 */
<SUBSECTION Standard>
VTE_TYPE_CURSOR_BLINK_MODE
@@ -150,14 +158,18 @@ vte_terminal_get_current_file_uri
<SUBSECTION Deprecated>
vte_terminal_copy_clipboard
vte_terminal_match_set_cursor
+#if VTE_GTK == 3
vte_terminal_match_set_cursor_type
vte_terminal_match_add_gregex
vte_terminal_search_get_gregex
vte_terminal_search_set_gregex
vte_terminal_event_check_gregex_simple
+#endif /* VTE_GTK == 3 */
vte_terminal_spawn_sync
+#if VTE_GTK == 3
vte_terminal_get_geometry_hints
vte_terminal_set_geometry_hints_for_window
+#endif /* VTE_GTK == 3 */
vte_terminal_get_icon_title
vte_terminal_set_encoding
vte_terminal_get_encoding
diff --git a/doc/reference/vte.types b/doc/reference/vte.types.in
index d7db2a09..d7db2a09 100644
--- a/doc/reference/vte.types
+++ b/doc/reference/vte.types.in
diff --git a/meson.build b/meson.build
index 5245090a..070d43a4 100644
--- a/meson.build
+++ b/meson.build
@@ -34,7 +34,10 @@ project(
gtk3_req_version = '3.20.0'
gtk3_min_req_version = '3.18'
gtk3_max_allowed_version = '3.20'
-gtk4_req_version = '4.0.0'
+
+gtk4_req_version = '4.0.1'
+gtk4_min_req_version = '4.0'
+gtk4_max_allowed_version = '4.0'
fribidi_req_version = '1.0.0'
gio_req_version = '2.52.0'
@@ -54,11 +57,8 @@ vte_api_minor_version = 91
vte_api_version = '@0@.@1@'.format(vte_api_major_version, vte_api_minor_version)
vte_api_name = 'vte-@0@.@1@'.format(vte_api_major_version, vte_api_minor_version)
-vte_gtk3_api_version = '@0@.@1@'.format(vte_api_major_version, vte_api_minor_version)
-vte_gtk4_api_version = '@0@.@1@'.format(vte_api_major_version + 1, vte_api_minor_version)
-
-vte_gtk3_api_name = 'vte-' + vte_gtk3_api_version
-vte_gtk4_api_name = 'vte-' + vte_gtk4_api_version
+vte_gtk3_api_name = 'vte-' + vte_api_version
+vte_gtk4_api_name = 'vte-' + vte_api_version + '-gtk4'
vte_gtk3_api_path = vte_gtk3_api_name / 'vte'
vte_gtk4_api_path = vte_gtk4_api_name / 'vte'
@@ -141,6 +141,17 @@ if get_option('gtk3')
gtk3_version_cppflags += '-DGDK_VERSION_MAX_ALLOWED=(G_ENCODE_VERSION(' + ver[0] + ',' + ver[1] + '))'
endif
+if get_option('gtk4')
+ gtk4_version_cppflags = []
+
+ ver = gtk4_min_req_version.split('.')
+ gtk4_version_cppflags += '-DGDK_VERSION_MIN_REQUIRED=(G_ENCODE_VERSION(' + ver[0] + ',' + ver[1] + '))'
+
+ ver = gtk4_max_allowed_version.split('.')
+ gtk4_version_cppflags += '-DGDK_VERSION_MAX_ALLOWED=(G_ENCODE_VERSION(' + ver[0] + ',' + ver[1] + '))'
+endif
+
+
# FIXME AC_USE_SYSTEM_EXTENSIONS also supported non-gnu systems
config_h.set10('_GNU_SOURCE', true)
@@ -427,7 +438,7 @@ else
endif
if get_option('gtk4')
- gtk4_dep = dependency('gtk+-4.0', version: '>=' + gtk4_req_version)
+ gtk4_dep = dependency('gtk4', version: '>=' + gtk4_req_version)
else
gtk4_dep = dependency('', required: false)
endif
@@ -462,6 +473,10 @@ subdir('bindings')
subdir('po')
if get_option('docs')
+ assert(meson.version().version_compare('>= 0.55.0'),
+ 'meson >= 0.55 is required to build docs'
+ )
+
subdir('doc/reference')
endif
@@ -470,8 +485,7 @@ endif
makefile_conf = configuration_data()
makefile_conf.set('srcdir', meson.current_source_dir())
makefile_conf.set('builddir', meson.current_build_dir())
-makefile_conf.set('vte_gtk3_api_version', vte_gtk3_api_version)
-makefile_conf.set('vte_gtk4_api_version', vte_gtk4_api_version)
+makefile_conf.set('vte_api_version', vte_api_version)
configure_file(
input: 'Makefile.meson',
@@ -516,4 +530,8 @@ output += '\n'
output += ' Prefix: ' + get_option('prefix') + '\n'
message(output)
+if get_option('gtk4')
+ warning('GTK+ 4.0 support is experimental; API and ABI are subject to change without notice\n')
+endif
+
# Done
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index fffa7710..13d510de 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -3,8 +3,8 @@ bindings/vala/search-popover.ui
src/vtespawn.cc
src/app/app.cc
src/app/appmenu-gtk3.ui
-src/app/appmenu.ui
+src/app/appmenu-gtk4.ui
src/app/search-popover-gtk3.ui
-src/app/search-popover.ui
+src/app/search-popover-gtk4.ui
src/app/window-gtk3.ui
-src/app/window.ui
+src/app/window-gtk4.ui
diff --git a/src/app/app-gtk4.gresource.xml b/src/app/app-gtk4.gresource.xml
new file mode 100644
index 00000000..6c76b21f
--- /dev/null
+++ b/src/app/app-gtk4.gresource.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2014, 2020 Christian Persch
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+-->
+<gresources>
+ <gresource prefix="/org/gnome/vte/app">
+ <file alias="ui/search-popover.ui" compressed="true" preprocess="xml-stripblanks">search-popover-gtk4.ui</file>
+ <file alias="ui/window.ui" compressed="true" preprocess="xml-stripblanks">window-gtk4.ui</file>
+ <file alias="gtk/menus.ui" compressed="true" preprocess="xml-stripblanks">appmenu-gtk4.ui</file>
+ </gresource>
+</gresources>
diff --git a/src/app/app.cc b/src/app/app.cc
index 01975287..4c83c207 100644
--- a/src/app/app.cc
+++ b/src/app/app.cc
@@ -38,6 +38,7 @@
#include <vector>
#include "std-glue.hh"
+#include "cairo-glue.hh"
#include "glib-glue.hh"
#include "libc-glue.hh"
#include "pango-glue.hh"
@@ -61,13 +62,11 @@ public:
gboolean feed_stdin{false};
gboolean icon_title{false};
gboolean keep{false};
- gboolean no_argb_visual{false};
gboolean no_bidi{false};
gboolean no_bold{false};
gboolean no_builtin_dingus{false};
gboolean no_context_menu{false};
gboolean no_decorations{false};
- gboolean no_double_buffer{false};
gboolean no_fallback_scrolling{false};
gboolean no_geometry_hints{false};
gboolean no_hyperlink{false};
@@ -121,6 +120,11 @@ public:
VteTextBlinkMode text_blink_mode{VTE_TEXT_BLINK_ALWAYS};
vte::glib::RefPtr<GtkCssProvider> css{};
+#if VTE_GTK == 3
+ gboolean no_argb_visual{false};
+ gboolean no_double_buffer{false};
+#endif /* VTE_GTK == 3 */
+
~Options() {
g_clear_object(&background_pixbuf);
g_free(command);
@@ -371,8 +375,12 @@ private:
Options* that = static_cast<Options*>(data);
auto css = vte::glib::take_ref(gtk_css_provider_new());
+#if VTE_GTK == 3
if (!gtk_css_provider_load_from_path(css.get(), value, error))
return false;
+#elif VTE_GTK == 4
+ gtk_css_provider_load_from_path(css.get(), value);
+#endif /* VTE_GKT */
that->css = std::move(css);
return true;
@@ -550,8 +558,6 @@ public:
"Enable the setting of the icon title", nullptr },
{ "keep", 'k', 0, G_OPTION_ARG_NONE, &keep,
"Live on after the command exits", nullptr },
- { "no-argb-visual", 0, 0, G_OPTION_ARG_NONE, &no_argb_visual,
- "Don't use an ARGB visual", nullptr },
{ "no-bidi", 0, 0, G_OPTION_ARG_NONE, &no_bidi,
"Disable BiDi", nullptr },
{ "no-bold", 0, 0, G_OPTION_ARG_NONE, &no_bold,
@@ -562,8 +568,6 @@ public:
"Disable context menu", nullptr },
{ "no-decorations", 0, 0, G_OPTION_ARG_NONE, &no_decorations,
"Disable window decorations", nullptr },
- { "no-double-buffer", '2', 0, G_OPTION_ARG_NONE, &no_double_buffer,
- "Disable double-buffering", nullptr },
{ "no-fallback-scrolling", 0, 0, G_OPTION_ARG_NONE, &no_fallback_scrolling,
"Disable fallback scrolling", nullptr },
{ "no-geometry-hints", 'G', 0, G_OPTION_ARG_NONE, &no_geometry_hints,
@@ -617,8 +621,6 @@ public:
nullptr, nullptr },
{ "console", 'C', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &console,
nullptr, nullptr },
- { "double-buffer", '2', G_OPTION_FLAG_REVERSE | G_OPTION_FLAG_HIDDEN,
- G_OPTION_ARG_NONE, &no_double_buffer, nullptr, nullptr },
{ "pty-flags", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &dummy_string,
nullptr, nullptr },
{ "scrollbar-policy", 'P', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING,
@@ -633,6 +635,15 @@ public:
#endif
{ "use-theme-colors", 0, 0, G_OPTION_ARG_NONE, &use_theme_colors,
"Use foreground and background colors from the gtk+ theme", nullptr },
+
+#if VTE_GTK == 3
+ { "no-argb-visual", 0, 0, G_OPTION_ARG_NONE, &no_argb_visual,
+ "Don't use an ARGB visual", nullptr },
+ { "double-buffer", '2', G_OPTION_FLAG_REVERSE | G_OPTION_FLAG_HIDDEN,
+ G_OPTION_ARG_NONE, &no_double_buffer, nullptr, nullptr },
+ { "no-double-buffer", '2', 0, G_OPTION_ARG_NONE, &no_double_buffer,
+ "Disable double-buffering", nullptr },
+#endif /* VTE_GTK == 3 */
{ nullptr }
};
@@ -666,7 +677,9 @@ public:
g_option_group_add_entries(group, entries);
g_option_context_set_main_group(context.get(), group);
+#if VTE_GTK == 3
g_option_context_add_group(context.get(), gtk_get_option_group(true));
+#endif
bool rv = g_option_context_parse(context.get(), &argc, &argv, error);
@@ -677,6 +690,14 @@ public:
swap(fg_color, bg_color);
}
+#if VTE_GTK == 4
+ if (rv && !gtk_init_check()) {
+ g_set_error_literal(error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
+ "Failed to initialise gtk+");
+ rv = false;
+ }
+#endif /* VTE_GTK == 4 */
+
return rv;
}
};
@@ -808,7 +829,11 @@ vteapp_search_popover_update_sensitivity(VteappSearchPopover* popover)
static void
vteapp_search_popover_update_regex(VteappSearchPopover* popover)
{
- char const* search_text = gtk_entry_get_text(GTK_ENTRY(popover->search_entry));
+#if VTE_GTK == 3
+ auto search_text = gtk_entry_get_text(GTK_ENTRY(popover->search_entry));
+#elif VTE_GTK == 4
+ auto search_text = gtk_editable_get_text(GTK_EDITABLE(popover->search_entry));
+#endif /* VTE_GTK */
bool caseless = gtk_toggle_button_get_active(popover->match_case_checkbutton) == FALSE;
char* pattern;
@@ -971,10 +996,18 @@ static GtkWidget*
vteapp_search_popover_new(VteTerminal* terminal,
GtkWidget* relative_to)
{
- return reinterpret_cast<GtkWidget*>(g_object_new(VTEAPP_TYPE_SEARCH_POPOVER,
- "terminal", terminal,
- "relative-to", relative_to,
- nullptr));
+ auto popover = reinterpret_cast<GtkWidget*>(g_object_new(VTEAPP_TYPE_SEARCH_POPOVER,
+ "terminal", terminal,
+#if VTE_GTK == 3
+ "relative-to", relative_to,
+#endif
+ nullptr));
+
+#if VTE_GTK == 4
+ gtk_widget_set_parent(popover, relative_to);
+#endif
+
+ return popover;
}
/* terminal */
@@ -992,7 +1025,11 @@ typedef struct _VteappTerminalClass VteappTerminalClass;
struct _VteappTerminal {
VteTerminal parent;
+ //#if VTE_GTK == 3
cairo_pattern_t* background_pattern;
+ //#elif VTE_GTK == 4
+ // GdkTexture* background_texture;
+ //#endif
bool has_backdrop;
bool use_backdrop;
};
@@ -1012,35 +1049,58 @@ vteapp_terminal_realize(GtkWidget* widget)
{
GTK_WIDGET_CLASS(vteapp_terminal_parent_class)->realize(widget);
- VteappTerminal* terminal = VTEAPP_TERMINAL(widget);
- if (options.background_pixbuf != nullptr) {
- auto surface = gdk_cairo_surface_create_from_pixbuf(options.background_pixbuf,
- 0 /* take scale from window */,
- gtk_widget_get_window(widget));
- terminal->background_pattern = cairo_pattern_create_for_surface(surface);
- cairo_surface_destroy(surface);
+ if (!options.background_pixbuf)
+ return;
- cairo_pattern_set_extend(terminal->background_pattern, options.background_extend);
- }
+ auto terminal = VTEAPP_TERMINAL(widget);
+
+#if VTE_GTK == 3
+ auto surface = vte::take_freeable
+ (gdk_cairo_surface_create_from_pixbuf(options.background_pixbuf,
+ 0 /* take scale from window */,
+ gtk_widget_get_window(widget)));
+#elif VTE_GTK == 4
+ auto const width = gdk_pixbuf_get_width(options.background_pixbuf);
+ auto const height = gdk_pixbuf_get_height(options.background_pixbuf);
+ auto surface = vte::take_freeable(cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ width, height));
+ auto cr = vte::take_freeable(cairo_create(surface.get()));
+ gdk_cairo_set_source_pixbuf(cr.get(), options.background_pixbuf, 0, 0);
+ cairo_paint(cr.get());
+ cairo_surface_flush(surface.get()); // FIXME necessary?
+#endif
+ terminal->background_pattern = cairo_pattern_create_for_surface(surface.get());
+
+ cairo_pattern_set_extend(terminal->background_pattern, options.background_extend);
+
+
+ //#elif VTE_GTK == 4
+ // terminal->background_texture = gdk_texture_new_for_pixbuf(options.background_pixbuf);
+ //#endif /* VTE_GTK */
}
static void
vteapp_terminal_unrealize(GtkWidget* widget)
{
- VteappTerminal* terminal = VTEAPP_TERMINAL(widget);
+#if VTE_GTK == 3
+ auto terminal = VTEAPP_TERMINAL(widget);
+
if (terminal->background_pattern != nullptr) {
cairo_pattern_destroy(terminal->background_pattern);
terminal->background_pattern = nullptr;
}
+#endif /* VTE_GTK */
GTK_WIDGET_CLASS(vteapp_terminal_parent_class)->unrealize(widget);
}
-static gboolean
-vteapp_terminal_draw(GtkWidget* widget,
- cairo_t* cr)
+static void
+vteapp_terminal_draw_background(GtkWidget* widget,
+ cairo_t* cr)
{
- VteappTerminal* terminal = VTEAPP_TERMINAL(widget);
+#if VTE_GTK == 3
+ auto terminal = VTEAPP_TERMINAL(widget);
+
if (terminal->background_pattern != nullptr) {
cairo_push_group(cr);
@@ -1063,8 +1123,29 @@ vteapp_terminal_draw(GtkWidget* widget,
cairo_paint_with_alpha(cr, options.get_alpha_bg_for_draw());
}
+#endif /* VTE_GTK == 3 */
+}
+
+#if VTE_GTK == 4
- auto rv = GTK_WIDGET_CLASS(vteapp_terminal_parent_class)->draw(widget, cr);
+static void
+vteapp_terminal_draw_background(GtkWidget* widget,
+ GtkSnapshot* snapshot)
+{
+ auto grect = GRAPHENE_RECT_INIT(float(0), float(0),
+ float(gtk_widget_get_allocated_width(widget)),
+ float(gtk_widget_get_allocated_height(widget)));
+ auto cr = vte::take_freeable(gtk_snapshot_append_cairo(snapshot, &grect));
+ vteapp_terminal_draw_background(widget, cr.get());
+}
+
+#endif /* VTE_GTK == 4 */
+
+static void
+vteapp_terminal_draw_backdrop(GtkWidget* widget,
+ cairo_t* cr)
+{
+ auto terminal = VTEAPP_TERMINAL(widget);
if (terminal->use_backdrop && terminal->has_backdrop) {
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
@@ -1074,49 +1155,162 @@ vteapp_terminal_draw(GtkWidget* widget,
gtk_widget_get_allocated_height(widget));
cairo_paint(cr);
}
+}
+
+#if VTE_GTK == 4
+
+static void
+vteapp_terminal_draw_backdrop(GtkWidget* widget,
+ GtkSnapshot* snapshot)
+{
+ auto grect = GRAPHENE_RECT_INIT(float(0), float(0),
+ float(gtk_widget_get_allocated_width(widget)),
+ float(gtk_widget_get_allocated_height(widget)));
+ auto cr = vte::take_freeable(gtk_snapshot_append_cairo(snapshot, &grect));
+ vteapp_terminal_draw_backdrop(widget, cr.get());
+}
+
+#endif /* VTE_GTK == 4 */
+
+#if VTE_GTK == 3
+
+static gboolean
+vteapp_terminal_draw(GtkWidget* widget,
+ cairo_t* cr)
+{
+ vteapp_terminal_draw_background(widget, cr);
+
+ auto const rv = GTK_WIDGET_CLASS(vteapp_terminal_parent_class)->draw(widget, cr);
+
+ vteapp_terminal_draw_backdrop(widget, cr);
return rv;
}
-static auto dti(double d) -> unsigned { return CLAMP((d*255), 0, 255); }
+#endif /* VTE_GTK == 3 */
+
+static void
+vteapp_terminal_update_theme_colors(GtkWidget* widget)
+{
+ if (!options.use_theme_colors)
+ return;
+
+ auto terminal = VTEAPP_TERMINAL(widget);
+ auto context = gtk_widget_get_style_context(widget);
+
+#if VTE_GTK == 3
+ auto const flags = gtk_style_context_get_state(context);
+#endif
+
+ auto theme_fg = GdkRGBA{};
+ gtk_style_context_get_color(context,
+#if VTE_GTK == 3
+ flags,
+#endif
+ &theme_fg);
+
+ auto theme_bg = GdkRGBA{};
+#if VTE_GTK == 3
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+ gtk_style_context_get_background_color(context, flags, &theme_bg);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
+#elif VTE_GTK == 4
+ // FIXMEgtk4 "background-color" lookup always fails
+ if (!gtk_style_context_lookup_color(context, "text_view_bg", &theme_bg)) {
+ verbose_print("Failed to get theme background color\n");
+ return;
+ }
+#endif
+
+ auto dti = [](double d) -> unsigned { return std::clamp(unsigned(d*255), 0u, 255u); };
+
+ verbose_print("Theme colors: foreground is #%02X%02X%02X, background is #%02X%02X%02X\n",
+ dti(theme_fg.red), dti(theme_fg.green), dti(theme_fg.blue),
+ dti(theme_bg.red), dti(theme_bg.green), dti(theme_bg.blue));
+
+ theme_fg.alpha = 1.;
+ theme_bg.alpha = options.get_alpha_bg();
+ vte_terminal_set_colors(VTE_TERMINAL(terminal), &theme_fg, &theme_bg, nullptr, 0);
+}
+
+#if VTE_GTK == 3
static void
vteapp_terminal_style_updated(GtkWidget* widget)
{
GTK_WIDGET_CLASS(vteapp_terminal_parent_class)->style_updated(widget);
- auto context = gtk_widget_get_style_context(widget);
- auto flags = gtk_style_context_get_state(context);
+ auto terminal = VTEAPP_TERMINAL(widget);
- VteappTerminal* terminal = VTEAPP_TERMINAL(widget);
+ auto context = gtk_widget_get_style_context(widget);
+ auto const flags = gtk_style_context_get_state(context);
terminal->has_backdrop = (flags & GTK_STATE_FLAG_BACKDROP) != 0;
- if (options.use_theme_colors) {
- auto theme_fg = GdkRGBA{};
- gtk_style_context_get_color(context, flags, &theme_fg);
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
- auto theme_bg = GdkRGBA{};
- gtk_style_context_get_background_color(context, flags, &theme_bg);
- G_GNUC_END_IGNORE_DEPRECATIONS;
+ vteapp_terminal_update_theme_colors(widget);
+}
- verbose_print("Theme colors: foreground is #%02X%02X%02X, background is #%02X%02X%02X\n",
- dti(theme_fg.red), dti(theme_fg.green), dti(theme_fg.blue),
- dti(theme_bg.red), dti(theme_bg.green), dti(theme_bg.blue));
+#endif /* VTE_GTK == 3 */
- theme_fg.alpha = 1.;
- theme_bg.alpha = options.get_alpha_bg();
- vte_terminal_set_colors(VTE_TERMINAL(terminal), &theme_fg, &theme_bg, nullptr, 0);
- }
+#if VTE_GTK == 4
+
+static void
+vteapp_terminal_snapshot(GtkWidget* widget,
+ GtkSnapshot* snapshot_object)
+{
+ vteapp_terminal_draw_background(widget, snapshot_object);
+
+ GTK_WIDGET_CLASS(vteapp_terminal_parent_class)->snapshot(widget, snapshot_object);
+
+ vteapp_terminal_draw_backdrop(widget, snapshot_object);
}
static void
+vteapp_terminal_css_changed(GtkWidget* widget,
+ GtkCssStyleChange* change)
+{
+ GTK_WIDGET_CLASS(vteapp_terminal_parent_class)->css_changed(widget, change);
+
+ vteapp_terminal_update_theme_colors(widget);
+}
+
+static void
+vteapp_terminal_state_flags_changed(GtkWidget* widget,
+ GtkStateFlags old_flags)
+{
+ GTK_WIDGET_CLASS(vteapp_terminal_parent_class)->state_flags_changed(widget, old_flags);
+
+ auto terminal = VTEAPP_TERMINAL(widget);
+ auto const flags = gtk_widget_get_state_flags(widget);
+ terminal->has_backdrop = (flags & GTK_STATE_FLAG_BACKDROP) != 0;
+}
+
+static void
+vteapp_terminal_system_setting_changed(GtkWidget* widget,
+ GtkSystemSetting setting)
+{
+ GTK_WIDGET_CLASS(vteapp_terminal_parent_class)->system_setting_changed(widget, setting);
+
+ // FIXMEgtk4 find a way to update colours on theme change like gtk3 above
+}
+
+#endif /* VTE_GTK == 4 */
+
+static void
vteapp_terminal_class_init(VteappTerminalClass *klass)
{
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
+ auto widget_class = GTK_WIDGET_CLASS(klass);
widget_class->realize = vteapp_terminal_realize;
widget_class->unrealize = vteapp_terminal_unrealize;
+
+#if VTE_GTK == 3
widget_class->draw = vteapp_terminal_draw;
widget_class->style_updated = vteapp_terminal_style_updated;
+#elif VTE_GTK == 4
+ widget_class->snapshot = vteapp_terminal_snapshot;
+ widget_class->css_changed = vteapp_terminal_css_changed;
+ widget_class->state_flags_changed = vteapp_terminal_state_flags_changed;
+ widget_class->system_setting_changed = vteapp_terminal_system_setting_changed;
+#endif
gtk_widget_class_set_css_name(widget_class, "vteapp-terminal");
}
@@ -1128,8 +1322,10 @@ vteapp_terminal_init(VteappTerminal *terminal)
terminal->has_backdrop = false;
terminal->use_backdrop = options.backdrop;
+#if VTE_GTK == 3
if (options.background_pixbuf != nullptr)
vte_terminal_set_clear_background(VTE_TERMINAL(terminal), false);
+#endif /* VTE_GTK == 3 */
}
static GtkWidget *
@@ -1165,12 +1361,9 @@ struct _VteappWindow {
/* end */
VteTerminal* terminal;
- GtkClipboard* clipboard;
GPid child_pid;
GtkWidget* search_popover;
- bool fullscreen{false};
-
/* used for updating the geometry hints */
int cached_cell_width{0};
int cached_cell_height{0};
@@ -1178,6 +1371,15 @@ struct _VteappWindow {
int cached_chrome_height{0};
int cached_csd_width{0};
int cached_csd_height{0};
+
+#if VTE_GTK == 3
+ GtkClipboard* clipboard;
+ GdkWindowState window_state{GdkWindowState(0)};
+#endif
+#if VTE_GTK == 4
+ GdkClipboard* clipboard;
+ GdkToplevelState toplevel_state{GdkToplevelState(0)};
+#endif
};
struct _VteappWindowClass {
@@ -1221,6 +1423,7 @@ vteapp_window_add_dingus(VteappWindow* window,
static void
vteapp_window_update_geometry(VteappWindow* window)
{
+#if VTE_GTK == 3
GtkWidget* window_widget = GTK_WIDGET(window);
GtkWidget* terminal_widget = GTK_WIDGET(window->terminal);
@@ -1301,18 +1504,43 @@ vteapp_window_update_geometry(VteappWindow* window)
window->cached_cell_width, window->cached_cell_height,
window->cached_chrome_width, window->cached_chrome_height,
window->cached_csd_width, window->cached_csd_height);
+#elif VTE_GTK == 4
+ // FIXMEgtk4 there appears to be no way to do this with gtk4 ? maybe go to X/wayland
+ // directly to set the geometry hints?
+#endif
}
+#include <gdk/gdk.h>
+
static void
vteapp_window_resize(VteappWindow* window)
{
- /* Don't do this for maximised or tiled windows. */
- auto win = gtk_widget_get_window(GTK_WIDGET(window));
- if (win != nullptr &&
- (gdk_window_get_state(win) & (GDK_WINDOW_STATE_MAXIMIZED |
- GDK_WINDOW_STATE_FULLSCREEN |
- GDK_WINDOW_STATE_TILED)) != 0)
+ /* Don't do this for fullscreened, maximised, or tiled windows. */
+#if VTE_GTK == 3
+ if (window->window_state & (GDK_WINDOW_STATE_MAXIMIZED |
+ GDK_WINDOW_STATE_FULLSCREEN |
+ GDK_WINDOW_STATE_TILED |
+#if GTK_CHECK_VERSION(3,22,23)
+ GDK_WINDOW_STATE_TOP_TILED |
+ GDK_WINDOW_STATE_BOTTOM_TILED |
+ GDK_WINDOW_STATE_LEFT_TILED |
+ GDK_WINDOW_STATE_RIGHT_TILED |
+#endif
+ 0))
+ return;
+#elif VTE_GTK == 4
+ if (window->toplevel_state & (GDK_TOPLEVEL_STATE_MAXIMIZED |
+ GDK_TOPLEVEL_STATE_FULLSCREEN |
+ GDK_TOPLEVEL_STATE_TILED |
+ GDK_TOPLEVEL_STATE_TOP_TILED |
+ GDK_TOPLEVEL_STATE_BOTTOM_TILED |
+ GDK_TOPLEVEL_STATE_LEFT_TILED |
+ GDK_TOPLEVEL_STATE_RIGHT_TILED))
return;
+#endif /* VTE_GTK */
+
+#if VTE_GTK == 3
+ // FIXMEgtk4
/* First, update the geometry hints, so that the cached_* members are up-to-date */
vteapp_window_update_geometry(window);
@@ -1327,11 +1555,13 @@ vteapp_window_resize(VteappWindow* window)
columns, rows, pixel_width, pixel_height);
gtk_window_resize(GTK_WINDOW(window), pixel_width, pixel_height);
+#endif /* VTE_GTK == 3 FIXMEgtk4 */
}
static void
vteapp_window_parse_geometry(VteappWindow* window)
{
+#if VTE_GTK == 3
/* First update the geometry hints, so that gtk_window_parse_geometry()
* knows the char width/height and base size increments.
*/
@@ -1376,6 +1606,9 @@ vteapp_window_parse_geometry(VteappWindow* window)
vteapp_window_resize(window);
}
}
+#elif VTE_GTK == 4
+ // FIXMEgtk4 ????
+#endif /* VTE_GTK */
}
static void
@@ -1409,8 +1642,13 @@ window_spawn_cb(VteTerminal* terminal,
auto msg = vte::glib::take_string(g_strdup_printf("Spawning failed: %s", error->message));
if (options.keep)
vte_terminal_feed(window->terminal, msg.get(), -1);
- else
+ else {
+#if VTE_GTK == 3
gtk_widget_destroy(GTK_WIDGET(window));
+#elif VTE_GTK == 4
+ gtk_window_destroy(GTK_WINDOW(window));
+#endif
+ }
}
}
@@ -1568,16 +1806,34 @@ window_update_copy_sensitivity(VteappWindow* window)
}
static void
+window_update_fullscreen_state(VteappWindow* window)
+{
+#if VTE_GTK == 3
+ auto const fullscreen = (window->window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
+#elif VTE_GTK == 4
+ auto const fullscreen = (window->toplevel_state & GDK_TOPLEVEL_STATE_FULLSCREEN) != 0;
+#endif
+ auto action = g_action_map_lookup_action(G_ACTION_MAP(window), "fullscreen");
+ g_simple_action_set_state(G_SIMPLE_ACTION(action), g_variant_new_boolean (fullscreen));
+}
+
+static void
window_update_paste_sensitivity(VteappWindow* window)
{
+ bool can_paste = false;
+
+#if VTE_GTK == 3
GdkAtom* targets;
int n_targets;
- bool can_paste = false;
if (gtk_clipboard_wait_for_targets(window->clipboard, &targets, &n_targets)) {
can_paste = gtk_targets_include_text(targets, n_targets);
g_free(targets);
}
+#elif VTE_GTK == 4
+ auto formats = gdk_clipboard_get_formats(window->clipboard);
+ can_paste = gdk_content_formats_contain_gtype(formats, G_TYPE_STRING);
+#endif /* VTE_GTK */
auto action = g_action_map_lookup_action(G_ACTION_MAP(window), "paste");
g_simple_action_set_enabled(G_SIMPLE_ACTION(action), can_paste);
@@ -1603,10 +1859,15 @@ window_action_copy_match_cb(GSimpleAction* action,
GVariant* parameter,
void* data)
{
- VteappWindow* window = VTEAPP_WINDOW(data);
- gsize len;
- char const* str = g_variant_get_string(parameter, &len);
+ auto window = VTEAPP_WINDOW(data);
+
+ auto len = size_t{};
+ auto str = g_variant_get_string(parameter, &len);
+#if VTE_GTK == 3
gtk_clipboard_set_text(window->clipboard, str, len);
+#elif VTE_GTK == 4
+ gdk_clipboard_set_text(window->clipboard, str);
+#endif
}
static void
@@ -1623,16 +1884,23 @@ window_action_reset_cb(GSimpleAction* action,
GVariant* parameter,
void* data)
{
- VteappWindow* window = VTEAPP_WINDOW(data);
- bool clear;
- GdkModifierType modifiers;
+ auto window = VTEAPP_WINDOW(data);
+ auto clear = false;
if (parameter != nullptr)
clear = g_variant_get_boolean(parameter);
- else if (gtk_get_current_event_state(&modifiers))
+ else {
+ auto modifiers = GdkModifierType{};
+#if VTE_GTK == 3
+ if (!gtk_get_current_event_state(&modifiers))
+ modifiers = GdkModifierType(0);
+#elif VTE_GTK == 4
+ // FIXMEgtk4!
+ modifiers = GdkModifierType(0);
+#endif
+
clear = (modifiers & GDK_CONTROL_MASK) != 0;
- else
- clear = false;
+ }
vte_terminal_reset(window->terminal, true, clear);
}
@@ -1646,7 +1914,6 @@ window_action_find_cb(GSimpleAction* action,
gtk_toggle_button_set_active(window->find_button, true);
}
-
static void
window_action_fullscreen_state_cb (GSimpleAction *action,
GVariant *state,
@@ -1665,6 +1932,7 @@ window_action_fullscreen_state_cb (GSimpleAction *action,
/* The window-state-changed callback will update the action's actual state */
}
+#if VTE_GTK == 3
static bool
vteapp_window_show_context_menu(VteappWindow* window,
guint button,
@@ -1678,20 +1946,21 @@ vteapp_window_show_context_menu(VteappWindow* window,
g_menu_append(menu, "_Copy", "win.copy::text");
g_menu_append(menu, "Copy As _HTML", "win.copy::html");
- if (event != nullptr) {
- auto hyperlink = vte_terminal_hyperlink_check_event(window->terminal, event);
- if (hyperlink != nullptr) {
- verbose_print("Hyperlink: %s\n", hyperlink);
- auto target = g_variant_new_string(hyperlink); /* floating */
+ if (event != nullptr)
+ {
+ auto hyperlink = vte::glib::take_string(vte_terminal_hyperlink_check_event(window->terminal, event));
+ if (hyperlink) {
+ verbose_print("Hyperlink: %s\n", hyperlink.get());
+ auto target = g_variant_new_string(hyperlink.get()); /* floating */
auto item = vte::glib::take_ref(g_menu_item_new("Copy _Hyperlink", nullptr));
g_menu_item_set_action_and_target_value(item.get(), "win.copy-match", target);
g_menu_append_item(menu, item.get());
}
- auto match = vte_terminal_match_check_event(window->terminal, event, nullptr);
- if (match != nullptr) {
- verbose_print("Match: %s\n", match);
- auto target = g_variant_new_string(match); /* floating */
+ auto match = vte::glib::take_string(vte_terminal_match_check_event(window->terminal, event, nullptr));
+ if (match) {
+ verbose_print("Match: %s\n", match.get());
+ auto target = g_variant_new_string(match.get()); /* floating */
auto item = vte::glib::take_ref(g_menu_item_new("Copy _Match", nullptr));
g_menu_item_set_action_and_target_value(item.get(), "win.copy-match", target);
g_menu_append_item(menu, item.get());
@@ -1725,15 +1994,14 @@ vteapp_window_show_context_menu(VteappWindow* window,
else
verbose_print("%s match: %s\n", extra_pattern, extra_match);
}
- g_free(hyperlink);
- g_free(match);
g_free(extra_match);
g_free(extra_subst);
}
g_menu_append(menu, "_Paste", "win.paste");
- if (window->fullscreen)
+ auto const fullscreen = (window->window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
+ if (fullscreen)
g_menu_append(menu, "_Fullscreen", "win.fullscreen");
auto popup = gtk_menu_new_from_model(G_MENU_MODEL(menu));
@@ -1744,13 +2012,23 @@ vteapp_window_show_context_menu(VteappWindow* window,
return true;
}
+#endif /* VTE_GTK */
+
+#if VTE_GTK == 3
static gboolean
window_popup_menu_cb(GtkWidget* widget,
VteappWindow* window)
{
- return vteapp_window_show_context_menu(window, 0, gtk_get_current_event_time(), nullptr);
+ auto const timestamp = gtk_get_current_event_time();
+
+ return vteapp_window_show_context_menu(window, 0, timestamp , nullptr);
}
+// FIXMEgtk4
+
+#endif /* VTE_GTK == 3 */
+
+#if VTE_GTK == 3
static gboolean
window_button_press_cb(GtkWidget* widget,
@@ -1764,6 +2042,8 @@ window_button_press_cb(GtkWidget* widget,
reinterpret_cast<GdkEvent*>(event));
}
+#endif /* VTE_GTK == 3 */
+
static void
window_cell_size_changed_cb(VteTerminal* term,
guint width,
@@ -1815,9 +2095,15 @@ window_child_exited_cb(VteTerminal* term,
if (options.keep)
return;
+#if VTE_GTK == 3
gtk_widget_destroy(GTK_WIDGET(window));
+#elif VTE_GTK == 4
+ gtk_window_destroy(GTK_WINDOW(window));
+#endif
}
+#if VTE_GTK == 3
+
static void
window_clipboard_owner_change_cb(GtkClipboard* clipboard,
GdkEvent* event,
@@ -1826,6 +2112,18 @@ window_clipboard_owner_change_cb(GtkClipboard* clipboard,
window_update_paste_sensitivity(window);
}
+#elif VTE_GTK == 4
+
+static void
+window_clipboard_formats_notify_cb(GdkClipboard* clipboard,
+ GParamSpec* pspec,
+ VteappWindow* window)
+{
+ window_update_paste_sensitivity(window);
+}
+
+#endif /* VTE_GTK */
+
static void
window_decrease_font_size_cb(VteTerminal* terminal,
VteappWindow* window)
@@ -1847,7 +2145,12 @@ window_deiconify_window_cb(VteTerminal* terminal,
if (!options.allow_window_ops)
return;
+#if VTE_GTK == 3
gtk_window_deiconify(GTK_WINDOW(window));
+#elif VTE_GTK == 4
+ auto toplevel = GDK_TOPLEVEL(gtk_native_get_surface(GTK_NATIVE(window)));
+ gdk_toplevel_present(toplevel, nullptr); // FIXMEgtk4 nullptr not allowed
+#endif
}
static void
@@ -1857,26 +2160,25 @@ window_iconify_window_cb(VteTerminal* terminal,
if (!options.allow_window_ops)
return;
+#if VTE_GTK == 3
gtk_window_iconify(GTK_WINDOW(window));
-}
-
-static void
-window_icon_title_changed_cb(VteTerminal* terminal,
- VteappWindow* window)
-{
- if (!options.icon_title)
- return;
-
- gdk_window_set_icon_name(gtk_widget_get_window(GTK_WIDGET(window)),
- vte_terminal_get_icon_title(window->terminal));
+#elif VTE_GTK == 4
+ auto toplevel = GDK_TOPLEVEL(gtk_native_get_surface(GTK_NATIVE(window)));
+ gdk_toplevel_minimize(toplevel);
+#endif
}
static void
window_window_title_changed_cb(VteTerminal* terminal,
VteappWindow* window)
{
- gtk_window_set_title(GTK_WINDOW(window),
- vte_terminal_get_window_title(window->terminal));
+ auto const title = vte_terminal_get_window_title(window->terminal);
+#if VTE_GTK == 3
+ gtk_window_set_title(GTK_WINDOW(window), title);
+#elif VTE_GTK == 4
+ auto toplevel = GDK_TOPLEVEL(gtk_native_get_surface(GTK_NATIVE(window)));
+ gdk_toplevel_set_title(toplevel, title);
+#endif
}
static void
@@ -1888,7 +2190,12 @@ window_lower_window_cb(VteTerminal* terminal,
if (!gtk_widget_get_realized(GTK_WIDGET(window)))
return;
+#if VTE_GTK == 3
gdk_window_lower(gtk_widget_get_window(GTK_WIDGET(window)));
+#elif VTE_GTK == 4
+ auto toplevel = GDK_TOPLEVEL(gtk_native_get_surface(GTK_NATIVE(window)));
+ gdk_toplevel_lower(toplevel);
+#endif
}
static void
@@ -1900,7 +2207,12 @@ window_raise_window_cb(VteTerminal* terminal,
if (!gtk_widget_get_realized(GTK_WIDGET(window)))
return;
+#if VTE_GTK == 3
gdk_window_raise(gtk_widget_get_window(GTK_WIDGET(window)));
+#elif VTE_GTK == 4
+ auto toplevel = GDK_TOPLEVEL(gtk_native_get_surface(GTK_NATIVE(window)));
+ gdk_toplevel_present(toplevel, nullptr); // FIXMEgtk4 gdk_toplevel_raise() doesn't exist??
+#endif
}
static void
@@ -1932,9 +2244,26 @@ window_move_window_cb(VteTerminal* terminal,
if (!options.allow_window_ops)
return;
+#if VTE_GTK == 3
gtk_window_move(GTK_WINDOW(window), x, y);
+#elif VTE_GTK == 4
+ // FIXMEgtk4
+#endif
}
+#if VTE_GTK == 4
+
+static void
+window_toplevel_notify_state_cb(GdkToplevel* toplevel,
+ GParamSpec* pspec,
+ VteappWindow* window)
+{
+ window->toplevel_state = gdk_toplevel_get_state(toplevel);
+ window_update_fullscreen_state(window);
+}
+
+#endif /* VTE_GTK == 4 */
+
static void
window_notify_cb(GObject* object,
GParamSpec* pspec,
@@ -2044,10 +2373,19 @@ vteapp_window_constructed(GObject *object)
gtk_widget_set_margin_bottom(GTK_WIDGET(window->terminal), margin);
}
- gtk_range_set_adjustment(GTK_RANGE(window->scrollbar),
- gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(window->terminal)));
+ auto vadj = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(window->terminal));
+#if VTE_GTK == 3
+ gtk_range_set_adjustment(GTK_RANGE(window->scrollbar), vadj);
+#elif VTE_GTK == 4
+ gtk_scrollbar_set_adjustment(GTK_SCROLLBAR(window->scrollbar), vadj);
+#endif
+
if (options.no_scrollbar) {
+#if VTE_GTK == 3
gtk_widget_destroy(GTK_WIDGET(window->scrollbar));
+#elif VTE_GTK == 4
+ // FIXMEgtk4
+#endif
window->scrollbar = nullptr;
}
@@ -2070,39 +2408,58 @@ vteapp_window_constructed(GObject *object)
g_action_map_add_action(map, G_ACTION(action.get()));
g_signal_connect(action.get(), "notify::state", G_CALLBACK(window_input_enabled_state_cb), window);
+#if VTE_GTK == 4
+ auto gear_popover = gtk_menu_button_get_popover(GTK_MENU_BUTTON(window->gear_button));
+ gtk_widget_set_halign(GTK_WIDGET(gear_popover), GTK_ALIGN_END);
+#endif
+
/* Find */
window->search_popover = vteapp_search_popover_new(window->terminal,
GTK_WIDGET(window->find_button));
+
g_signal_connect(window->search_popover, "closed",
G_CALLBACK(window_search_popover_closed_cb), window);
g_signal_connect(window->find_button, "toggled",
G_CALLBACK(window_find_button_toggled_cb), window);
/* Clipboard */
+#if VTE_GTK == 3
window->clipboard = gtk_widget_get_clipboard(GTK_WIDGET(window), GDK_SELECTION_CLIPBOARD);
g_signal_connect(window->clipboard, "owner-change", G_CALLBACK(window_clipboard_owner_change_cb), window);
+#elif VTE_GTK == 4
+ window->clipboard = gtk_widget_get_clipboard(GTK_WIDGET(window));
+ g_signal_connect(window->clipboard, "notify::formats", G_CALLBACK(window_clipboard_formats_notify_cb), window);
+#endif /* VTE_GTK */
/* Set ARGB visual */
if (options.transparency_percent >= 0) {
+#if VTE_GTK == 3
if (!options.no_argb_visual) {
auto screen = gtk_widget_get_screen(GTK_WIDGET(window));
auto visual = gdk_screen_get_rgba_visual(screen);
if (visual != nullptr)
gtk_widget_set_visual(GTK_WIDGET(window), visual);
- }
+ }
/* Without this transparency doesn't work; see bug #729884. */
gtk_widget_set_app_paintable(GTK_WIDGET(window), true);
+
+#elif VTE_GTK == 4
+ // FIXMEgtk4
+#endif /* VTE_GTK == 3 */
}
/* Signals */
+#if VTE_GTK == 3
g_signal_connect(window->terminal, "popup-menu", G_CALLBACK(window_popup_menu_cb), window);
g_signal_connect(window->terminal, "button-press-event", G_CALLBACK(window_button_press_cb), window);
+#elif VTE_GTK == 4
+ // FIXMEgtk4
+#endif
g_signal_connect(window->terminal, "char-size-changed", G_CALLBACK(window_cell_size_changed_cb), window);
g_signal_connect(window->terminal, "child-exited", G_CALLBACK(window_child_exited_cb), window);
g_signal_connect(window->terminal, "decrease-font-size", G_CALLBACK(window_decrease_font_size_cb), window);
g_signal_connect(window->terminal, "deiconify-window", G_CALLBACK(window_deiconify_window_cb), window);
- g_signal_connect(window->terminal, "icon-title-changed", G_CALLBACK(window_icon_title_changed_cb), window);
g_signal_connect(window->terminal, "iconify-window", G_CALLBACK(window_iconify_window_cb), window);
g_signal_connect(window->terminal, "increase-font-size", G_CALLBACK(window_increase_font_size_cb), window);
g_signal_connect(window->terminal, "lower-window", G_CALLBACK(window_lower_window_cb), window);
@@ -2118,11 +2475,13 @@ vteapp_window_constructed(GObject *object)
g_signal_connect(window->terminal, "notify", G_CALLBACK(window_notify_cb), window);
/* Settings */
+#if VTE_GTK == 3
if (options.no_double_buffer) {
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
gtk_widget_set_double_buffered(GTK_WIDGET(window->terminal), false);
G_GNUC_END_IGNORE_DEPRECATIONS;
}
+#endif /* VTE_GTK == 3 */
if (options.encoding != nullptr) {
auto error = vte::glib::Error{};
@@ -2183,6 +2542,8 @@ vteapp_window_constructed(GObject *object)
/* Done! */
gtk_grid_attach(GTK_GRID(window->window_grid), GTK_WIDGET(window->terminal),
0, 0, 1, 1);
+ gtk_widget_set_halign(GTK_WIDGET(window->terminal), GTK_ALIGN_FILL);
+ gtk_widget_set_valign(GTK_WIDGET(window->terminal), GTK_ALIGN_FILL);
gtk_widget_show(GTK_WIDGET(window->terminal));
window_update_paste_sensitivity(window);
@@ -2201,13 +2562,21 @@ vteapp_window_dispose(GObject *object)
if (window->clipboard != nullptr) {
g_signal_handlers_disconnect_by_func(window->clipboard,
+#if VTE_GTK == 3
(void*)window_clipboard_owner_change_cb,
+#elif VTE_GTK == 4
+ (void*)window_clipboard_formats_notify_cb,
+#endif
window);
window->clipboard = nullptr;
}
if (window->search_popover != nullptr) {
+#if VTE_GTK == 3
gtk_widget_destroy(window->search_popover);
+#elif VTE_GTK == 4
+ gtk_widget_unparent(window->search_popover); // this destroys the popover
+#endif /* VTE_GTK */
window->search_popover = nullptr;
}
@@ -2222,10 +2591,37 @@ vteapp_window_realize(GtkWidget* widget)
/* Now we can know the CSD size, and thus apply the geometry. */
VteappWindow* window = VTEAPP_WINDOW(widget);
verbose_print("VteappWindow::realize\n");
+
+#if VTE_GTK == 3
+ auto win = gtk_widget_get_window(GTK_WIDGET(window));
+ window->window_state = gdk_window_get_state(win);
+#elif VTE_GTK == 4
+ auto surface = gtk_native_get_surface(GTK_NATIVE(widget));
+ window->toplevel_state = gdk_toplevel_get_state(GDK_TOPLEVEL(surface));
+ g_signal_connect(surface, "notify::state",
+ G_CALLBACK(window_toplevel_notify_state_cb), window);
+#endif
+
+ window_update_fullscreen_state(window);
+
vteapp_window_resize(window);
}
static void
+vteapp_window_unrealize(GtkWidget* widget)
+{
+#if VTE_GTK == 4
+ auto window = VTEAPP_WINDOW(widget);
+ auto toplevel = gtk_native_get_surface(GTK_NATIVE(widget));
+ g_signal_handlers_disconnect_by_func(toplevel,
+ (void*)window_toplevel_notify_state_cb,
+ window);
+#endif
+
+ GTK_WIDGET_CLASS(vteapp_window_parent_class)->unrealize(widget);
+}
+
+static void
vteapp_window_show(GtkWidget* widget)
{
GTK_WIDGET_CLASS(vteapp_window_parent_class)->show(widget);
@@ -2236,6 +2632,8 @@ vteapp_window_show(GtkWidget* widget)
vteapp_window_resize(window);
}
+#if VTE_GTK == 3
+
static void
vteapp_window_style_updated(GtkWidget* widget)
{
@@ -2251,18 +2649,17 @@ static gboolean
vteapp_window_state_event (GtkWidget* widget,
GdkEventWindowState* event)
{
- VteappWindow* window = VTEAPP_WINDOW(widget);
+ auto window = VTEAPP_WINDOW(widget);
+ window->window_state = event->new_window_state;
- if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
- window->fullscreen = (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
-
- auto action = reinterpret_cast<GSimpleAction*>(g_action_map_lookup_action(G_ACTION_MAP(window), "fullscreen"));
- g_simple_action_set_state(action, g_variant_new_boolean (window->fullscreen));
- }
+ if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
+ window_update_fullscreen_state(window);
return GTK_WIDGET_CLASS(vteapp_window_parent_class)->window_state_event(widget, event);
}
+#endif /* VTE_GTK == 3 */
+
static void
vteapp_window_class_init(VteappWindowClass* klass)
{
@@ -2272,9 +2669,15 @@ vteapp_window_class_init(VteappWindowClass* klass)
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
widget_class->realize = vteapp_window_realize;
+ widget_class->unrealize = vteapp_window_unrealize;
widget_class->show = vteapp_window_show;
+
+#if VTE_GTK == 3
widget_class->style_updated = vteapp_window_style_updated;
widget_class->window_state_event = vteapp_window_state_event;
+#elif VTE_GTK == 4
+ // FIXMEgtk4 window state event
+#endif
gtk_widget_class_set_template_from_resource(widget_class, "/org/gnome/vte/app/ui/window.ui");
gtk_widget_class_set_css_name(widget_class, "vteapp-window");
@@ -2340,8 +2743,14 @@ app_action_close_cb(GSimpleAction* action,
{
GtkApplication* application = GTK_APPLICATION(data);
auto window = gtk_application_get_active_window(application);
- if (window != nullptr)
- gtk_widget_destroy(GTK_WIDGET(window));
+ if (window == nullptr)
+ return;
+
+#if VTE_GTK == 3
+ gtk_widget_destroy(GTK_WIDGET(window));
+#elif VTE_GTK == 4
+ gtk_window_destroy(GTK_WINDOW(window));
+#endif
}
static gboolean
@@ -2381,16 +2790,24 @@ static void
vteapp_application_init(VteappApplication* application)
{
g_object_set(gtk_settings_get_default(),
- "gtk-enable-mnemonics", FALSE,
"gtk-enable-accels", FALSE,
+#if VTE_GTK == 3
+ "gtk-enable-mnemonics", FALSE,
/* Make gtk+ CSD not steal F10 from the terminal */
"gtk-menu-bar-accel", nullptr,
+#endif
nullptr);
if (options.css) {
+#if VTE_GTK == 3
gtk_style_context_add_provider_for_screen(gdk_screen_get_default (),
GTK_STYLE_PROVIDER(options.css.get()),
GTK_STYLE_PROVIDER_PRIORITY_USER);
+#elif VTE_GTK == 4
+ gtk_style_context_add_provider_for_display(gdk_display_get_default (),
+ GTK_STYLE_PROVIDER(options.css.get()),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+#endif
}
if (options.feed_stdin) {
@@ -2491,8 +2908,11 @@ main(int argc,
return EXIT_SUCCESS;
}
+#if VTE_GTK == 3
if (options.debug)
gdk_window_set_debug_updates(true);
+#endif /* VTE_GTK == 3 */
+
#ifdef VTE_DEBUG
if (options.test_mode) {
vte_set_test_flags(VTE_TEST_FLAGS_ALL);
diff --git a/src/app/appmenu-gtk4.ui b/src/app/appmenu-gtk4.ui
new file mode 100644
index 00000000..ac64ebb3
--- /dev/null
+++ b/src/app/appmenu-gtk4.ui
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2017, 2020 Christian Persch
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+-->
+<interface>
+ <menu id="app-menu">
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_New Terminal</attribute>
+ <attribute name="action">app.new</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Close</attribute>
+ <attribute name="action">app.close</attribute>
+ </item>
+ </section>
+ </menu>
+</interface>
diff --git a/src/app/meson.build b/src/app/meson.build
index f7df6dbf..dd9c713c 100644
--- a/src/app/meson.build
+++ b/src/app/meson.build
@@ -44,11 +44,11 @@ if get_option('gtk3')
)
app_gtk3_sources = app_sources + app_gtk3_resource_sources
- app_gtk3_cppflags = app_common_cppflags + gtk3_version_cppflags
+ app_gtk3_cppflags = app_common_cppflags + gtk3_version_cppflags + ['-DVTE_GTK=3',]
app_gtk3_deps = app_common_deps + [libvte_gtk3_dep]
app_gtk3 = executable(
- 'vte-' + vte_gtk3_api_version,
+ 'vte-' + vte_api_version,
app_gtk3_sources,
dependencies: app_gtk3_deps,
cpp_args: app_gtk3_cppflags,
@@ -56,3 +56,32 @@ if get_option('gtk3')
install: true,
)
endif
+
+if get_option('gtk4')
+
+ app_gtk4_resource_data = files(
+ 'appmenu-gtk4.ui',
+ 'search-popover-gtk4.ui',
+ 'window-gtk4.ui',
+ )
+
+ app_gtk4_resource_sources = gnome.compile_resources(
+ 'resources-gtk4.cc',
+ 'app-gtk4.gresource.xml',
+ c_name: 'app',
+ dependencies: app_gtk4_resource_data,
+ )
+
+ app_gtk4_sources = app_sources + [app_gtk4_resource_sources,]
+ app_gtk4_cppflags = app_common_cppflags + gtk4_version_cppflags + ['-DVTE_GTK=4',]
+ app_gtk4_deps = app_common_deps + [libvte_gtk4_dep]
+
+ app_gtk4 = executable(
+ 'vte-' + vte_api_version + '-gtk4',
+ app_gtk4_sources,
+ dependencies: app_gtk4_deps,
+ cpp_args: app_gtk4_cppflags,
+ include_directories: top_inc,
+ install: true,
+ )
+endif
diff --git a/src/app/search-popover-gtk3.ui b/src/app/search-popover-gtk3.ui
index d7191b86..fbad2d0b 100644
--- a/src/app/search-popover-gtk3.ui
+++ b/src/app/search-popover-gtk3.ui
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.19.0 -->
<!--
Copyright © 2016, 2017 Christian Persch
diff --git a/src/app/search-popover-gtk4.ui b/src/app/search-popover-gtk4.ui
new file mode 100644
index 00000000..4b187190
--- /dev/null
+++ b/src/app/search-popover-gtk4.ui
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2016, 2017, 2020 Christian Persch
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+-->
+<interface>
+ <requires lib="gtk+" version="3.16"/>
+ <template class="VteappSearchPopover" parent="GtkPopover">
+ <property name="can_focus">0</property>
+ <property name="child">
+ <object class="GtkBox" id="box1">
+ <property name="can_focus">0</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin_top">12</property>
+ <property name="margin_bottom">12</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="can_focus">0</property>
+ <property name="spacing">18</property>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="hexpand">1</property>
+ <property name="can_focus">0</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="hexpand">1</property>
+ <property name="activates_default">1</property>
+ <property name="width_chars">30</property>
+ <property name="placeholder_text" translatable="yes">Search</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_prev_button">
+ <property name="receives_default">1</property>
+ <property name="tooltip_text" translatable="yes">Search for previous occurrence</property>
+ <property name="focus_on_click">0</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="can_focus">0</property>
+ <property name="icon_name">go-up-symbolic</property>
+ <property name="use_fallback">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="search_next_button">
+ <property name="receives_default">1</property>
+ <property name="tooltip_text" translatable="yes">Search for next occurrence</property>
+ <property name="focus_on_click">0</property>
+ <child>
+ <object class="GtkImage" id="image3">
+ <property name="can_focus">0</property>
+ <property name="icon_name">go-down-symbolic</property>
+ <property name="use_fallback">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="linked"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="reveal_button">
+ <property name="receives_default">1</property>
+ <property name="tooltip_text" translatable="yes">Toggle search options</property>
+ <property name="focus_on_click">0</property>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="can_focus">0</property>
+ <property name="icon_name">open-menu-symbolic</property>
+ <property name="use_fallback">1</property>
+ </object>
+ </child>
+ <!--
+ <accessibility>
+ <relation type="controller-for" target="revealer"/>
+ </accessibility>
+ -->
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="close_button">
+ <property name="receives_default">1</property>
+ <property name="focus_on_click">0</property>
+ <child>
+ <object class="GtkImage" id="image4">
+ <property name="can_focus">0</property>
+ <property name="icon_name">window-close-symbolic</property>
+ <property name="use_fallback">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkRevealer" id="revealer">
+ <property name="can_focus">0</property>
+ <property name="transition_type">none</property>
+ <property name="reveal_child">0</property>
+ <property name="child">
+ <object class="GtkBox" id="box3">
+ <property name="can_focus">0</property>
+ <property name="margin_top">18</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="match_case_checkbutton">
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">_Match case</property>
+ <property name="use_underline">1</property>
+ <property name="focus_on_click">0</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="entire_word_checkbutton">
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Match _entire word only</property>
+ <property name="use_underline">1</property>
+ <property name="focus_on_click">0</property>
+ <property name="halign">start</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="regex_checkbutton">
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">Match as _regular expression</property>
+ <property name="use_underline">1</property>
+ <property name="focus_on_click">0</property>
+ <property name="halign">start</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="wrap_around_checkbutton">
+ <property name="valign">center</property>
+ <property name="label" translatable="yes">_Wrap around</property>
+ <property name="use_underline">1</property>
+ <property name="focus_on_click">0</property>
+ <property name="halign">start</property>
+ <property name="active">1</property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+</interface>
diff --git a/src/app/window-gtk3.ui b/src/app/window-gtk3.ui
index 29758b1a..b7bdb012 100644
--- a/src/app/window-gtk3.ui
+++ b/src/app/window-gtk3.ui
@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.19.0 -->
<!--
Copyright © 2014, 2017 Christian Persch
diff --git a/src/app/window-gtk4.ui b/src/app/window-gtk4.ui
new file mode 100644
index 00000000..dc3c33a4
--- /dev/null
+++ b/src/app/window-gtk4.ui
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2014, 2017, 2020 Christian Persch
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+-->
+<interface>
+ <requires lib="gtk+" version="3.10"/>
+ <menu id="gear_menu_model">
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_New Terminal</attribute>
+ <attribute name="action">app.new</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Copy</attribute>
+ <attribute name="action">win.copy</attribute>
+ <attribute name="target">text</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Copy As _HTML</attribute>
+ <attribute name="action">win.copy</attribute>
+ <attribute name="target">html</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Paste</attribute>
+ <attribute name="action">win.paste</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Find…</attribute>
+ <attribute name="action">win.find</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Reset</attribute>
+ <attribute name="action">win.reset</attribute>
+ <attribute name="target" type="b">false</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">Reset and Cl_ear</attribute>
+ <attribute name="action">win.reset</attribute>
+ <attribute name="target" type="b">true</attribute>
+ </item>
+ <item>
+ <attribute name="label" translatable="yes">_Input enabled</attribute>
+ <attribute name="action">win.input-enabled</attribute>
+ </item>
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Fullscreen</attribute>
+ <attribute name="action">win.fullscreen</attribute>
+ </item>
+ </section>
+ </menu>
+ <template class="VteappWindow" parent="GtkApplicationWindow">
+ <property name="can_focus">0</property>
+ <property name="icon_name">utilities-terminal</property>
+ <child>
+ <object class="GtkGrid" id="window_grid">
+ <property name="can_focus">0</property>
+ <property name="halign">fill</property>
+ <property name="valign">fill</property>
+ <property name="hexpand">1</property>
+ <property name="vexpand">1</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkScrollbar" id="scrollbar">
+ <property name="can_focus">0</property>
+ <property name="orientation">vertical</property>
+ <property name="hexpand">0</property>
+ <property name="vexpand">1</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="titlebar">
+ <object class="GtkHeaderBar" id="headerbar">
+ <property name="can_focus">0</property>
+ <property name="decoration_layout">:close</property>
+ <child type="start">
+ <object class="GtkButton" id="copy_button">
+ <property name="receives_default">1</property>
+ <property name="tooltip_text" translatable="yes">Copy</property>
+ <property name="action_name">win.copy</property>
+ <property name="action_target">&quot;text&quot;</property>
+ <property name="focus_on_click">0</property>
+ <child>
+ <object class="GtkImage" id="image2">
+ <property name="can_focus">0</property>
+ <property name="icon_name">edit-copy-symbolic</property>
+ <property name="use_fallback">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="start">
+ <object class="GtkButton" id="paste_button">
+ <property name="receives_default">1</property>
+ <property name="tooltip_text" translatable="yes">Paste</property>
+ <property name="action_name">win.paste</property>
+ <property name="focus_on_click">0</property>
+ <child>
+ <object class="GtkImage" id="image3">
+ <property name="can_focus">0</property>
+ <property name="icon_name">edit-paste-symbolic</property>
+ <property name="use_fallback">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="start">
+ <object class="GtkToggleButton" id="find_button">
+ <property name="receives_default">1</property>
+ <property name="focus_on_click">0</property>
+ <child>
+ <object class="GtkImage" id="image5">
+ <property name="can_focus">0</property>
+ <property name="icon_name">edit-find-symbolic</property>
+ <property name="use_fallback">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="title">
+ <placeholder/>
+ </child>
+ <child type="end">
+ <object class="GtkMenuButton" id="gear_button">
+ <property name="receives_default">1</property>
+ <property name="focus_on_click">0</property>
+ <property name="menu-model">gear_menu_model</property>
+ <property name="icon_name">open-menu-symbolic</property>
+ </object>
+ </child>
+ <child type="end">
+ <object class="GtkGrid" id="notifications_grid">
+ <property name="can_focus">0</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <property name="hexpand">0</property>
+ <property name="vexpand">1</property>
+ <child>
+ <object class="GtkImage" id="readonly_emblem">
+ <property name="visible">0</property>
+ <property name="can_focus">0</property>
+ <property name="tooltip_text" translatable="yes">Read-only</property>
+ <property name="icon_name">emblem-readonly</property>
+ <property name="use_fallback">1</property>
+ <property name="hexpand">0</property>
+ <property name="vexpand">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/cairo-glue.hh b/src/cairo-glue.hh
index 234c8fcd..c6370e33 100644
--- a/src/cairo-glue.hh
+++ b/src/cairo-glue.hh
@@ -23,7 +23,9 @@
namespace vte {
-VTE_DECLARE_FREEABLE(cairo_t, cairo_destroy);
+VTE_DECLARE_FREEABLE(cairo_rectangle_list_t, cairo_rectangle_list_destroy);
+VTE_DECLARE_FREEABLE(cairo_region_t, cairo_region_destroy);
VTE_DECLARE_FREEABLE(cairo_surface_t, cairo_surface_destroy);
+VTE_DECLARE_FREEABLE(cairo_t, cairo_destroy);
} // namespace vte::cairo
diff --git a/src/clipboard-gtk.cc b/src/clipboard-gtk.cc
index a70c0eea..402e3a41 100644
--- a/src/clipboard-gtk.cc
+++ b/src/clipboard-gtk.cc
@@ -22,6 +22,7 @@
#include "widget.hh"
#include "vteinternal.hh"
+#include <new>
#include <stdexcept>
#include <utility>
@@ -42,12 +43,20 @@ Clipboard::Clipboard(Widget& delegate,
switch (type) {
case ClipboardType::PRIMARY:
- m_clipboard = vte::glib::make_ref(gtk_clipboard_get_for_display(display,
- GDK_SELECTION_PRIMARY));
+ m_clipboard = vte::glib::make_ref
+#if VTE_GTK == 3
+ (gtk_clipboard_get_for_display(display, GDK_SELECTION_PRIMARY));
+#elif VTE_GTK == 4
+ (gdk_display_get_primary_clipboard(display));
+#endif
break;
case ClipboardType::CLIPBOARD:
- m_clipboard = vte::glib::make_ref(gtk_clipboard_get_for_display(display,
- GDK_SELECTION_CLIPBOARD));
+ m_clipboard = vte::glib::make_ref
+#if VTE_GTK == 3
+ (gtk_clipboard_get_for_display(display, GDK_SELECTION_CLIPBOARD));
+#elif VTE_GTK == 4
+ (gdk_display_get_clipboard(display));
+#endif
break;
}
@@ -55,6 +64,8 @@ Clipboard::Clipboard(Widget& delegate,
throw std::runtime_error{"Failed to create clipboard"};
}
+#if VTE_GTK == 3
+
class Clipboard::Offer {
public:
Offer(Clipboard& clipboard,
@@ -75,7 +86,7 @@ public:
{
auto [targets, n_targets] = targets_for_format(format);
- // Transfers clipboardship of *offer to the clipboard. If setting succeeds,
+ // Transfers ownership of *offer to the clipboard. If setting succeeds,
// the clipboard will own *offer until the clipboard_data_clear_cb
// callback is called.
// If setting the clipboard fails, the clear callback will never be
@@ -150,8 +161,8 @@ private:
guint info,
void* user_data) noexcept
{
- if (info != vte::to_integral(ClipboardFormat::TEXT) &&
- info != vte::to_integral(ClipboardFormat::HTML))
+ if (int(info) != vte::to_integral(ClipboardFormat::TEXT) &&
+ int(info) != vte::to_integral(ClipboardFormat::HTML))
return;
reinterpret_cast<Offer*>(user_data)->dispatch_get(ClipboardFormat(info), data);
@@ -161,12 +172,11 @@ private:
clipboard_clear_cb(GtkClipboard* clipboard,
void* user_data) noexcept
{
- // Assume ownership of the Request, and delete it after dispatching the callback
+ // Assume ownership of the Offer, and delete it after dispatching the callback
auto offer = std::unique_ptr<Offer>{reinterpret_cast<Offer*>(user_data)};
offer->dispatch_clear();
}
-
static std::pair<GtkTargetEntry*, int>
targets_for_format(ClipboardFormat format)
{
@@ -227,6 +237,8 @@ private:
}; // class Clipboard::Offer
+#endif /* VTE_GTK == 3 */
+
class Clipboard::Request {
public:
Request(Clipboard& clipboard,
@@ -244,10 +256,12 @@ public:
static void run(std::unique_ptr<Request> request) noexcept
{
+#if VTE_GTK == 3
auto platform = request->clipboard().platform();
gtk_clipboard_request_text(platform,
text_received_cb,
request.release());
+#endif /* VTE_GTK */
}
private:
@@ -255,6 +269,7 @@ private:
RequestDoneCallback m_done_callback;
RequestFailedCallback m_failed_callback;
+#if VTE_GTK == 3
void dispatch(char const *text) noexcept
try
{
@@ -278,6 +293,8 @@ private:
request->dispatch(text);
}
+#endif /* VTE_GTK */
+
}; // class Clipboard::Request
void
@@ -285,13 +302,17 @@ Clipboard::offer_data(ClipboardFormat format,
OfferGetCallback get_callback,
OfferClearCallback clear_callback) /* throws */
{
+#if VTE_GTK == 3
Offer::run(std::make_unique<Offer>(*this, get_callback, clear_callback), format);
+#endif
}
void
Clipboard::set_text(std::string_view const& text) noexcept
{
+#if VTE_GTK == 3
gtk_clipboard_set_text(platform(), text.data(), text.size());
+#endif
}
void
diff --git a/src/clipboard-gtk.hh b/src/clipboard-gtk.hh
index d2b66228..45660c3e 100644
--- a/src/clipboard-gtk.hh
+++ b/src/clipboard-gtk.hh
@@ -75,7 +75,11 @@ public:
RequestFailedCallback failed_callback) /* throws */;
private:
+#if VTE_GTK == 3
vte::glib::RefPtr<GtkClipboard> m_clipboard;
+#elif VTE_GTK == 4
+ vte::glib::RefPtr<GdkClipboard> m_clipboard;
+#endif
std::weak_ptr<Widget> m_delegate;
ClipboardType m_type;
diff --git a/src/debug.h b/src/debug.h
index c91c4968..da1d51d8 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -113,6 +113,12 @@ static void _vte_debug_print(guint flags, const char *fmt, ...)
#define _vte_debug_print(args...) do { } while(0)
#endif /* VTE_DEBUG */
+static inline char const*
+_vte_debug_tf(bool v) noexcept
+{
+ return v ? "true" : "false";
+}
+
G_END_DECLS
#endif
diff --git a/src/fonts-pangocairo.cc b/src/fonts-pangocairo.cc
index fc0f4e54..995b441e 100644
--- a/src/fonts-pangocairo.cc
+++ b/src/fonts-pangocairo.cc
@@ -210,13 +210,13 @@ FontInfo::measure_font()
}
}
-FontInfo::FontInfo(PangoContext *context)
+FontInfo::FontInfo(vte::glib::RefPtr<PangoContext> context)
{
_vte_debug_print (VTE_DEBUG_PANGOCAIRO,
"vtepangocairo: %p allocating FontInfo\n",
(void*)this);
- m_layout = vte::glib::take_ref(pango_layout_new(context));
+ m_layout = vte::glib::take_ref(pango_layout_new(context.get()));
auto tabs = pango_tab_array_new_with_positions(1, FALSE, PANGO_TAB_LEFT, 1);
pango_layout_set_tabs(m_layout.get(), tabs);
@@ -230,7 +230,7 @@ FontInfo::FontInfo(PangoContext *context)
#if PANGO_VERSION_CHECK(1, 44, 0)
/* Try using the font's metrics; see issue#163. */
if (auto metrics = vte::take_freeable
- (pango_context_get_metrics(context,
+ (pango_context_get_metrics(context.get(),
nullptr /* use font from context */,
nullptr /* use language from context */))) {
/* Use provided metrics if possible */
@@ -337,7 +337,7 @@ context_equal (PangoContext *a,
&& vte_pango_context_get_fontconfig_timestamp (a) == vte_pango_context_get_fontconfig_timestamp (b);
}
-/* assumes ownership/reference of context */
+// FIXMEchpe return vte::base::RefPtr<FontInfo>
FontInfo*
FontInfo::create_for_context(vte::glib::RefPtr<PangoContext> context,
PangoFontDescription const* desc,
@@ -381,14 +381,13 @@ FontInfo::create_for_context(vte::glib::RefPtr<PangoContext> context,
info);
info = info->ref();
} else {
- _vte_debug_print (VTE_DEBUG_PANGOCAIRO,
- "vtepangocairo: FontInfo not in cache\n");
- info = new FontInfo{context.get()};
- }
+ info = new FontInfo{std::move(context)};
+ }
return info;
}
+#if VTE_GTK == 3
FontInfo*
FontInfo::create_for_screen(GdkScreen* screen,
PangoFontDescription const* desc,
@@ -400,15 +399,28 @@ FontInfo::create_for_screen(GdkScreen* screen,
return create_for_context(vte::glib::take_ref(gdk_pango_context_get_for_screen(screen)),
desc, language, fontconfig_timestamp);
}
+#endif /* VTE_GTK */
FontInfo*
FontInfo::create_for_widget(GtkWidget* widget,
PangoFontDescription const* desc)
{
- auto screen = gtk_widget_get_screen(widget);
- auto language = pango_context_get_language(gtk_widget_get_pango_context(widget));
+ auto context = gtk_widget_get_pango_context(widget);
+ auto language = pango_context_get_language(context);
+#if VTE_GTK == 3
+ auto screen = gtk_widget_get_screen(widget);
return create_for_screen(screen, desc, language);
+#elif VTE_GTK == 4
+ auto display = gtk_widget_get_display(widget);
+ auto settings = gtk_settings_get_for_display(display);
+ auto fontconfig_timestamp = guint{};
+ g_object_get (settings, "gtk-fontconfig-timestamp", &fontconfig_timestamp, nullptr);
+ return create_for_context(vte::glib::make_ref(context),
+ desc, language, fontconfig_timestamp);
+ // FIXMEgtk4: this uses a per-widget context, while the gtk3 code uses a per-screen
+ // one. That means there may be a lot less sharing and a lot more FontInfo's around?
+#endif
}
FontInfo::UnistrInfo*
diff --git a/src/fonts-pangocairo.hh b/src/fonts-pangocairo.hh
index c7aac75c..586e6668 100644
--- a/src/fonts-pangocairo.hh
+++ b/src/fonts-pangocairo.hh
@@ -120,7 +120,7 @@ class FontInfo {
int const font_cache_timeout = 30; // seconds
public:
- FontInfo(PangoContext* context);
+ FontInfo(vte::glib::RefPtr<PangoContext> context);
~FontInfo();
FontInfo* ref()
@@ -269,9 +269,12 @@ private:
PangoFontDescription const* desc,
PangoLanguage* language,
guint fontconfig_timestamp);
+#if VTE_GTK == 3
static FontInfo *create_for_screen(GdkScreen* screen,
PangoFontDescription const* desc,
PangoLanguage* language);
+#endif
+
public:
static FontInfo *create_for_widget(GtkWidget* widget,
diff --git a/src/graphene-glue.hh b/src/graphene-glue.hh
new file mode 100644
index 00000000..16456117
--- /dev/null
+++ b/src/graphene-glue.hh
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2020 Christian Persch
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <cairo.h>
+#include <graphene.h>
+
+#include "std-glue.hh"
+
+namespace vte::graphene {
+
+inline constexpr auto
+make_rect(int x,
+ int y,
+ int width,
+ int height)
+{
+ return GRAPHENE_RECT_INIT(float(x), float(y), float(width), float(height));
+}
+
+inline constexpr auto
+make_rect(cairo_rectangle_int_t const* rect)
+{
+ return make_rect(rect->x, rect->y, rect->width, rect->height);
+}
+
+} // namespace vte::graphene
+
+namespace vte {
+
+// VTE_DECLARE_FREEABLE(graphene_rect_t, graphene_rect_free);
+
+} // namespace vte::cairo
diff --git a/src/gtk-glue.hh b/src/gtk-glue.hh
index 1634beb6..71ffc9fd 100644
--- a/src/gtk-glue.hh
+++ b/src/gtk-glue.hh
@@ -25,6 +25,12 @@ namespace vte::gtk {
namespace vte {
+#if VTE_GTK == 3
VTE_DECLARE_FREEABLE(GtkTargetList, gtk_target_list_unref);
+#endif /* VTE_GTK == 3 */
+
+#if VTE_GTK == 4
+VTE_DECLARE_FREEABLE(GdkContentFormats, gdk_content_formats_unref);
+#endif /* VTE_GTK == 4 */
} // namespace vte
diff --git a/src/keymap.h b/src/keymap.h
index 3feef90e..4eface40 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -25,8 +25,13 @@
G_BEGIN_DECLS
+#if VTE_GTK == 3
#define VTE_ALT_MASK GDK_MOD1_MASK
#define VTE_NUMLOCK_MASK GDK_MOD2_MASK
+#elif VTE_GTK == 4
+#define VTE_ALT_MASK GDK_ALT_MASK
+#define VTE_NUMLOCK_MASK 0 /* FIXME */
+#endif
/* Map the specified keyval/modifier setup, dependent on the mode, to either
* a literal string or a capability name. */
diff --git a/src/meson.build b/src/meson.build
index bfbeebb2..e9192be0 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -32,6 +32,10 @@ glib_glue_sources = files(
'glib-glue.hh',
)
+graphene_glue_sources = files(
+ 'graphene-glue.hh',
+)
+
gtk_glue_sources = files(
'gtk-glue.hh',
)
@@ -212,10 +216,6 @@ libvte_common_sources = config_sources + debug_sources + glib_glue_sources + gtk
'widget.hh',
)
-if get_option('a11y')
- libvte_common_sources += a11y_sources
-endif
-
if get_option('icu')
libvte_common_sources += icu_sources
endif
@@ -294,9 +294,13 @@ libvte_common_cppflags = [
if get_option('gtk3')
libvte_gtk3_sources = libvte_common_sources + libvte_gtk3_public_headers + libvte_gtk3_enum_sources
- libvte_gtk3_cppflags = libvte_common_cppflags + gtk3_version_cppflags
- libvte_gtk3_deps = libvte_common_deps + [gtk3_dep]
- libvte_gtk3_public_deps = libvte_common_public_deps + [gtk3_dep]
+ libvte_gtk3_cppflags = libvte_common_cppflags + gtk3_version_cppflags + ['-DVTE_GTK=3',]
+ libvte_gtk3_deps = libvte_common_deps + [gtk3_dep,]
+ libvte_gtk3_public_deps = libvte_common_public_deps + [gtk3_dep,]
+
+ if get_option('a11y')
+ libvte_gtk3_sources += a11y_sources
+ endif
libvte_gtk3 = shared_library(
vte_gtk3_api_name,
@@ -310,7 +314,7 @@ if get_option('gtk3')
libvte_gtk3_dep = declare_dependency(
sources: libvte_gtk3_public_headers,
- include_directories: [src_inc, vte_inc],
+ include_directories: [src_inc, vte_inc,],
dependencies: libvte_gtk3_deps,
link_with: libvte_gtk3
)
@@ -327,6 +331,41 @@ if get_option('gtk3')
)
endif
+if get_option('gtk4')
+ libvte_gtk4_sources = libvte_common_sources + libvte_gtk4_public_headers + libvte_gtk4_enum_sources + graphene_glue_sources
+ libvte_gtk4_cppflags = libvte_common_cppflags + gtk4_version_cppflags + ['-DVTE_GTK=4',]
+ libvte_gtk4_deps = libvte_common_deps + [gtk4_dep,]
+ libvte_gtk4_public_deps = libvte_common_public_deps + [gtk4_dep,]
+
+ libvte_gtk4 = shared_library(
+ vte_gtk4_api_name,
+ sources: libvte_gtk4_sources,
+ version: libvte_gtk4_soversion,
+ include_directories: incs,
+ dependencies: libvte_gtk4_deps,
+ cpp_args: libvte_gtk4_cppflags,
+ install: true,
+ )
+
+ libvte_gtk4_dep = declare_dependency(
+ sources: libvte_gtk4_public_headers,
+ include_directories: [src_inc, vte_inc,],
+ dependencies: libvte_gtk4_deps,
+ link_with: libvte_gtk4
+ )
+
+ pkg.generate(
+ libvte_gtk4,
+ version: vte_version,
+ name: 'vte',
+ description: 'VTE widget for GTK+ 4.0',
+ filebase: vte_gtk4_api_name,
+ subdirs: vte_gtk4_api_name,
+ requires: libvte_gtk4_public_deps,
+ variables: 'exec_prefix=${prefix}',
+ )
+endif
+
## Tests
# decoder cat
@@ -425,17 +464,19 @@ reflect_textview = executable(
install: false,
)
-reflect_vte = executable(
- 'reflect-vte',
- sources: reflect_sources,
- dependencies: [gtk3_dep, libvte_gtk3_dep],
- c_args: [
- '-DUSE_VTE',
- '-DVTE_DISABLE_DEPRECATION_WARNINGS',
- ],
- include_directories: top_inc,
- install: false,
-)
+if get_option('gtk3')
+ reflect_vte = executable(
+ 'reflect-vte',
+ sources: reflect_sources,
+ dependencies: [gtk3_dep, libvte_gtk3_dep,],
+ c_args: [
+ '-DUSE_VTE',
+ '-DVTE_DISABLE_DEPRECATION_WARNINGS',
+ ],
+ include_directories: [top_inc,],
+ install: false,
+ )
+endif
# vte-urlencode-cwd
@@ -599,14 +640,16 @@ test_vtetypes_sources = config_sources + libc_glue_sources + files(
'vtetypes.hh',
)
-test_vtetypes = executable(
- 'test-vtetypes',
- sources: test_vtetypes_sources,
- dependencies: [glib_dep, pango_dep, gtk3_dep],
- cpp_args: ['-DMAIN'],
- include_directories: top_inc,
- install: false,
-)
+if get_option('gtk3')
+ test_vtetypes = executable(
+ 'test-vtetypes',
+ sources: test_vtetypes_sources,
+ dependencies: [glib_dep, pango_dep, gtk3_dep,],
+ cpp_args: ['-DMAIN'],
+ include_directories: top_inc,
+ install: false,
+ )
+endif
test_env = [
'VTE_DEBUG=0'
@@ -621,9 +664,14 @@ test_units = [
['stream', test_stream],
['tabstops', test_tabstops],
['utf8', test_utf8],
- ['vtetypes', test_vtetypes],
]
+if get_option('gtk3')
+ test_units += [
+ ['vtetypes', test_vtetypes],
+ ]
+endif
+
if get_option('sixel')
test_units += [
['sixel', test_sixel],
diff --git a/src/vte.cc b/src/vte.cc
index 64193498..0aec5fd2 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004,2009,2010 Red Hat, Inc.
- * Copyright © 2008, 2009, 2010 Christian Persch
+ * Copyright © 2008, 2009, 2010, 2020 Christian Persch
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
@@ -49,6 +49,7 @@
#include "ringview.hh"
#include "caps.hh"
#include "widget.hh"
+#include "cairo-glue.hh"
#ifdef HAVE_WCHAR_H
#include <wchar.h>
@@ -72,8 +73,12 @@
#include "gobject-glue.hh"
#ifdef WITH_A11Y
+#if VTE_GTK == 3
#include "vteaccess.h"
-#endif
+#else
+#undef WITH_A11Y
+#endif /* VTE_GTK == 3 */
+#endif /* WITH_A11Y */
#include <new> /* placement new */
@@ -95,6 +100,12 @@ static inline double round(double x) {
#define VTE_DRAW_OPAQUE (1.0)
+#if VTE_GTK == 3
+#define VTE_STYLE_CLASS_READ_ONLY GTK_STYLE_CLASS_READ_ONLY
+#elif VTE_GTK == 4
+#define VTE_STYLE_CLASS_READ_ONLY "read-only"
+#endif
+
namespace vte {
namespace terminal {
@@ -106,7 +117,10 @@ static void remove_update_timeout(vte::terminal::Terminal* that);
static gboolean process_timeout (gpointer data) noexcept;
static gboolean update_timeout (gpointer data) noexcept;
-static cairo_region_t *vte_cairo_get_clip_region (cairo_t *cr);
+
+#if VTE_GTK == 3
+static vte::Freeable<cairo_region_t> vte_cairo_get_clip_region(cairo_t* cr);
+#endif
/* these static variables are guarded by the GDK mutex */
static guint process_timeout_tag = 0;
@@ -438,7 +452,11 @@ Terminal::invalidate_rows(vte::grid::row_t row_start,
rect.x += allocation.x + m_padding.left;
rect.y += allocation.y + m_padding.top;
cairo_region_t *region = cairo_region_create_rectangle(&rect);
+#if VTE_GTK == 3
gtk_widget_queue_draw_region(m_widget, region);
+#elif VTE_GTK == 4
+ gtk_widget_queue_draw(m_widget); // FIXMEchpe
+#endif
cairo_region_destroy(region);
}
@@ -1528,6 +1546,9 @@ Terminal::regex_match_check(vte::grid::column_t column,
vte::grid::row_t row,
int* tag)
{
+ /* Need to ensure the ringview is updated. */
+ ringview_update();
+
long delta = m_screen->scroll_delta;
_vte_debug_print(VTE_DEBUG_EVENTS | VTE_DEBUG_REGEX,
"Checking for match at (%ld,%ld).\n",
@@ -1568,7 +1589,11 @@ Terminal::regex_match_check(vte::grid::column_t column,
vte::view::coords
Terminal::view_coords_from_event(vte::platform::MouseEvent const& event) const
{
+#if VTE_GTK == 3
return vte::view::coords(event.x() - m_padding.left, event.y() - m_padding.top);
+#elif VTE_GTK == 4
+ return vte::view::coords(event.x(), event.y());
+#endif
}
bool
@@ -1816,10 +1841,50 @@ Terminal::rowcol_from_event(vte::platform::MouseEvent const& event,
return true;
}
-char *
+#if VTE_GTK == 4
+
+bool
+Terminal::rowcol_at(double x,
+ double y,
+ long* column,
+ long* row)
+{
+ auto rowcol = grid_coords_from_view_coords(vte::view::coords(x, y));
+ if (!grid_coords_visible(rowcol))
+ return false;
+
+ *column = rowcol.column();
+ *row = rowcol.row();
+ return true;
+}
+
+char*
+Terminal::hyperlink_check_at(double x,
+ double y)
+{
+ long col, row;
+ if (!rowcol_at(x, y, &col, &row))
+ return nullptr;
+
+ return hyperlink_check(col, row);
+}
+
+#endif /* VTE_GTK == 4 */
+
+char*
Terminal::hyperlink_check(vte::platform::MouseEvent const& event)
{
long col, row;
+ if (!rowcol_from_event(event, &col, &row))
+ return nullptr;
+
+ return hyperlink_check(col, row);
+}
+
+char*
+Terminal::hyperlink_check(vte::grid::column_t col,
+ vte::grid::row_t row)
+{
const char *hyperlink;
const char *separator;
@@ -1829,9 +1894,6 @@ Terminal::hyperlink_check(vte::platform::MouseEvent const& event)
/* Need to ensure the ringview is updated. */
ringview_update();
- if (!rowcol_from_event(event, &col, &row))
- return NULL;
-
_vte_ring_get_hyperlink_at_position(m_screen->row_data, row, col, false, &hyperlink);
if (hyperlink != NULL) {
@@ -1848,15 +1910,12 @@ Terminal::hyperlink_check(vte::platform::MouseEvent const& event)
return g_strdup(hyperlink);
}
-char *
+char*
Terminal::regex_match_check(vte::platform::MouseEvent const& event,
int *tag)
{
long col, row;
- /* Need to ensure the ringview is updated. */
- ringview_update();
-
if (!rowcol_from_event(event, &col, &row))
return FALSE;
@@ -1872,9 +1931,23 @@ Terminal::regex_match_check_extra(vte::platform::MouseEvent const& event,
uint32_t match_flags,
char** matches)
{
+ long col, row;
+ if (!rowcol_from_event(event, &col, &row))
+ return false;
+
+ return regex_match_check_extra(col, row, regexes, n_regexes, match_flags, matches);
+}
+
+bool
+Terminal::regex_match_check_extra(vte::grid::column_t col,
+ vte::grid::row_t row,
+ vte::base::Regex const** regexes,
+ size_t n_regexes,
+ uint32_t match_flags,
+ char** matches)
+{
gsize offset, sattr, eattr;
bool any_matches = false;
- long col, row;
guint i;
assert(regexes != nullptr || n_regexes == 0);
@@ -1883,9 +1956,6 @@ Terminal::regex_match_check_extra(vte::platform::MouseEvent const& event,
/* Need to ensure the ringview is updated. */
ringview_update();
- if (!rowcol_from_event(event, &col, &row))
- return false;
-
if (m_match_contents == nullptr) {
match_contents_refresh();
}
@@ -4583,10 +4653,11 @@ Terminal::beep()
bool
Terminal::widget_key_press(vte::platform::KeyEvent const& event)
{
+ auto handled = false;
char *normal = NULL;
gsize normal_length = 0;
struct termios tio;
- gboolean scrolled = FALSE, steal = FALSE, modifier = FALSE, handled,
+ gboolean scrolled = FALSE, steal = FALSE, modifier = FALSE,
suppress_alt_esc = FALSE, add_modifiers = FALSE;
guint keyval = 0;
gunichar keychar = 0;
@@ -4614,12 +4685,6 @@ Terminal::widget_key_press(vte::platform::KeyEvent const& event)
set_pointer_autohidden(true);
}
- _vte_debug_print(VTE_DEBUG_EVENTS,
- "Keypress, modifiers=0x%x, "
- "keyval=0x%x\n",
- m_modifiers,
- keyval);
-
/* We steal many keypad keys here. */
if (!m_im_preedit_active) {
switch (keyval) {
@@ -4709,6 +4774,7 @@ Terminal::widget_key_press(vte::platform::KeyEvent const& event)
/* Let the input method at this one first. */
if (!steal && m_input_enabled) {
+ // FIXMEchpe FIXMEgtk4: update IM position? im_set_cursor_location()
if (m_real_widget->im_filter_keypress(event)) {
_vte_debug_print(VTE_DEBUG_EVENTS,
"Keypress taken by IM.\n");
@@ -5040,6 +5106,16 @@ Terminal::widget_key_press(vte::platform::KeyEvent const& event)
}
return true;
}
+
+#if VTE_GTK == 4
+ if (!handled &&
+ event.matches(GDK_KEY_Menu, 0)) {
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Showing context menu\n");
+ // FIXMEgtk4 do context menu
+ handled = true;
+ }
+#endif
+
return false;
}
@@ -5960,6 +6036,8 @@ Terminal::invalidate_match_span()
void
Terminal::match_hilite_update()
{
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Match hilite update\n");
+
/* Need to ensure the ringview is updated. */
ringview_update();
@@ -5973,10 +6051,6 @@ Terminal::match_hilite_update()
vte::base::BidiRow const* bidirow = m_ringview.get_bidirow(confine_grid_row(row));
col = bidirow->vis2log(col);
- _vte_debug_print(VTE_DEBUG_EVENTS,
- "Match hilite update (%ld, %ld) -> %ld, %ld\n",
- pos.x, pos.y, col, row);
-
/* Whether there's any chance we'd highlight something */
bool do_check_hilite = view_coords_visible(pos) &&
m_mouse_cursor_over_widget &&
@@ -6768,8 +6842,7 @@ Terminal::widget_mouse_motion(vte::platform::MouseEvent const& event)
auto rowcol = grid_coords_from_view_coords(pos);
_vte_debug_print(VTE_DEBUG_EVENTS,
- "Motion notify %s %s\n",
- pos.to_string(), rowcol.to_string());
+ "Motion grid %s\n", rowcol.to_string());
m_modifiers = event.modifiers();
@@ -6824,17 +6897,22 @@ Terminal::widget_mouse_press(vte::platform::MouseEvent const& event)
/* Need to ensure the ringview is updated. */
ringview_update();
+ /* Reset IM (like GtkTextView does) here */
+ if (event.press_count() == 1)
+ widget()->im_reset();
+
auto pos = view_coords_from_event(event);
auto rowcol = grid_coords_from_view_coords(pos);
+ _vte_debug_print(VTE_DEBUG_EVENTS,
+ "Click gesture pressed button=%d at grid %s\n",
+ event.button_value(),
+ rowcol.to_string());
+
m_modifiers = event.modifiers();
switch (event.press_count()) {
case 1: /* single click */
- _vte_debug_print(VTE_DEBUG_EVENTS,
- "Button %d single-click at %s\n",
- event.button_value(),
- rowcol.to_string());
/* Handle this event ourselves. */
switch (event.button()) {
case vte::platform::MouseEvent::Button::eLEFT:
@@ -6844,6 +6922,8 @@ Terminal::widget_mouse_press(vte::platform::MouseEvent const& event)
if (!m_has_focus)
widget()->grab_focus();
+ // FIXMEchpe FIXMEgtk do im_reset() here
+
/* If we're in event mode, and the user held down the
* shift key, we start selecting. */
if (m_mouse_tracking_mode != MouseTrackingMode::eNONE) {
@@ -6904,10 +6984,6 @@ Terminal::widget_mouse_press(vte::platform::MouseEvent const& event)
}
break;
case 2: /* double click */
- _vte_debug_print(VTE_DEBUG_EVENTS,
- "Button %d double-click at %s\n",
- event.button_value(),
- rowcol.to_string());
switch (event.button()) {
case vte::platform::MouseEvent::Button::eLEFT:
if (m_will_select_after_threshold) {
@@ -6928,10 +7004,6 @@ Terminal::widget_mouse_press(vte::platform::MouseEvent const& event)
}
break;
case 3: /* triple click */
- _vte_debug_print(VTE_DEBUG_EVENTS,
- "Button %d triple-click at %s\n",
- event.button_value(),
- rowcol.to_string());
switch (event.button()) {
case vte::platform::MouseEvent::Button::eLEFT:
if ((m_mouse_handled_buttons & 1) != 0) {
@@ -6949,6 +7021,16 @@ Terminal::widget_mouse_press(vte::platform::MouseEvent const& event)
break;
}
+#if VTE_GTK == 4
+ if (!handled &&
+ ((event.button() == vte::platform::MouseEvent::Button::eRIGHT) ||
+ !(event.modifiers() & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK)))) {
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Showing context menu\n");
+ // FIXMEgtk4 context menu
+ handled = true;
+ }
+#endif /* VTE_GTK == 4 */
+
/* Save the pointer state for later use. */
if (event.button_value() >= 1 && event.button_value() <= 3)
m_mouse_pressed_buttons |= (1 << (event.button_value() - 1));
@@ -6973,15 +7055,16 @@ Terminal::widget_mouse_release(vte::platform::MouseEvent const& event)
auto pos = view_coords_from_event(event);
auto rowcol = grid_coords_from_view_coords(pos);
+ _vte_debug_print(VTE_DEBUG_EVENTS,
+ "Click gesture released button=%d at grid %s\n",
+ event.button_value(), rowcol.to_string());
+
stop_autoscroll();
m_modifiers = event.modifiers();
switch (event.type()) {
case vte::platform::EventBase::Type::eMOUSE_RELEASE:
- _vte_debug_print(VTE_DEBUG_EVENTS,
- "Button %d released at %s\n",
- event.button_value(), rowcol.to_string());
switch (event.button()) {
case vte::platform::MouseEvent::Button::eLEFT:
if ((m_mouse_handled_buttons & 1) != 0)
@@ -7020,8 +7103,6 @@ Terminal::widget_mouse_release(vte::platform::MouseEvent const& event)
void
Terminal::widget_focus_in()
{
- _vte_debug_print(VTE_DEBUG_EVENTS, "Focus in.\n");
-
m_has_focus = true;
widget()->grab_focus();
@@ -7049,8 +7130,6 @@ Terminal::widget_focus_in()
void
Terminal::widget_focus_out()
{
- _vte_debug_print(VTE_DEBUG_EVENTS, "Focus out.\n");
-
/* We only have an IM context when we're realized, and there's not much
* point to painting ourselves if we don't have a window. */
if (widget_realized()) {
@@ -7083,8 +7162,9 @@ Terminal::widget_mouse_enter(vte::platform::MouseEvent const& event)
auto pos = view_coords_from_event(event);
// FIXMEchpe read event modifiers here
+ // FIXMEgtk4 or maybe not since there is no event to read them from on gtk4
- _vte_debug_print(VTE_DEBUG_EVENTS, "Enter at %s\n", pos.to_string());
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Motion enter at grid %s\n", pos.to_string());
m_mouse_cursor_over_widget = TRUE;
m_mouse_last_position = pos;
@@ -7098,14 +7178,23 @@ Terminal::widget_mouse_enter(vte::platform::MouseEvent const& event)
void
Terminal::widget_mouse_leave(vte::platform::MouseEvent const& event)
{
+#if VTE_GTK == 3
auto pos = view_coords_from_event(event);
// FIXMEchpe read event modifiers here
+ // FIXMEgtk4 or maybe not since there is no event to read them from on gtk4
- _vte_debug_print(VTE_DEBUG_EVENTS, "Leave at %s\n", pos.to_string());
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Motion leave at grid %s\n", pos.to_string());
m_mouse_cursor_over_widget = FALSE;
m_mouse_last_position = pos;
+#elif VTE_GTK == 4
+ // FIXMEgtk4 !!!
+ m_mouse_cursor_over_widget = false;
+ // keep m_mouse_last_position since the event here has no position
+#endif
+
+ // FIXMEchpe: also set m_mouse_scroll_delta to 0 here?
hyperlink_hilite_update();
match_hilite_update();
@@ -7193,7 +7282,11 @@ Terminal::apply_font_metrics(int cell_width_unscaled,
/* Queue a resize if anything's changed. */
if (resize) {
if (widget_realized()) {
+#if VTE_GTK == 3
gtk_widget_queue_resize_no_redraw(m_widget);
+#elif VTE_GTK == 4
+ gtk_widget_queue_resize(m_widget); // FIXMEchpe?
+#endif
}
}
/* Emit a signal that the font changed. */
@@ -7306,6 +7399,7 @@ Terminal::set_font_desc(vte::Freeable<PangoFontDescription> font_desc)
bool
Terminal::update_font_desc()
{
+#if VTE_GTK == 3
auto desc = vte::Freeable<PangoFontDescription>{};
auto context = gtk_widget_get_style_context(m_widget);
@@ -7315,6 +7409,16 @@ Terminal::update_font_desc()
&vte::get_freeable(desc),
nullptr);
gtk_style_context_restore(context);
+#elif VTE_GTK == 4
+ // FIXMEgtk4
+ // This is how gtktextview does it, but the APIs are private... thanks, gtk4!
+ // desc = vte::take_freeable
+ // (gtk_css_style_get_pango_font(gtk_style_context_lookup_style(context));
+
+ auto context = gtk_widget_get_pango_context(m_widget);
+ auto context_desc = pango_context_get_font_description(context);
+ auto desc = vte::take_freeable(pango_font_description_copy(context_desc));
+#endif /* VTE_GTK */
pango_font_description_set_family_static(desc.get(), "monospace");
@@ -7633,7 +7737,11 @@ Terminal::set_size(long columns,
_vte_ring_next (m_screen->row_data) - 1));
adjust_adjustments_full();
+#if VTE_GTK == 3
gtk_widget_queue_resize_no_redraw(m_widget);
+#elif VTE_GTK == 4
+ gtk_widget_queue_resize(m_widget); // FIXMEchpe?
+#endif
/* Our visible text changed. */
emit_text_modified();
}
@@ -7798,11 +7906,9 @@ Terminal::Terminal(vte::platform::Widget* w,
}
void
-Terminal::widget_get_preferred_width(int *minimum_width,
- int *natural_width)
+Terminal::widget_measure_width(int *minimum_width,
+ int *natural_width)
{
- _vte_debug_print(VTE_DEBUG_LIFECYCLE, "vte_terminal_get_preferred_width()\n");
-
ensure_font();
refresh_size();
@@ -7825,11 +7931,9 @@ Terminal::widget_get_preferred_width(int *minimum_width,
}
void
-Terminal::widget_get_preferred_height(int *minimum_height,
- int *natural_height)
+Terminal::widget_measure_height(int *minimum_height,
+ int *natural_height)
{
- _vte_debug_print(VTE_DEBUG_LIFECYCLE, "vte_terminal_get_preferred_height()\n");
-
ensure_font();
refresh_size();
@@ -7852,7 +7956,17 @@ Terminal::widget_get_preferred_height(int *minimum_height,
}
void
-Terminal::widget_size_allocate(GtkAllocation *allocation)
+#if VTE_GTK == 3
+Terminal::widget_size_allocate(int allocation_x,
+ int allocation_y,
+ int allocation_width,
+ int allocation_height,
+ int allocation_baseline)
+#elif VTE_GTK == 4
+Terminal::widget_size_allocate(int allocation_width,
+ int allocation_height,
+ int allocation_baseline)
+#endif /* VTE_GTK */
{
glong width, height;
gboolean repaint, update_scrollback;
@@ -7860,9 +7974,9 @@ Terminal::widget_size_allocate(GtkAllocation *allocation)
_vte_debug_print(VTE_DEBUG_LIFECYCLE,
"vte_terminal_size_allocate()\n");
- width = (allocation->width - (m_padding.left + m_padding.right)) /
+ width = (allocation_width - (m_padding.left + m_padding.right)) /
m_cell_width;
- height = (allocation->height - (m_padding.top + m_padding.bottom)) /
+ height = (allocation_height - (m_padding.top + m_padding.bottom)) /
m_cell_height;
width = MAX(width, 1);
height = MAX(height, 1);
@@ -7870,19 +7984,21 @@ Terminal::widget_size_allocate(GtkAllocation *allocation)
_vte_debug_print(VTE_DEBUG_WIDGET_SIZE,
"[Terminal %p] Sizing window to %dx%d (%ldx%ld, padding %d,%d;%d,%d).\n",
m_terminal,
- allocation->width, allocation->height,
+ allocation_width, allocation_height,
width, height,
m_padding.left, m_padding.right, m_padding.top, m_padding.bottom);
auto current_allocation = get_allocated_rect();
- repaint = current_allocation.width != allocation->width
- || current_allocation.height != allocation->height;
- update_scrollback = current_allocation.height != allocation->height;
+ repaint = current_allocation.width != allocation_width ||
+ current_allocation.height != allocation_height;
+ update_scrollback = current_allocation.height != allocation_height;
- /* Set our allocation to match the structure. */
- gtk_widget_set_allocation(m_widget, allocation);
- set_allocated_rect(*allocation);
+#if VTE_GTK == 3
+ set_allocated_rect({allocation_x, allocation_y, allocation_width, allocation_height});
+#elif VTE_GTK == 4
+ set_allocated_rect({0, 0, allocation_width, allocation_height});
+#endif
if (width != m_column_count
|| height != m_row_count
@@ -7949,8 +8065,9 @@ Terminal::set_blink_settings(bool blink,
int blink_time,
int blink_timeout) noexcept
{
- m_cursor_blink_cycle = blink_time / 2;
- m_cursor_blink_timeout = blink_timeout;
+ m_cursor_blinks = blink;
+ m_cursor_blink_cycle = std::max(blink_time / 2, VTE_MIN_CURSOR_BLINK_CYCLE);
+ m_cursor_blink_timeout = std::max(blink_timeout, VTE_MIN_CURSOR_BLINK_TIMEOUT);
update_cursor_blinks();
@@ -9222,6 +9339,7 @@ Terminal::paint_im_preedit_string()
height,
get_color(VTE_DEFAULT_BG), m_background_alpha);
}
+
draw_cells_with_attributes(
items, len,
m_im_preedit_attrs.get(),
@@ -9248,11 +9366,41 @@ Terminal::paint_im_preedit_string()
}
}
+#if VTE_GTK == 3
+
+void
+Terminal::widget_draw(cairo_t* cr)
+{
+#ifdef VTE_DEBUG
+ _VTE_DEBUG_IF(VTE_DEBUG_LIFECYCLE | VTE_DEBUG_WORK | VTE_DEBUG_UPDATES) do {
+ auto clip_rect = cairo_rectangle_int_t{};
+ if (!gdk_cairo_get_clip_rectangle (cr, &clip_rect))
+ break;
+
+ _vte_debug_print(VTE_DEBUG_LIFECYCLE, "vte_terminal_draw()\n");
+ _vte_debug_print (VTE_DEBUG_WORK, "+");
+ _vte_debug_print (VTE_DEBUG_UPDATES, "Draw (%d,%d)x(%d,%d)\n",
+ clip_rect.x, clip_rect.y,
+ clip_rect.width, clip_rect.height);
+ } while (0);
+#endif /* VTE_DEBUG */
+
+ auto region = vte_cairo_get_clip_region (cr);
+ if (!region)
+ return;
+
+ /* Transform to view coordinates */
+ cairo_region_translate(region.get(), -m_padding.left, -m_padding.top);
+
+ draw(cr, region.get());
+}
+
+#endif /* VTE_GTK == 3 */
+
void
-Terminal::widget_draw(cairo_t *cr)
+Terminal::draw(cairo_t* cr,
+ cairo_region_t const* region)
{
- cairo_rectangle_int_t clip_rect;
- cairo_region_t *region;
int allocated_width, allocated_height;
int extra_area_for_cursor;
bool text_blink_enabled_now;
@@ -9261,19 +9409,6 @@ Terminal::widget_draw(cairo_t *cr)
#endif
gint64 now = 0;
- if (!gdk_cairo_get_clip_rectangle (cr, &clip_rect))
- return;
-
- _vte_debug_print(VTE_DEBUG_LIFECYCLE, "vte_terminal_draw()\n");
- _vte_debug_print (VTE_DEBUG_WORK, "+");
- _vte_debug_print (VTE_DEBUG_UPDATES, "Draw (%d,%d)x(%d,%d)\n",
- clip_rect.x, clip_rect.y,
- clip_rect.width, clip_rect.height);
-
- region = vte_cairo_get_clip_region (cr);
- if (region == NULL)
- return;
-
allocated_width = get_allocated_width();
allocated_height = get_allocated_height();
@@ -9294,9 +9429,6 @@ Terminal::widget_draw(cairo_t *cr)
cairo_translate(cr, m_padding.left, m_padding.top);
- /* Transform to view coordinates */
- cairo_region_translate(region, -m_padding.left, -m_padding.top);
-
#ifdef WITH_SIXEL
/* Draw images */
if (m_images_enabled) {
@@ -9365,8 +9497,6 @@ Terminal::widget_draw(cairo_t *cr)
/* Done with various structures. */
m_draw.set_cairo(nullptr);
- cairo_region_destroy (region);
-
/* If painting encountered any cell with blink attribute, we might need to set up a timer.
* Blinking is implemented using a one-shot (not repeating) timer that keeps getting reinstalled
* here as long as blinking cells are encountered during (re)painting. This way there's no need
@@ -9380,47 +9510,43 @@ Terminal::widget_draw(cairo_t *cr)
m_invalidated_all = FALSE;
}
+#if VTE_GTK == 3
+
/* Handle an expose event by painting the exposed area. */
-static cairo_region_t *
+static vte::Freeable<cairo_region_t>
vte_cairo_get_clip_region (cairo_t *cr)
{
- cairo_rectangle_list_t *list;
- cairo_region_t *region;
- int i;
-
- list = cairo_copy_clip_rectangle_list (cr);
+ auto list = vte::take_freeable(cairo_copy_clip_rectangle_list(cr));
if (list->status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) {
- cairo_rectangle_int_t clip_rect;
- cairo_rectangle_list_destroy (list);
+ auto clip_rect = cairo_rectangle_int_t{};
+ if (!gdk_cairo_get_clip_rectangle(cr, &clip_rect))
+ return nullptr;
- if (!gdk_cairo_get_clip_rectangle (cr, &clip_rect))
- return NULL;
- return cairo_region_create_rectangle (&clip_rect);
+ return vte::take_freeable(cairo_region_create_rectangle(&clip_rect));
}
+ auto region = vte::take_freeable(cairo_region_create());
+ for (auto i = list->num_rectangles - 1; i >= 0; --i) {
+ auto rect = &list->rectangles[i];
- region = cairo_region_create ();
- for (i = list->num_rectangles - 1; i >= 0; --i) {
- cairo_rectangle_t *rect = &list->rectangles[i];
cairo_rectangle_int_t clip_rect;
-
clip_rect.x = floor (rect->x);
clip_rect.y = floor (rect->y);
clip_rect.width = ceil (rect->x + rect->width) - clip_rect.x;
clip_rect.height = ceil (rect->y + rect->height) - clip_rect.y;
- if (cairo_region_union_rectangle (region, &clip_rect) != CAIRO_STATUS_SUCCESS) {
- cairo_region_destroy (region);
- region = NULL;
+ if (cairo_region_union_rectangle(region.get(), &clip_rect) != CAIRO_STATUS_SUCCESS) {
+ region.reset();
break;
}
}
- cairo_rectangle_list_destroy (list);
return region;
}
+#endif /* VTE_GTK == 3 */
+
bool
Terminal::widget_mouse_scroll(vte::platform::ScrollEvent const& event)
{
@@ -9652,15 +9778,11 @@ Terminal::set_rewrap_on_resize(bool rewrap)
void
Terminal::update_cursor_blinks()
{
- bool blink = false;
+ auto blink = false;
switch (decscusr_cursor_blink()) {
case CursorBlinkMode::eSYSTEM:
- gboolean v;
- g_object_get(gtk_widget_get_settings(m_widget),
- "gtk-cursor-blink",
- &v, nullptr);
- blink = v != FALSE;
+ blink = m_cursor_blinks_system;
break;
case CursorBlinkMode::eON:
blink = true;
@@ -10507,6 +10629,7 @@ Terminal::invalidate_dirty_rects_and_process_updates()
if (G_UNLIKELY (!m_update_rects->len))
return false;
+#if VTE_GTK == 3
auto region = cairo_region_create();
auto n_rects = m_update_rects->len;
for (guint i = 0; i < n_rects; i++) {
@@ -10524,6 +10647,9 @@ Terminal::invalidate_dirty_rects_and_process_updates()
/* and perform the merge with the window visible area */
gtk_widget_queue_draw_region(m_widget, region);
cairo_region_destroy (region);
+#elif VTE_GTK == 4
+ gtk_widget_queue_draw(m_widget);
+#endif
return true;
}
@@ -10928,7 +11054,7 @@ Terminal::set_input_enabled (bool enabled)
if (m_has_focus)
widget()->im_focus_in();
- gtk_style_context_remove_class (context, GTK_STYLE_CLASS_READ_ONLY);
+ gtk_style_context_remove_class (context, VTE_STYLE_CLASS_READ_ONLY);
} else {
im_reset();
if (m_has_focus)
@@ -10937,7 +11063,7 @@ Terminal::set_input_enabled (bool enabled)
disconnect_pty_write();
_vte_byte_array_clear(m_outgoing);
- gtk_style_context_add_class (context, GTK_STYLE_CLASS_READ_ONLY);
+ gtk_style_context_add_class (context, VTE_STYLE_CLASS_READ_ONLY);
}
return true;
diff --git a/src/vte/meson.build b/src/vte/meson.build
index 6d672a49..af614545 100644
--- a/src/vte/meson.build
+++ b/src/vte/meson.build
@@ -16,21 +16,6 @@
vte_inc = include_directories('.')
-libvte_common_enum_headers = files(
- # These files contain enums to be extracted by glib-mkenums
- 'vtedeprecated.h',
- 'vteenums.h',
-)
-
-libvte_gtk3_enum_sources = gnome.mkenums(
- 'vtetypebuiltins.h',
- sources: libvte_common_enum_headers,
- c_template: '../vtetypebuiltins.cc.template',
- h_template: '../vtetypebuiltins.h.template',
- install_header: true,
- install_dir: vte_includedir / vte_gtk3_api_path
-)
-
libvte_common_public_headers = files(
'vte.h',
'vtedeprecated.h',
@@ -40,31 +25,111 @@ libvte_common_public_headers = files(
'vtepty.h',
'vteregex.h',
'vteterminal.h',
+ 'vtetypebuiltins.h',
)
+libvte_common_enum_headers = files(
+ # These files contain enums to be extracted by glib-mkenums
+ 'vtedeprecated.h',
+ 'vteenums.h',
+)
+
+# Version header
+
vteversion_conf = configuration_data()
vteversion_conf.set('VTE_MAJOR_VERSION', vte_major_version)
vteversion_conf.set('VTE_MINOR_VERSION', vte_minor_version)
vteversion_conf.set('VTE_MICRO_VERSION', vte_micro_version)
-libvte_version_headers = configure_file(
+libvte_common_public_headers += configure_file(
input: 'vteversion.h.in',
output: '@BASENAME@',
configuration: vteversion_conf,
install: false,
)
+# Install headers, and create the type builtin files.
+# Note that we cannot use gnome.mkenums() to create the type builtins
+# files, since we need to install the generated header for both gtk3
+# and gtk4, and gnome.mkenums does not work with install_header()
+# [https://github.com/mesonbuild/meson/issues/1687]. However, neither does
+# custom_target() itself.
+# so we need to generate differently-named files for gtk3 and gtk4, and
+# install them sepearately, with an extra header that includes the right
+# one. And since gnome.mkenums() does not allow specifying the output names
+# when using templates, we need to use custom_target() for that.
+glib_mkenums = find_program('glib-mkenums')
+
if get_option('gtk3')
- libvte_gtk3_public_headers = libvte_common_public_headers + [libvte_version_headers]
+
+ libvte_gtk3_public_headers = libvte_common_public_headers
install_headers(
libvte_gtk3_public_headers,
subdir: vte_gtk3_api_path
)
- # BUG! Due to meson bug, this header cannot be installed with the rule above. Instead,
- # use the install_header attribute in the mkenums call, and add the header afterwards
- # to the list.
- libvte_gtk3_public_headers += libvte_gtk3_enum_sources[1]
+ libvte_gtk3_public_headers += custom_target(
+ 'vtetypebuiltins-gtk3.h',
+ command: [
+ glib_mkenums,
+ '--output', '@OUTPUT@',
+ '--template', meson.current_source_dir() / '..' / 'vtetypebuiltins.h.template',
+ '@INPUT@',
+ ],
+ input: libvte_common_enum_headers,
+ install: true,
+ install_dir: vte_includedir / vte_gtk3_api_path,
+ output: 'vtetypebuiltins-gtk3.h',
+ )
+
+ libvte_gtk3_enum_sources = [custom_target(
+ 'vtetypebuiltins-gtk3.cc',
+ command: [
+ glib_mkenums,
+ '--output', '@OUTPUT@',
+ '--template', meson.current_source_dir() / '..' / 'vtetypebuiltins.cc.template',
+ '@INPUT@',
+ ],
+ input: libvte_common_enum_headers,
+ install: false,
+ output: 'vtetypebuiltins-gtk3.cc',
+ ),]
+endif
+
+if get_option('gtk4')
+
+ libvte_gtk4_public_headers = libvte_common_public_headers
+
+ install_headers(
+ libvte_gtk4_public_headers,
+ subdir: vte_gtk4_api_path
+ )
+
+ libvte_gtk4_public_headers += custom_target(
+ 'vtetypebuiltins-gtk4.h',
+ command: [
+ glib_mkenums,
+ '--output', '@OUTPUT@',
+ '--template', meson.current_source_dir() / '..' / 'vtetypebuiltins.h.template',
+ '@INPUT@',
+ ],
+ input: libvte_common_enum_headers,
+ install: true,
+ install_dir: vte_includedir / vte_gtk4_api_path,
+ output: 'vtetypebuiltins-gtk4.h',
+ )
+ libvte_gtk4_enum_sources = [custom_target(
+ 'vtetypebuiltins-gtk4.cc',
+ command: [
+ glib_mkenums,
+ '--output', '@OUTPUT@',
+ '--template', meson.current_source_dir() / '..' / 'vtetypebuiltins.cc.template',
+ '@INPUT@',
+ ],
+ input: libvte_common_enum_headers,
+ install: false,
+ output: 'vtetypebuiltins-gtk4.cc',
+ ),]
endif
diff --git a/src/vte/vte.h b/src/vte/vte.h
index d4a6ff58..c9fa1fe6 100644
--- a/src/vte/vte.h
+++ b/src/vte/vte.h
@@ -18,9 +18,13 @@
#pragma once
#include <glib.h>
+#include <gtk/gtk.h>
#define __VTE_VTE_H_INSIDE__ 1
+/* This must always be included first */
+#include "vtemacros.h"
+
#include "vteenums.h"
#include "vteglobals.h"
#include "vtepty.h"
diff --git a/src/vte/vtedeprecated.h b/src/vte/vtedeprecated.h
index cbc1b57c..fd4913eb 100644
--- a/src/vte/vtedeprecated.h
+++ b/src/vte/vtedeprecated.h
@@ -33,11 +33,15 @@
G_BEGIN_DECLS
+#if _VTE_GTK == 3
+
_VTE_DEPRECATED
_VTE_PUBLIC
int vte_terminal_match_add_gregex(VteTerminal *terminal,
GRegex *gregex,
- GRegexMatchFlags gflags) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ GRegexMatchFlags gflags) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
+
+#endif /* _VTE_GTK == 3 */
_VTE_DEPRECATED
_VTE_PUBLIC
@@ -45,11 +49,13 @@ void vte_terminal_match_set_cursor(VteTerminal *terminal,
int tag,
GdkCursor *cursor) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
+#if _VTE_GTK == 3
_VTE_DEPRECATED
_VTE_PUBLIC
void vte_terminal_match_set_cursor_type(VteTerminal *terminal,
int tag,
GdkCursorType cursor_type) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
+#endif
_VTE_DEPRECATED
_VTE_PUBLIC
@@ -57,6 +63,8 @@ char *vte_terminal_match_check(VteTerminal *terminal,
glong column, glong row,
int *tag) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) G_GNUC_MALLOC;
+#if _VTE_GTK == 3
+
_VTE_DEPRECATED
_VTE_PUBLIC
gboolean vte_terminal_event_check_gregex_simple(VteTerminal *terminal,
@@ -64,7 +72,7 @@ gboolean vte_terminal_event_check_gregex_simple(VteTerminal *terminal,
GRegex **regexes,
gsize n_regexes,
GRegexMatchFlags match_flags,
- char **matches) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ char **matches) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
_VTE_DEPRECATED
_VTE_PUBLIC
@@ -76,6 +84,8 @@ _VTE_DEPRECATED
_VTE_PUBLIC
GRegex *vte_terminal_search_get_gregex (VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
+#endif /* _VTE_GTK == 3 */
+
_VTE_DEPRECATED
_VTE_PUBLIC
gboolean vte_terminal_spawn_sync(VteTerminal *terminal,
@@ -88,7 +98,7 @@ gboolean vte_terminal_spawn_sync(VteTerminal *terminal,
gpointer child_setup_data,
GPid *child_pid /* out */,
GCancellable *cancellable,
- GError **error) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(4);
+ GError **error) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 4);
_VTE_DEPRECATED
_VTE_PUBLIC
@@ -98,17 +108,21 @@ _VTE_DEPRECATED
_VTE_PUBLIC
void vte_terminal_copy_clipboard(VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
+#if _VTE_GTK == 3
+
_VTE_DEPRECATED
_VTE_PUBLIC
void vte_terminal_get_geometry_hints(VteTerminal *terminal,
GdkGeometry *hints,
int min_rows,
- int min_columns) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ int min_columns) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
_VTE_DEPRECATED
_VTE_PUBLIC
void vte_terminal_set_geometry_hints_for_window(VteTerminal *terminal,
- GtkWindow *window) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ GtkWindow *window) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
+
+#endif /* _VTE_GTK == 3 */
_VTE_DEPRECATED
_VTE_PUBLIC
diff --git a/src/vte/vtemacros.h b/src/vte/vtemacros.h
index 30ba7039..c1300998 100644
--- a/src/vte/vtemacros.h
+++ b/src/vte/vtemacros.h
@@ -21,6 +21,18 @@
#error "Only <vte/vte.h> can be included directly."
#endif
+#include <gtk/gtk.h>
+
+#if GTK_CHECK_VERSION(4,0,0)
+#define _VTE_GTK 4
+#elif GTK_CHECK_VERSION(3,90,0)
+#error gtk+ version not supported
+#elif GTK_CHECK_VERSION(3,0,0)
+#define _VTE_GTK 3
+#else
+#error gtk+ version unknown
+#endif
+
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6)
#define _VTE_GNUC_PACKED __attribute__((__packed__))
#else
@@ -28,12 +40,12 @@
#endif /* !__GNUC__ */
#ifdef VTE_COMPILATION
-#define _VTE_GNUC_NONNULL(position)
+#define _VTE_GNUC_NONNULL(...)
#else
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
-#define _VTE_GNUC_NONNULL(position) __attribute__((__nonnull__(position)))
+#if defined(__GNUC__)
+#define _VTE_GNUC_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
#else
-#define _VTE_GNUC_NONNULL(position)
+#define _VTE_GNUC_NONNULL(...)
#endif
#endif
diff --git a/src/vte/vtepty.h b/src/vte/vtepty.h
index 524e91d6..f6348cd7 100644
--- a/src/vte/vtepty.h
+++ b/src/vte/vtepty.h
@@ -91,8 +91,6 @@ gboolean vte_pty_set_utf8 (VtePty *pty,
gboolean utf8,
GError **error) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
-G_DEFINE_AUTOPTR_CLEANUP_FUNC(VtePty, g_object_unref)
-
_VTE_PUBLIC
void vte_pty_spawn_async(VtePty *pty,
const char *working_directory,
@@ -105,7 +103,7 @@ void vte_pty_spawn_async(VtePty *pty,
int timeout,
GCancellable *cancellable,
GAsyncReadyCallback callback,
- gpointer user_data) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(3);
+ gpointer user_data) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 3);
_VTE_PUBLIC
void vte_pty_spawn_with_fds_async(VtePty *pty,
@@ -123,12 +121,14 @@ void vte_pty_spawn_with_fds_async(VtePty *pty,
int timeout,
GCancellable *cancellable,
GAsyncReadyCallback callback,
- gpointer user_data) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(3);
+ gpointer user_data) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 3);
_VTE_PUBLIC
gboolean vte_pty_spawn_finish(VtePty *pty,
GAsyncResult *result,
GPid *child_pid /* out */,
- GError **error) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ GError **error) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(VtePty, g_object_unref)
G_END_DECLS
diff --git a/src/vte/vteregex.h b/src/vte/vteregex.h
index 626ae87c..6eb95343 100644
--- a/src/vte/vteregex.h
+++ b/src/vte/vteregex.h
@@ -71,7 +71,7 @@ char *vte_regex_substitute(VteRegex *regex,
const char *subject,
const char *replacement,
guint32 flags,
- GError **error) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2) _VTE_GNUC_NONNULL(3) G_GNUC_MALLOC;
+ GError **error) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2, 3) G_GNUC_MALLOC;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(VteRegex, vte_regex_unref)
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
index e705ece6..736b3e77 100644
--- a/src/vte/vteterminal.h
+++ b/src/vte/vteterminal.h
@@ -50,8 +50,10 @@ typedef struct _VteCharAttributes VteCharAttributes;
*/
struct _VteTerminal {
GtkWidget widget;
+#if _VTE_GTK == 3
/*< private >*/
gpointer *_unused_padding[1]; /* FIXMEchpe: remove this field on the next ABI break */
+#endif
};
/**
@@ -105,6 +107,7 @@ struct _VteTerminalClass {
/* Padding for future expansion. */
gpointer padding[16];
+// FIXMEgtk4 use class private data instead
VteTerminalClassPrivate *priv;
};
@@ -156,7 +159,7 @@ void vte_terminal_spawn_async(VteTerminal *terminal,
int timeout,
GCancellable *cancellable,
VteTerminalSpawnAsyncCallback callback,
- gpointer user_data) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(4);
+ gpointer user_data) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 4);
_VTE_PUBLIC
void vte_terminal_spawn_with_fds_async(VteTerminal* terminal,
@@ -175,7 +178,7 @@ void vte_terminal_spawn_with_fds_async(VteTerminal* terminal,
int timeout,
GCancellable* cancellable,
VteTerminalSpawnAsyncCallback callback,
- gpointer user_data) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(4);
+ gpointer user_data) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 4);
/* Send data to the terminal to display, or to the terminal's forked command
* to handle in some way. If it's 'cat', they should be the same. */
@@ -268,10 +271,10 @@ void vte_terminal_set_color_bold(VteTerminal *terminal,
const GdkRGBA *bold) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
_VTE_PUBLIC
void vte_terminal_set_color_foreground(VteTerminal *terminal,
- const GdkRGBA *foreground) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ const GdkRGBA *foreground) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
_VTE_PUBLIC
void vte_terminal_set_color_background(VteTerminal *terminal,
- const GdkRGBA *background) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ const GdkRGBA *background) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
_VTE_PUBLIC
void vte_terminal_set_color_cursor(VteTerminal *terminal,
const GdkRGBA *cursor_background) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
@@ -395,21 +398,25 @@ void vte_terminal_get_cursor_position(VteTerminal *terminal,
glong *column,
glong *row) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
+#if _VTE_GTK == 3
+
_VTE_PUBLIC
char *vte_terminal_hyperlink_check_event(VteTerminal *terminal,
- GdkEvent *event) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2) G_GNUC_MALLOC;
+ GdkEvent *event) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2) G_GNUC_MALLOC;
+
+#endif /* _VTE_GTK */
/* Add a matching expression, returning the tag the widget assigns to that
* expression. */
_VTE_PUBLIC
int vte_terminal_match_add_regex(VteTerminal *terminal,
VteRegex *regex,
- guint32 flags) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ guint32 flags) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
/* Set the cursor to be used when the pointer is over a given match. */
_VTE_PUBLIC
void vte_terminal_match_set_cursor_name(VteTerminal *terminal,
int tag,
- const char *cursor_name) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(3);
+ const char *cursor_name) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 3);
_VTE_PUBLIC
void vte_terminal_match_remove(VteTerminal *terminal,
int tag) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
@@ -419,24 +426,29 @@ void vte_terminal_match_remove_all(VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VTE
/* Check if a given cell on the screen contains part of a matched string. If
* it does, return the string, and store the match tag in the optional tag
* argument. */
+#if _VTE_GTK == 3
+
_VTE_PUBLIC
char *vte_terminal_match_check_event(VteTerminal *terminal,
GdkEvent *event,
- int *tag) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2) G_GNUC_MALLOC;
+ int *tag) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2) G_GNUC_MALLOC;
+
_VTE_PUBLIC
char **vte_terminal_event_check_regex_array(VteTerminal *terminal,
GdkEvent *event,
VteRegex **regexes,
gsize n_regexes,
guint32 match_flags,
- gsize *n_matches) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2) G_GNUC_MALLOC;
+ gsize *n_matches) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2) G_GNUC_MALLOC;
_VTE_PUBLIC
gboolean vte_terminal_event_check_regex_simple(VteTerminal *terminal,
GdkEvent *event,
VteRegex **regexes,
gsize n_regexes,
guint32 match_flags,
- char **matches) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ char **matches) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
+
+#endif /* _VTE_GTK */
_VTE_PUBLIC
void vte_terminal_search_set_regex (VteTerminal *terminal,
@@ -492,12 +504,17 @@ _VTE_PUBLIC
gboolean vte_terminal_get_input_enabled (VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
/* rarely useful functions */
+
+#if _VTE_GTK == 3
+
_VTE_PUBLIC
void vte_terminal_set_clear_background(VteTerminal* terminal,
gboolean setting) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
_VTE_PUBLIC
void vte_terminal_get_color_background_for_draw(VteTerminal* terminal,
- GdkRGBA* color) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ GdkRGBA* color) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
+
+#endif /* _VTE_GTK == 3 */
/* Writing contents out */
_VTE_PUBLIC
@@ -505,7 +522,7 @@ gboolean vte_terminal_write_contents_sync (VteTerminal *terminal,
GOutputStream *stream,
VteWriteFlags flags,
GCancellable *cancellable,
- GError **error) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) _VTE_GNUC_NONNULL(2);
+ GError **error) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
/* Images */
diff --git a/src/vte/vtetypebuiltins.h b/src/vte/vtetypebuiltins.h
new file mode 100644
index 00000000..8678cdae
--- /dev/null
+++ b/src/vte/vtetypebuiltins.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2021 Christian Persch
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#if !defined (__VTE_VTE_H_INSIDE__) && !defined (VTE_COMPILATION)
+#error "Only <vte/vte.h> can be included directly."
+#endif
+
+#if _VTE_GTK == 3
+#include "vtetypebuiltins-gtk3.h"
+#elif _VTE_GTK == 4
+#include "vtetypebuiltins-gtk4.h"
+#endif
diff --git a/src/vteaccess.h b/src/vteaccess.h
index 4362ede4..31f21601 100644
--- a/src/vteaccess.h
+++ b/src/vteaccess.h
@@ -15,9 +15,7 @@
* along with this library. If not, see <https://www.gnu.org/licenses/>.
*/
-#ifndef vte_vteaccess_h_included
-#define vte_vteaccess_h_included
-
+#pragma once
#include <glib.h>
#include <gtk/gtk.h>
@@ -51,5 +49,3 @@ struct _VteTerminalAccessibleClass {
GType _vte_terminal_accessible_get_type(void);
G_END_DECLS
-
-#endif
diff --git a/src/vtedefines.hh b/src/vtedefines.hh
index b1720735..16f6ae78 100644
--- a/src/vtedefines.hh
+++ b/src/vtedefines.hh
@@ -148,3 +148,6 @@
#define VTE_SIXEL_MAX_WIDTH (2048)
#define VTE_SIXEL_MAX_HEIGHT (2052)
#define VTE_SIXEL_NUM_COLOR_REGISTERS (1024)
+
+#define VTE_MIN_CURSOR_BLINK_CYCLE (50 /* ms */)
+#define VTE_MIN_CURSOR_BLINK_TIMEOUT (50 /* ms */)
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index a1be90df..cee355a1 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -63,8 +63,12 @@
#include "vteregexinternal.hh"
#ifdef WITH_A11Y
+#if VTE_GTK == 3
#include "vteaccess.h"
-#endif
+#else
+#undef WITH_A11Y
+#endif /* VTE_GTK == 3 */
+#endif /* WITH_A11Y */
#ifdef WITH_ICU
#include "icu-glue.hh"
@@ -79,6 +83,19 @@ struct _VteTerminalClassPrivate {
GtkStyleProvider *style_provider;
};
+#if VTE_GTK == 4
+
+static void
+style_provider_parsing_error_cb(GtkCssProvider* provider,
+ void* section,
+ GError* error)
+{
+ g_assert_no_error(error);
+}
+
+#endif
+
+
class VteTerminalPrivate {
public:
VteTerminalPrivate(VteTerminal* terminal)
@@ -217,7 +234,6 @@ vte_terminal_set_hscroll_policy(VteTerminal *terminal,
try
{
WIDGET(terminal)->set_hscroll_policy(policy);
- gtk_widget_queue_resize_no_redraw (GTK_WIDGET (terminal));
}
catch (...)
{
@@ -230,7 +246,6 @@ vte_terminal_set_vscroll_policy(VteTerminal *terminal,
try
{
WIDGET(terminal)->set_vscroll_policy(policy);
- gtk_widget_queue_resize_no_redraw (GTK_WIDGET (terminal));
}
catch (...)
{
@@ -260,6 +275,8 @@ catch (...)
vte::log_exception();
}
+#if VTE_GTK == 3
+
static void
vte_terminal_style_updated (GtkWidget *widget) noexcept
try
@@ -298,7 +315,7 @@ try
}
}
- return WIDGET(terminal)->key_press(event);
+ return WIDGET(terminal)->event_key_press(event);
}
catch (...)
{
@@ -312,7 +329,7 @@ vte_terminal_key_release(GtkWidget *widget,
try
{
VteTerminal *terminal = VTE_TERMINAL(widget);
- return WIDGET(terminal)->key_release(event);
+ return WIDGET(terminal)->event_key_release(event);
}
catch (...)
{
@@ -326,7 +343,7 @@ vte_terminal_motion_notify(GtkWidget *widget,
try
{
VteTerminal *terminal = VTE_TERMINAL(widget);
- return WIDGET(terminal)->motion_notify(event);
+ return WIDGET(terminal)->event_motion_notify(event);
}
catch (...)
{
@@ -340,7 +357,7 @@ vte_terminal_button_press(GtkWidget *widget,
try
{
VteTerminal *terminal = VTE_TERMINAL(widget);
- return WIDGET(terminal)->button_press(event);
+ return WIDGET(terminal)->event_button_press(event);
}
catch (...)
{
@@ -354,7 +371,7 @@ vte_terminal_button_release(GtkWidget *widget,
try
{
VteTerminal *terminal = VTE_TERMINAL(widget);
- return WIDGET(terminal)->button_release(event);
+ return WIDGET(terminal)->event_button_release(event);
}
catch (...)
{
@@ -368,7 +385,7 @@ vte_terminal_scroll(GtkWidget *widget,
try
{
auto terminal = VTE_TERMINAL(widget);
- return WIDGET(terminal)->scroll(event);
+ return WIDGET(terminal)->event_scroll(event);
}
catch (...)
{
@@ -382,7 +399,7 @@ vte_terminal_focus_in(GtkWidget *widget,
try
{
VteTerminal *terminal = VTE_TERMINAL(widget);
- WIDGET(terminal)->focus_in(event);
+ WIDGET(terminal)->event_focus_in(event);
return FALSE;
}
catch (...)
@@ -397,7 +414,7 @@ vte_terminal_focus_out(GtkWidget *widget,
try
{
VteTerminal *terminal = VTE_TERMINAL(widget);
- WIDGET(terminal)->focus_out(event);
+ WIDGET(terminal)->event_focus_out(event);
return FALSE;
}
catch (...)
@@ -418,7 +435,7 @@ try
ret = GTK_WIDGET_CLASS (vte_terminal_parent_class)->enter_notify_event (widget, event);
}
- WIDGET(terminal)->enter(event);
+ WIDGET(terminal)->event_enter(event);
return ret;
}
@@ -440,7 +457,7 @@ try
ret = GTK_WIDGET_CLASS (vte_terminal_parent_class)->leave_notify_event (widget, event);
}
- WIDGET(terminal)->leave(event);
+ WIDGET(terminal)->event_leave(event);
return ret;
}
@@ -478,33 +495,7 @@ catch (...)
vte::log_exception();
}
-static void
-vte_terminal_size_allocate(GtkWidget *widget,
- GtkAllocation *allocation) noexcept
-try
-{
- VteTerminal *terminal = VTE_TERMINAL(widget);
- WIDGET(terminal)->size_allocate(allocation);
-}
-catch (...)
-{
- vte::log_exception();
-}
-
-static gboolean
-vte_terminal_draw(GtkWidget *widget,
- cairo_t *cr) noexcept
-try
-{
- VteTerminal *terminal = VTE_TERMINAL (widget);
- WIDGET(terminal)->draw(cr);
- return FALSE;
-}
-catch (...)
-{
- vte::log_exception();
- return false;
-}
+#endif /* VTE_GTK == 3 */
static void
vte_terminal_realize(GtkWidget *widget) noexcept
@@ -569,16 +560,105 @@ vte_terminal_unmap(GtkWidget *widget) noexcept
}
static void
-vte_terminal_screen_changed (GtkWidget *widget,
- GdkScreen *previous_screen) noexcept
+vte_terminal_state_flags_changed(GtkWidget* widget,
+ GtkStateFlags old_flags) noexcept
try
{
- VteTerminal *terminal = VTE_TERMINAL (widget);
+ GTK_WIDGET_CLASS(vte_terminal_parent_class)->state_flags_changed(widget, old_flags);
- if (GTK_WIDGET_CLASS (vte_terminal_parent_class)->screen_changed) {
- GTK_WIDGET_CLASS (vte_terminal_parent_class)->screen_changed (widget, previous_screen);
- }
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->state_flags_changed(old_flags);
+}
+catch (...)
+{
+ vte::log_exception();
+}
+
+static void
+vte_terminal_direction_changed(GtkWidget* widget,
+ GtkTextDirection old_direction) noexcept
+try
+{
+ auto const parent_class = GTK_WIDGET_CLASS(vte_terminal_parent_class);
+ if (parent_class->direction_changed)
+ parent_class->direction_changed(widget, old_direction);
+
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->direction_changed(old_direction);
+}
+catch (...)
+{
+ vte::log_exception();
+}
+
+static GtkSizeRequestMode
+vte_terminal_get_request_mode(GtkWidget* widget) noexcept
+{
+ return GTK_SIZE_REQUEST_CONSTANT_SIZE;
+}
+
+static gboolean
+vte_terminal_query_tooltip(GtkWidget* widget,
+ int x,
+ int y,
+ gboolean keyboard,
+ GtkTooltip* tooltip) noexcept
+try
+{
+ auto const parent_class = GTK_WIDGET_CLASS(vte_terminal_parent_class);
+ if (parent_class->query_tooltip(widget, x, y, keyboard, tooltip))
+ return true;
+
+ auto terminal = VTE_TERMINAL(widget);
+ return WIDGET(terminal)->query_tooltip(x, y, keyboard, tooltip);
+}
+catch (...)
+{
+ vte::log_exception();
+ return false;
+}
+
+
+#if VTE_GTK == 3
+
+static void
+vte_terminal_size_allocate(GtkWidget* widget,
+ GtkAllocation* allocation) noexcept
+try
+{
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->size_allocate(allocation);
+}
+catch (...)
+{
+ vte::log_exception();
+}
+
+static gboolean
+vte_terminal_draw(GtkWidget* widget,
+ cairo_t* cr) noexcept
+try
+{
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->draw(cr);
+ return FALSE;
+}
+catch (...)
+{
+ vte::log_exception();
+ return false;
+}
+static void
+vte_terminal_screen_changed(GtkWidget* widget,
+ GdkScreen* previous_screen) noexcept
+try
+{
+ auto const parent_class = GTK_WIDGET_CLASS(vte_terminal_parent_class);
+ if (parent_class->screen_changed)
+ parent_class->screen_changed(widget, previous_screen);
+
+ auto terminal = VTE_TERMINAL(widget);
WIDGET(terminal)->screen_changed(previous_screen);
}
catch (...)
@@ -586,6 +666,156 @@ catch (...)
vte::log_exception();
}
+#endif /* VTE_GTK == 3 */
+
+#if VTE_GTK == 4
+
+static void
+vte_terminal_size_allocate(GtkWidget *widget,
+ int width,
+ int height,
+ int baseline) noexcept
+try
+{
+ GTK_WIDGET_CLASS(vte_terminal_parent_class)->size_allocate(widget, width, height, baseline);
+
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->size_allocate(width, height, baseline);
+}
+catch (...)
+{
+ vte::log_exception();
+}
+
+static void
+vte_terminal_root(GtkWidget *widget) noexcept
+try
+{
+ GTK_WIDGET_CLASS(vte_terminal_parent_class)->root(widget);
+
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->root();
+}
+catch (...)
+{
+ vte::log_exception();
+}
+
+static void
+vte_terminal_unroot(GtkWidget *widget) noexcept
+{
+ _vte_debug_print(VTE_DEBUG_LIFECYCLE, "vte_terminal_unroot()\n");
+
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->unroot();
+
+ GTK_WIDGET_CLASS(vte_terminal_parent_class)->unroot(widget);
+}
+
+static void
+vte_terminal_measure(GtkWidget* widget,
+ GtkOrientation orientation,
+ int for_size,
+ int* minimum,
+ int* natural,
+ int* minimum_baseline,
+ int* natural_baseline) noexcept
+try
+{
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->measure(orientation, for_size,
+ minimum, natural,
+ minimum_baseline, natural_baseline);
+}
+catch (...)
+{
+ vte::log_exception();
+}
+
+static void
+vte_terminal_compute_expand(GtkWidget* widget,
+ gboolean* hexpand,
+ gboolean* vexpand) noexcept
+try
+{
+ auto terminal = VTE_TERMINAL(widget);
+ auto [h, v] = WIDGET(terminal)->compute_expand();
+ *hexpand = h;
+ *vexpand = v;
+}
+catch (...)
+{
+ vte::log_exception();
+ *hexpand = *vexpand = false;
+}
+
+static void
+vte_terminal_css_changed(GtkWidget* widget,
+ GtkCssStyleChange* change) noexcept
+try
+{
+ GTK_WIDGET_CLASS(vte_terminal_parent_class)->css_changed(widget, change);
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->css_changed(change);
+}
+catch (...)
+{
+ vte::log_exception();
+}
+
+static void
+vte_terminal_system_setting_changed(GtkWidget* widget,
+ GtkSystemSetting setting) noexcept
+try
+{
+ GTK_WIDGET_CLASS(vte_terminal_parent_class)->system_setting_changed(widget, setting);
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->system_setting_changed(setting);
+}
+catch (...)
+{
+ vte::log_exception();
+}
+
+static void
+vte_terminal_snapshot(GtkWidget* widget,
+ GtkSnapshot* snapshot_object) noexcept
+try
+{
+ GTK_WIDGET_CLASS(vte_terminal_parent_class)->snapshot(widget, snapshot_object);
+ auto terminal = VTE_TERMINAL(widget);
+ WIDGET(terminal)->snapshot(snapshot_object);
+}
+catch (...)
+{
+ vte::log_exception();
+}
+
+static gboolean
+vte_terminal_contains(GtkWidget* widget,
+ double x,
+ double y) noexcept
+try
+{
+ auto terminal = VTE_TERMINAL(widget);
+ if (WIDGET(terminal)->contains(x, y))
+ return true;
+
+ auto const parent_class = GTK_WIDGET_CLASS(vte_terminal_parent_class);
+ if (parent_class->contains &&
+ parent_class->contains(widget, x, y))
+ return true;
+
+ return false;
+}
+catch (...)
+{
+ vte::log_exception();
+ return false;
+}
+
+#endif /* VTE_GTK == 4 */
+
static void
vte_terminal_constructed (GObject *object) noexcept
try
@@ -615,7 +845,9 @@ try
VTE_TERMINAL_GET_CLASS (terminal)->priv->style_provider,
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+#if VTE_GTK == 3
gtk_widget_set_has_window(&terminal->widget, FALSE);
+#endif
place = vte_terminal_get_instance_private(terminal);
new (place) VteTerminalPrivate{terminal};
@@ -916,10 +1148,6 @@ catch (...)
static void
vte_terminal_class_init(VteTerminalClass *klass)
{
- GObjectClass *gobject_class;
- GtkWidgetClass *widget_class;
- GtkBindingSet *binding_set;
-
#ifdef VTE_DEBUG
{
_vte_debug_init();
@@ -943,13 +1171,15 @@ vte_terminal_class_init(VteTerminalClass *klass)
}
#endif
+#if VTE_GTK == 3
_VTE_DEBUG_IF (VTE_DEBUG_UPDATES) gdk_window_set_debug_updates(TRUE);
+#endif
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
- gobject_class = G_OBJECT_CLASS(klass);
- widget_class = GTK_WIDGET_CLASS(klass);
+ auto gobject_class = G_OBJECT_CLASS(klass);
+ auto widget_class = GTK_WIDGET_CLASS(klass);
/* Override some of the default handlers. */
gobject_class->constructed = vte_terminal_constructed;
@@ -957,12 +1187,21 @@ vte_terminal_class_init(VteTerminalClass *klass)
gobject_class->finalize = vte_terminal_finalize;
gobject_class->get_property = vte_terminal_get_property;
gobject_class->set_property = vte_terminal_set_property;
+
widget_class->realize = vte_terminal_realize;
widget_class->unrealize = vte_terminal_unrealize;
widget_class->map = vte_terminal_map;
widget_class->unmap = vte_terminal_unmap;
- widget_class->scroll_event = vte_terminal_scroll;
+
+ widget_class->size_allocate = vte_terminal_size_allocate;
+ widget_class->state_flags_changed = vte_terminal_state_flags_changed;
+ widget_class->direction_changed = vte_terminal_direction_changed;
+ widget_class->get_request_mode = vte_terminal_get_request_mode;
+ widget_class->query_tooltip = vte_terminal_query_tooltip;
+
+#if VTE_GTK == 3
widget_class->draw = vte_terminal_draw;
+ widget_class->scroll_event = vte_terminal_scroll;
widget_class->key_press_event = vte_terminal_key_press;
widget_class->key_release_event = vte_terminal_key_release;
widget_class->button_press_event = vte_terminal_button_press;
@@ -975,8 +1214,19 @@ vte_terminal_class_init(VteTerminalClass *klass)
widget_class->style_updated = vte_terminal_style_updated;
widget_class->get_preferred_width = vte_terminal_get_preferred_width;
widget_class->get_preferred_height = vte_terminal_get_preferred_height;
- widget_class->size_allocate = vte_terminal_size_allocate;
widget_class->screen_changed = vte_terminal_screen_changed;
+#endif
+
+#if VTE_GTK == 4
+ widget_class->root = vte_terminal_root;
+ widget_class->unroot = vte_terminal_unroot;
+ widget_class->measure = vte_terminal_measure;
+ widget_class->compute_expand = vte_terminal_compute_expand;
+ widget_class->css_changed = vte_terminal_css_changed;
+ widget_class->system_setting_changed = vte_terminal_system_setting_changed;
+ widget_class->snapshot = vte_terminal_snapshot;
+ widget_class->contains = vte_terminal_contains;
+#endif
gtk_widget_class_set_css_name(widget_class, VTE_TERMINAL_CSS_NAME);
@@ -2077,23 +2327,33 @@ vte_terminal_class_init(VteTerminalClass *klass)
g_object_class_install_properties(gobject_class, LAST_PROP, pspecs);
+#if VTE_GTK == 3
/* Disable GtkWidget's keybindings except for Shift-F10 and MenuKey
* which pop up the context menu.
*/
- binding_set = gtk_binding_set_by_class(vte_terminal_parent_class);
+ auto const binding_set = gtk_binding_set_by_class(vte_terminal_parent_class);
gtk_binding_entry_skip(binding_set, GDK_KEY_F1, GDK_CONTROL_MASK);
gtk_binding_entry_skip(binding_set, GDK_KEY_F1, GDK_SHIFT_MASK);
gtk_binding_entry_skip(binding_set, GDK_KEY_KP_F1, GDK_CONTROL_MASK);
gtk_binding_entry_skip(binding_set, GDK_KEY_KP_F1, GDK_SHIFT_MASK);
+#endif /* VTE_GTK == 3 */
process_timer = g_timer_new();
klass->priv = G_TYPE_CLASS_GET_PRIVATE (klass, VTE_TYPE_TERMINAL, VteTerminalClassPrivate);
klass->priv->style_provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+#if VTE_GTK == 3
+ auto err = vte::glib::Error{};
+#elif VTE_GTK == 4
+ g_signal_connect(klass->priv->style_provider, "parsing-error",
+ G_CALLBACK(style_provider_parsing_error_cb), nullptr);
+#endif
gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (klass->priv->style_provider),
"VteTerminal, " VTE_TERMINAL_CSS_NAME " {\n"
+#if VTE_GTK == 3
"padding: 1px 1px 1px 1px;\n"
+#endif
#if GTK_CHECK_VERSION (3, 24, 22)
"background-color: @text_view_bg;\n"
#else
@@ -2101,12 +2361,21 @@ vte_terminal_class_init(VteTerminalClass *klass)
#endif
"color: @theme_text_color;\n"
"}\n",
- -1, NULL);
+ -1
+#if VTE_GTK == 3
+ , NULL
+#endif
+ );
+#if VTE_GTK == 3
+ err.assert_no_error();
+#endif
+#if VTE_GTK == 3
#ifdef WITH_A11Y
/* a11y */
gtk_widget_class_set_accessible_type(widget_class, VTE_TYPE_TERMINAL_ACCESSIBLE);
#endif
+#endif
}
static gboolean
@@ -2504,6 +2773,8 @@ catch (...)
vte::log_exception();
}
+#if VTE_GTK == 3
+
/**
* vte_terminal_match_add_gregex:
* @terminal: a #VteTerminal
@@ -2524,6 +2795,8 @@ vte_terminal_match_add_gregex(VteTerminal *terminal,
return -1;
}
+#endif /* VTE_GTK == 3 */
+
/**
* vte_terminal_match_add_regex:
* @terminal: a #VteTerminal
@@ -2600,6 +2873,8 @@ catch (...)
return nullptr;
}
+#if VTE_GTK == 3
+
/**
* vte_terminal_match_check_event:
* @terminal: a #VteTerminal
@@ -2768,6 +3043,10 @@ catch (...)
return false;
}
+#endif /* VTE_GTK */
+
+#if VTE_GTK == 3
+
/**
* vte_terminal_event_check_gregex_simple:
* @terminal: a #VteTerminal
@@ -2795,6 +3074,8 @@ vte_terminal_event_check_gregex_simple(VteTerminal *terminal,
return FALSE;
}
+#endif /* VTE_GTK == 3 */
+
/**
* vte_terminal_match_set_cursor:
* @terminal: a #VteTerminal
@@ -2823,6 +3104,8 @@ catch (...)
vte::log_exception();
}
+#if VTE_GTK == 3
+
/**
* vte_terminal_match_set_cursor_type:
* @terminal: a #VteTerminal
@@ -2849,6 +3132,7 @@ catch (...)
{
vte::log_exception();
}
+#endif /* VTE_GTK == 3 */
/**
* vte_terminal_match_set_cursor_name:
@@ -3011,6 +3295,8 @@ catch (...)
return nullptr;
}
+#if VTE_GTK == 3
+
/**
* vte_terminal_search_set_gregex:
* @terminal: a #VteTerminal
@@ -3044,6 +3330,8 @@ vte_terminal_search_get_gregex (VteTerminal *terminal) noexcept
return nullptr;
}
+#endif /* VTE_GTK == 3 */
+
/**
* vte_terminal_search_set_wrap_around:
* @terminal: a #VteTerminal
@@ -5046,6 +5334,8 @@ catch (...)
vte::log_exception();
}
+#if VTE_GTK == 3
+
/* Just some arbitrary minimum values */
#define MIN_COLUMNS (16)
#define MIN_ROWS (2)
@@ -5136,6 +5426,8 @@ vte_terminal_set_geometry_hints_for_window(VteTerminal *terminal,
GDK_HINT_BASE_SIZE));
}
+#endif /* VTE_GTK == 3 */
+
/**
* vte_terminal_get_has_selection:
* @terminal: a #VteTerminal
@@ -5698,6 +5990,8 @@ catch (...)
return vte::glib::set_error_from_exception(error);
}
+#if VTE_GTK == 3
+
/**
* vte_terminal_set_clear_background:
* @terminal: a #VteTerminal
@@ -5764,6 +6058,8 @@ catch (...)
*color = {0., 0., 0., 1.};
}
+#endif /* VTE_GTK == 3 */
+
/**
* vte_terminal_set_enable_sixel:
* @terminal: a #VteTerminal
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 41766c0e..a6ad315b 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -89,9 +89,14 @@ namespace platform {
* Holds a platform cursor. This is either a named cursor (string),
* a reference to a GdkCursor*, or a cursor type.
*/
+#if VTE_GTK == 3
using Cursor = std::variant<std::string,
vte::glib::RefPtr<GdkCursor>,
GdkCursorType>;
+#elif VTE_GTK == 4
+using Cursor = std::variant<std::string,
+ vte::glib::RefPtr<GdkCursor>>;
+#endif
} // namespace platform
} // namespace vte
@@ -427,9 +432,10 @@ public:
"cursor-blink-timer"};
CursorBlinkMode m_cursor_blink_mode{CursorBlinkMode::eSYSTEM};
bool m_cursor_blink_state{false};
- bool m_cursor_blinks{false}; /* whether the cursor is actually blinking */
- gint m_cursor_blink_cycle; /* gtk-cursor-blink-time / 2 */
- int m_cursor_blink_timeout{500}; /* gtk-cursor-blink-timeout */
+ bool m_cursor_blinks{false}; /* whether the cursor is actually blinking */
+ bool m_cursor_blinks_system{true}; /* gtk-cursor-blink */
+ gint m_cursor_blink_cycle{1000}; /* gtk-cursor-blink-time / 2 */
+ int m_cursor_blink_timeout{500}; /* gtk-cursor-blink-timeout */
gint64 m_cursor_blink_time; /* how long the cursor has been blinking yet */
bool m_has_focus{false}; /* is the widget focused */
@@ -691,7 +697,11 @@ public:
double m_undercurl_thickness{VTE_LINE_WIDTH};
/* Style stuff */
+#if VTE_GTK == 3
GtkBorder m_padding{1, 1, 1, 1};
+#elif VTE_GTK == 4
+ GtkBorder m_padding{0, 0, 0, 0};
+#endif
auto padding() const noexcept { return &m_padding; }
vte::glib::RefPtr<GtkAdjustment> m_vadjustment{};
@@ -806,6 +816,9 @@ public:
/* The allocation of the widget */
cairo_rectangle_int_t m_allocated_rect;
+
+ constexpr auto const* allocated_rect() const noexcept { return &m_allocated_rect; }
+
/* The usable view area. This is the allocation, minus the padding, but
* including additional right/bottom area if the allocation is not grid aligned.
*/
@@ -872,17 +885,32 @@ public:
void widget_mouse_enter(vte::platform::MouseEvent const& event);
void widget_mouse_leave(vte::platform::MouseEvent const& event);
bool widget_mouse_scroll(vte::platform::ScrollEvent const& event);
+#if VTE_GTK == 3
void widget_draw(cairo_t *cr);
- void widget_get_preferred_width(int *minimum_width,
- int *natural_width);
- void widget_get_preferred_height(int *minimum_height,
- int *natural_height);
- void widget_size_allocate(GtkAllocation *allocation);
+#endif /* VTE_GTK == 3 */
+ void widget_measure_width(int *minimum_width,
+ int *natural_width);
+ void widget_measure_height(int *minimum_height,
+ int *natural_height);
+
+#if VTE_GTK == 3
+ void widget_size_allocate(int x,
+ int y,
+ int width,
+ int height,
+ int baseline);
+#elif VTE_GTK == 4
+ void widget_size_allocate(int width,
+ int height,
+ int baseline);
+#endif /* VTE_GTK */
void set_blink_settings(bool blink,
int blink_time,
int blink_timeout) noexcept;
+ void draw(cairo_t *cr,
+ cairo_region_t const* region);
void paint_cursor();
void paint_im_preedit_string();
void draw_cells(vte::view::DrawingContext::TextRequest* items,
@@ -1119,26 +1147,53 @@ public:
bool rowcol_from_event(vte::platform::MouseEvent const& event,
long *column,
long *row);
+#if VTE_GTK == 4
+ bool rowcol_at(double x,
+ double y,
+ long* column,
+ long* row);
+#endif
char *hyperlink_check(vte::platform::MouseEvent const& event);
+ char *hyperlink_check_at(double x,
+ double y);
+ char *hyperlink_check(vte::grid::column_t column,
+ vte::grid::row_t row);
bool regex_match_check_extra(vte::platform::MouseEvent const& event,
vte::base::Regex const** regexes,
size_t n_regexes,
uint32_t match_flags,
char** matches);
+ bool regex_match_check_extra_at(double x,
+ double y,
+ vte::base::Regex const** regexes,
+ size_t n_regexes,
+ uint32_t match_flags,
+ char** matches);
+ bool regex_match_check_extra(vte::grid::column_t column,
+ vte::grid::row_t row,
+ vte::base::Regex const** regexes,
+ size_t n_regexes,
+ uint32_t match_flags,
+ char** matches);
char *regex_match_check(vte::grid::column_t column,
vte::grid::row_t row,
int *tag);
char *regex_match_check(vte::platform::MouseEvent const& event,
int *tag);
+ char *regex_match_check_at(double x,
+ double y,
+ int *tag);
void regex_match_remove(int tag) noexcept;
void regex_match_remove_all() noexcept;
void regex_match_set_cursor(int tag,
GdkCursor *gdk_cursor);
+ #if VTE_GTK == 3
void regex_match_set_cursor(int tag,
GdkCursorType cursor_type);
+ #endif
void regex_match_set_cursor(int tag,
char const* cursor_name);
bool match_rowcol_to_offset(vte::grid::column_t column,
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 1b76ff22..2a8d777d 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -9140,12 +9140,17 @@ Terminal::XTERM_WM(vte::parser::Sequence const& seq)
/* FIMXE: this should really report the monitor's workarea,
* or even just a fixed value.
*/
+#if VTE_GTK == 3
auto gdkscreen = gtk_widget_get_screen(m_widget);
int height = gdk_screen_get_height(gdkscreen);
int width = gdk_screen_get_width(gdkscreen);
_vte_debug_print(VTE_DEBUG_EMULATION,
"Reporting screen size as %dx%d cells.\n",
height / int(m_cell_height), width / int(m_cell_width));
+#elif VTE_GTK == 4
+ auto height = int(m_row_count * m_cell_height);
+ auto width = int(m_column_count * m_cell_width);
+#endif
reply(seq, VTE_REPLY_XTERM_WM,
{9, height / int(m_cell_height), width / int(m_cell_width)});
diff --git a/src/widget.cc b/src/widget.cc
index 25e4b242..a88d737b 100644
--- a/src/widget.cc
+++ b/src/widget.cc
@@ -32,6 +32,16 @@
#include "vteptyinternal.hh"
#include "debug.h"
+#if VTE_GTK == 4
+#include "graphene-glue.hh"
+#endif
+
+#if VTE_GTK == 3
+#define VTE_STYLE_CLASS_MONOSPACE GTK_STYLE_CLASS_MONOSPACE
+#elif VTE_GTK == 4
+#define VTE_STYLE_CLASS_MONOSPACE "monospace"
+#endif
+
using namespace std::literals;
namespace vte {
@@ -142,11 +152,19 @@ Widget::Widget(VteTerminal* t)
m_hscroll_policy{GTK_SCROLL_NATURAL},
m_vscroll_policy{GTK_SCROLL_NATURAL}
{
+#if VTE_GTK == 3
gtk_widget_set_can_focus(gtk(), true);
+#endif
+
+#if VTE_GTK == 4
+ gtk_widget_set_focusable(gtk(), true);
+#endif
+#if VTE_GTK == 3
/* We do our own redrawing. */
// FIXMEchpe is this still necessary?
gtk_widget_set_redraw_on_allocate(gtk(), false);
+#endif
/* Until Terminal init is completely fixed, use zero'd memory */
auto place = g_malloc0(sizeof(vte::terminal::Terminal));
@@ -156,7 +174,7 @@ Widget::Widget(VteTerminal* t)
Widget::~Widget() noexcept
try
{
- g_signal_handlers_disconnect_matched(gtk_widget_get_settings(m_widget),
+ g_signal_handlers_disconnect_matched(m_settings.get(),
G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL,
this);
@@ -175,19 +193,38 @@ void
Widget::beep() noexcept
{
if (realized())
- gdk_window_beep(gtk_widget_get_window(m_widget));
+ gtk_widget_error_bell(gtk());
}
+#if VTE_GTK == 4
+
+bool
+Widget::contains(double x,
+ double y)
+{
+ return false;
+}
+
+#endif /* VTE_GTK == 4 */
+
vte::glib::RefPtr<GdkCursor>
Widget::create_cursor(std::string const& name) const noexcept
{
+#if VTE_GTK == 3
return vte::glib::take_ref(gdk_cursor_new_from_name(gtk_widget_get_display(m_widget), name.c_str()));
+#elif VTE_GTK == 4
+ return vte::glib::take_ref(gdk_cursor_new_from_name(name.c_str(), nullptr /* fallback */));
+#endif
}
void
Widget::set_cursor(GdkCursor* cursor) noexcept
{
+#if VTE_GTK == 3
gdk_window_set_cursor(m_event_window, cursor);
+#elif VTE_GTK == 4
+ gtk_widget_set_cursor(gtk(), cursor);
+#endif
}
void
@@ -196,24 +233,36 @@ Widget::set_cursor(Cursor const& cursor) noexcept
if (!realized())
return;
- auto display = gtk_widget_get_display(m_widget);
GdkCursor* gdk_cursor{nullptr};
switch (cursor.index()) {
case 0:
- gdk_cursor = gdk_cursor_new_from_name(display, std::get<0>(cursor).c_str());
+#if VTE_GTK == 3
+ gdk_cursor = gdk_cursor_new_from_name(gtk_widget_get_display(gtk()),
+ std::get<0>(cursor).c_str());
+#elif VTE_GTK == 4
+ gdk_cursor = gdk_cursor_new_from_name(std::get<0>(cursor).c_str(),
+ nullptr /* fallback */);
+#endif /* VTE_GTK */
break;
+
case 1:
gdk_cursor = std::get<1>(cursor).get();
- if (gdk_cursor != nullptr &&
- gdk_cursor_get_display(gdk_cursor) == display) {
+ if (gdk_cursor != nullptr
+#if VTE_GTK == 3
+ && gdk_cursor_get_display(gdk_cursor) == gtk_widget_get_display(gtk())
+#endif
+ ) {
g_object_ref(gdk_cursor);
} else {
gdk_cursor = nullptr;
}
break;
+
+#if VTE_GTK == 3
case 2:
- gdk_cursor = gdk_cursor_new_for_display(display, std::get<2>(cursor));
+ gdk_cursor = gdk_cursor_new_for_display(gtk_widget_get_display(gtk()), std::get<2>(cursor));
break;
+#endif
}
set_cursor(gdk_cursor);
@@ -225,8 +274,8 @@ Clipboard&
Widget::clipboard_get(ClipboardType type) const
{
switch (type) {
- case ClipboardType::CLIPBOARD: return *m_clipboard;
case ClipboardType::PRIMARY: return *m_primary_clipboard;
+ case ClipboardType::CLIPBOARD: return *m_clipboard;
default: g_assert_not_reached(); throw std::runtime_error{""}; break;
}
}
@@ -290,15 +339,60 @@ Widget::clipboard_set_text(ClipboardType type,
clipboard_get(type).set_text(str);
}
+#if VTE_GTK == 4
+
+std::pair<bool, bool>
+Widget::compute_expand()
+{
+ return {true, true};
+}
+
+#endif /* VTE_GTK == 4 */
+
void
Widget::constructed() noexcept
{
+#if VTE_GTK == 3
+ auto context = gtk_widget_get_style_context(m_widget);
+ gtk_style_context_add_class (context, VTE_STYLE_CLASS_MONOSPACE);
+#elif VTE_GTK == 4
+ gtk_widget_add_css_class(gtk(), VTE_STYLE_CLASS_MONOSPACE);
+#endif /* VTE_GTK */
+
+#if VTE_GTK == 4
+
+ connect_settings();
+
+#endif /* VTE_GTK == 4 */
+
+#if VTE_GTK == 3
/* Set the style as early as possible, before GTK+ starts
* invoking various callbacks. This is needed in order to
* compute the initial geometry correctly in presence of
* non-default padding, see bug 787710.
*/
style_updated();
+#elif VTE_GTK == 4
+ padding_changed();
+#endif /* VTE_GTK */
+}
+
+#if VTE_GTK == 4
+
+void
+Widget::css_changed(GtkCssStyleChange* change)
+{
+ /* This function is mostly useless, since there's no public API for GtkCssStyleChange */
+
+ padding_changed();
+}
+
+#endif /* VTE_GTK == 4 */
+
+void
+Widget::direction_changed(GtkTextDirection old_direction) noexcept
+{
+ // FIXME: does this need to feed to BiDi somehow?
}
void
@@ -330,10 +424,123 @@ Widget::im_filter_keypress(KeyEvent const& event) noexcept
// FIXMEchpe this can only be called when realized, so the m_im_context check is redundant
return m_im_context &&
gtk_im_context_filter_keypress(m_im_context.get(),
- reinterpret_cast<GdkEventKey*>(event.platform_event()));
+#if VTE_GTK == 3
+ reinterpret_cast<GdkEventKey*>(event.platform_event())
+#elif VTE_GTK == 4
+ event.platform_event()
+#endif
+ );
+}
+
+#if VTE_GTK == 3
+
+void
+Widget::event_focus_in(GdkEventFocus *event)
+{
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Focus In");
+
+ m_terminal->widget_focus_in();
+}
+
+void
+Widget::event_focus_out(GdkEventFocus *event)
+{
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Focus Out");
+
+ m_terminal->widget_focus_out();
+}
+
+bool
+Widget::event_key_press(GdkEventKey *event)
+{
+ auto key_event = key_event_from_gdk(reinterpret_cast<GdkEvent*>(event));
+
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Key press key=%x keycode=%x modifiers=%x\n",
+ key_event.keyval(), key_event.keycode(), key_event.modifiers());
+
+ return m_terminal->widget_key_press(key_event);
+}
+
+bool
+Widget::event_key_release(GdkEventKey *event)
+{
+ auto key_event = key_event_from_gdk(reinterpret_cast<GdkEvent*>(event));
+
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Key release key=%x keycode=%x modifiers=%x\n",
+ key_event.keyval(), key_event.keycode(), key_event.modifiers());
+
+ return m_terminal->widget_key_release(key_event);
+}
+
+bool
+Widget::event_button_press(GdkEventButton *event)
+{
+ auto mouse_event = mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event));
+
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Click press button=%d press_count=%d x=%.3f y=%.3f\n",
+ mouse_event.button_value(), mouse_event.press_count(),
+ mouse_event.x(), mouse_event.y());
+
+ return m_terminal->widget_mouse_press(mouse_event);
+}
+
+bool
+Widget::event_button_release(GdkEventButton *event)
+{
+ auto mouse_event = mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event));
+
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Click release button=%d x=%.3f y=%.3f\n",
+ mouse_event.button_value(), mouse_event.x(), mouse_event.y());
+
+ return m_terminal->widget_mouse_release(mouse_event);
}
void
+Widget::event_enter(GdkEventCrossing *event)
+{
+ auto mouse_event = mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event));
+
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Motion enter x=%.3f y=%.3f\n",
+ mouse_event.x(), mouse_event.y());
+
+ m_terminal->widget_mouse_enter(mouse_event);
+}
+
+void
+Widget::event_leave(GdkEventCrossing *event)
+{
+ auto mouse_event = mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event));
+
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Motion leave x=%.3f y=%.3f\n",
+ mouse_event.x(), mouse_event.y());
+
+ m_terminal->widget_mouse_leave(mouse_event);
+}
+bool
+Widget::event_scroll(GdkEventScroll *event)
+{
+ auto scroll_event = scroll_event_from_gdk(reinterpret_cast<GdkEvent*>(event));
+
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Scroll delta_x=%.3f delta_y=%.3f\n",
+ scroll_event.dx(), scroll_event.dy());
+
+ return m_terminal->widget_mouse_scroll(scroll_event);
+}
+
+bool
+Widget::event_motion_notify(GdkEventMotion *event)
+{
+ auto mouse_event = mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event));
+
+ _vte_debug_print(VTE_DEBUG_EVENTS, "Motion x=%.3f y=%.3f\n",
+ mouse_event.x(), mouse_event.y());
+
+ return m_terminal->widget_mouse_motion(mouse_event);
+}
+
+#endif /* VTE_GTK == 3 */
+
+void
Widget::im_focus_in() noexcept
{
gtk_im_context_focus_in(m_im_context.get());
@@ -368,6 +575,8 @@ Widget::im_set_cursor_location(cairo_rectangle_int_t const* rect) noexcept
gtk_im_context_set_cursor_location(m_im_context.get(), rect);
}
+#if VTE_GTK == 3
+
unsigned
Widget::read_modifiers_from_gdk(GdkEvent* event) const noexcept
{
@@ -376,11 +585,9 @@ Widget::read_modifiers_from_gdk(GdkEvent* event) const noexcept
if (!gdk_event_get_state(event, &mods))
return 0;
- #if 1
/* HACK! Treat META as ALT; see bug #663779. */
if (mods & GDK_META_MASK)
mods = GdkModifierType(mods | GDK_MOD1_MASK);
- #endif
/* Map non-virtual modifiers to virtual modifiers (Super, Hyper, Meta) */
auto display = gdk_window_get_display(gdk_event_get_window(event));
@@ -390,9 +597,12 @@ Widget::read_modifiers_from_gdk(GdkEvent* event) const noexcept
return unsigned(mods);
}
+#endif /* VTE_GTK == 3 */
+
unsigned
Widget::key_event_translate_ctrlkey(KeyEvent const& event) const noexcept
{
+#if VTE_GTK == 3
if (event.keyval() < 128)
return event.keyval();
@@ -417,33 +627,55 @@ Widget::key_event_translate_ctrlkey(KeyEvent const& event) const noexcept
}
return keyval;
+#elif VTE_GTK == 4
+ // FIXMEgtk4: find a way to do this on gtk4
+ return event.keyval();
+#endif
}
KeyEvent
-Widget::key_event_from_gdk(GdkEventKey* event) const
+Widget::key_event_from_gdk(GdkEvent* event) const
{
auto type = EventBase::Type{};
- switch (gdk_event_get_event_type(reinterpret_cast<GdkEvent*>(event))) {
+ switch (gdk_event_get_event_type(event)) {
case GDK_KEY_PRESS: type = KeyEvent::Type::eKEY_PRESS; break;
case GDK_KEY_RELEASE: type = KeyEvent::Type::eKEY_RELEASE; break;
default: g_assert_not_reached(); return {};
}
- auto base_event = reinterpret_cast<GdkEvent*>(event);
- return {base_event,
+#if VTE_GTK == 3
+ auto keyval = unsigned{};
+ gdk_event_get_keyval(event, &keyval);
+ auto const scancode = unsigned(reinterpret_cast<GdkEventKey*>(event)->hardware_keycode);
+ auto const group = reinterpret_cast<GdkEventKey*>(event)->group;
+ auto const is_modifier = reinterpret_cast<GdkEventKey*>(event)->is_modifier != 0;
+#elif VTE_GTK == 4
+ auto keyval = gdk_key_event_get_keyval(event);
+ auto scancode = gdk_key_event_get_keycode(event);
+ auto const group = gdk_key_event_get_level(event);
+ auto const is_modifier = gdk_key_event_is_modifier(event) != false;
+#endif /* VTE_GTK */
+
+ return {event,
type,
- read_modifiers_from_gdk(base_event),
- event->keyval,
- event->hardware_keycode, // gdk_event_get_scancode(event),
- event->group,
- event->is_modifier != 0};
+#if VTE_GTK == 3
+ read_modifiers_from_gdk(event),
+#elif VTE_GTK == 4
+ gdk_event_get_modifier_state(event),
+#endif
+ keyval,
+ scancode,
+ group,
+ is_modifier};
}
+#if VTE_GTK == 3
+
MouseEvent
Widget::mouse_event_from_gdk(GdkEvent* event) const /* throws */
{
auto type = EventBase::Type{};
- auto press_count = 0u;
+ auto press_count = 0;
switch (gdk_event_get_event_type(event)) {
case GDK_2BUTTON_PRESS:
type = MouseEvent::Type::eMOUSE_PRESS;
@@ -478,7 +710,7 @@ Widget::mouse_event_from_gdk(GdkEvent* event) const /* throws */
!gdk_event_get_coords(event, &x, &y))
x = y = -1.; // FIXMEchpe or throw?
- auto button = unsigned{0};
+ auto button = 0u;
(void)gdk_event_get_button(event, &button);
return {type,
@@ -512,24 +744,79 @@ Widget::scroll_event_from_gdk(GdkEvent* event) const /* throws */
dx, dy};
}
+#endif /* VTE_GTK == 3 */
+
void
Widget::map() noexcept
{
+#if VTE_GTK == 3
if (m_event_window)
gdk_window_show_unraised(m_event_window);
+#endif
+}
+
+#if VTE_GTK == 4
+
+void
+Widget::measure(GtkOrientation orientation,
+ int for_size,
+ int* minimum,
+ int* natural,
+ int* minimum_baseline,
+ int* natural_baseline)
+{
+ _vte_debug_print(VTE_DEBUG_WIDGET_SIZE, "Widget measure for_size=%d orientation=%s\n",
+ for_size,
+ orientation == GTK_ORIENTATION_HORIZONTAL ? "horizontal" : "vertical");
+
+ switch (orientation) {
+ case GTK_ORIENTATION_HORIZONTAL:
+ terminal()->widget_measure_width(minimum, natural);
+ break;
+ case GTK_ORIENTATION_VERTICAL:
+ *minimum_baseline = *natural_baseline = 0;
+ terminal()->widget_measure_height(minimum, natural);
+ break;
+ }
+}
+
+#endif /* VTE_GTK == 4 */
+
+void
+Widget::padding_changed()
+{
+#if VTE_GTK == 3
+ auto padding = GtkBorder{};
+ auto context = gtk_widget_get_style_context(gtk());
+ gtk_style_context_get_padding(context,
+#if VTE_GTK == 3
+ gtk_style_context_get_state(context),
+#endif
+ &padding);
+ terminal()->set_border_padding(&padding);
+#endif /* VTE_GTK FIXMEgtk4 how to handle margin/padding? */
}
bool
Widget::primary_paste_enabled() const noexcept
{
auto primary_paste = gboolean{};
- g_object_get(gtk_widget_get_settings(gtk()),
+ g_object_get(m_settings.get(),
"gtk-enable-primary-paste", &primary_paste,
nullptr);
return primary_paste != false;
}
+bool
+Widget::query_tooltip(int x,
+ int y,
+ bool keyboard,
+ GtkTooltip* tooltip) noexcept
+{
+ return false;
+}
+
void
Widget::realize() noexcept
{
@@ -545,6 +832,7 @@ Widget::realize() noexcept
else
m_hyperlink_cursor = create_cursor(VTE_HYPERLINK_CURSOR);
+#if VTE_GTK == 3
/* Create an input window for the widget. */
auto allocation = m_terminal->get_allocated_rect();
GdkWindowAttr attributes;
@@ -579,15 +867,21 @@ Widget::realize() noexcept
m_event_window = gdk_window_new(gtk_widget_get_parent_window (m_widget),
&attributes, attributes_mask);
gtk_widget_register_window(m_widget, m_event_window);
+#endif /* VTE_GTK == 3 */
assert(!m_im_context);
- m_im_context.reset(gtk_im_multicontext_new());
-#if GTK_CHECK_VERSION (3, 24, 14)
+ m_im_context = vte::glib::take_ref(gtk_im_multicontext_new());
+#if (VTE_GTK == 3 && GTK_CHECK_VERSION (3, 24, 14)) || VTE_GTK == 4
g_object_set(m_im_context.get(),
"input-purpose", GTK_INPUT_PURPOSE_TERMINAL,
nullptr);
#endif
+
+#if VTE_GTK == 3
gtk_im_context_set_client_window(m_im_context.get(), m_event_window);
+#elif VTE_GTK == 4
+ gtk_im_context_set_client_widget(m_im_context.get(), gtk());
+#endif
g_signal_connect(m_im_context.get(), "commit",
G_CALLBACK(im_commit_cb), this);
g_signal_connect(m_im_context.get(), "preedit-start",
@@ -608,42 +902,82 @@ Widget::realize() noexcept
m_terminal->widget_realize();
}
+#if VTE_GTK == 4
+
+void
+Widget::root()
+{
+}
+
+#endif /* VTE_GTK == 4 */
+
+#if VTE_GTK == 3
+
void
Widget::screen_changed(GdkScreen *previous_screen) noexcept
{
auto gdk_screen = gtk_widget_get_screen(m_widget);
- if (previous_screen != nullptr &&
- (gdk_screen != previous_screen || gdk_screen == nullptr)) {
- auto settings = gtk_settings_get_for_screen(previous_screen);
- g_signal_handlers_disconnect_matched(settings, G_SIGNAL_MATCH_DATA,
+ if (gdk_screen == previous_screen || gdk_screen == nullptr)
+ return;
+
+ connect_settings();
+}
+
+#elif VTE_GTK == 4
+
+void
+Widget::display_changed() noexcept
+{
+ /* There appears to be no way to retrieve the previous display */
+ connect_settings();
+}
+
+#endif /* VTE_GTK */
+
+void
+Widget::connect_settings()
+{
+ auto settings = vte::glib::make_ref(gtk_widget_get_settings(m_widget));
+ if (settings == m_settings)
+ return;
+
+ if (m_settings)
+ g_signal_handlers_disconnect_matched(m_settings.get(), G_SIGNAL_MATCH_DATA,
0, 0, nullptr, nullptr,
this);
- }
- if (gdk_screen == previous_screen || gdk_screen == nullptr)
- return;
+ m_settings = std::move(settings);
settings_changed();
- auto settings = gtk_widget_get_settings(m_widget);
- g_signal_connect (settings, "notify::gtk-cursor-blink",
- G_CALLBACK(settings_notify_cb), this);
- g_signal_connect (settings, "notify::gtk-cursor-blink-time",
- G_CALLBACK(settings_notify_cb), this);
- g_signal_connect (settings, "notify::gtk-cursor-blink-timeout",
- G_CALLBACK(settings_notify_cb), this);
+ g_signal_connect(m_settings.get(), "notify::gtk-cursor-blink",
+ G_CALLBACK(settings_notify_cb), this);
+ g_signal_connect(m_settings.get(), "notify::gtk-cursor-blink-time",
+ G_CALLBACK(settings_notify_cb), this);
+ g_signal_connect(m_settings.get(), "notify::gtk-cursor-blink-timeout",
+ G_CALLBACK(settings_notify_cb), this);
+#if VTE_GTK == 4
+ g_signal_connect(m_settings.get(), "notify::gtk-cursor-aspect-ratio",
+ G_CALLBACK(settings_notify_cb), this);
+#endif
}
void
-Widget::settings_changed() noexcept
+Widget::settings_changed()
{
auto blink = gboolean{};
auto blink_time = int{};
auto blink_timeout = int{};
- g_object_get(gtk_widget_get_settings(m_widget),
+#if VTE_GTK == 4
+ auto aspect = double{};
+#endif
+ g_object_get(m_settings.get(),
"gtk-cursor-blink", &blink,
"gtk-cursor-blink-time", &blink_time,
"gtk-cursor-blink-timeout", &blink_timeout,
+#if VTE_GTK == 4
+ "gtk-cursor-aspect-ratio", &aspect,
+#endif
nullptr);
_vte_debug_print(VTE_DEBUG_MISC,
@@ -651,6 +985,10 @@ Widget::settings_changed() noexcept
blink, blink_time, blink_timeout);
m_terminal->set_blink_settings(blink, blink_time, blink_timeout);
+
+#if VTE_GTK == 4
+ m_terminal->set_cursor_aspect(aspect);
+#endif
}
void
@@ -664,6 +1002,30 @@ Widget::set_cursor(CursorType type) noexcept
}
}
+void
+Widget::set_hscroll_policy(GtkScrollablePolicy policy)
+{
+ m_hscroll_policy = policy;
+
+#if VTE_GTK == 3
+ gtk_widget_queue_resize_no_redraw(gtk());
+#elif VTE_GTK == 4
+ gtk_widget_queue_resize(gtk());
+#endif
+}
+
+void
+Widget::set_vscroll_policy(GtkScrollablePolicy policy)
+{
+ m_vscroll_policy = policy;
+
+#if VTE_GTK == 3
+ gtk_widget_queue_resize_no_redraw(gtk());
+#elif VTE_GTK == 4
+ gtk_widget_queue_resize(gtk());
+#endif
+}
+
bool
Widget::set_pty(VtePty* pty_obj) noexcept
{
@@ -704,10 +1066,19 @@ Widget::unset_pty() noexcept
g_object_notify_by_pspec(object(), pspecs[PROP_PTY]);
}
+#if VTE_GTK == 3
+
void
-Widget::size_allocate(GtkAllocation* allocation) noexcept
+Widget::size_allocate(GtkAllocation* allocation)
{
- m_terminal->widget_size_allocate(allocation);
+ _vte_debug_print(VTE_DEBUG_WIDGET_SIZE, "Widget size allocate width=%d height=%d x=%d y=%d\n",
+ allocation->width, allocation->height, allocation->x, allocation->y);
+
+ m_terminal->widget_size_allocate(allocation->x, allocation->y,
+ allocation->width, allocation->height,
+ -1);
+
+ gtk_widget_set_allocation(gtk(), allocation);
if (realized())
gdk_window_move_resize(m_event_window,
@@ -717,6 +1088,23 @@ Widget::size_allocate(GtkAllocation* allocation) noexcept
allocation->height);
}
+#elif VTE_GTK == 4
+
+void
+Widget::size_allocate(int width,
+ int height,
+ int baseline)
+{
+ _vte_debug_print(VTE_DEBUG_WIDGET_SIZE, "Widget size allocate width=%d height=%d baseline=%d\n",
+ width, height, baseline);
+
+ terminal()->widget_size_allocate(width, height, baseline);
+
+ gtk_widget_allocate(gtk(), width, height, baseline, nullptr);
+}
+
+#endif /* VTE_GTK */
+
bool
Widget::should_emit_signal(int id) noexcept
{
@@ -727,13 +1115,35 @@ Widget::should_emit_signal(int id) noexcept
}
void
+Widget::state_flags_changed(GtkStateFlags old_flags)
+{
+ _vte_debug_print(VTE_DEBUG_STYLE, "Widget state flags changed\n");
+}
+
+#if VTE_GTK == 4
+
+void
+Widget::snapshot(GtkSnapshot* snapshot_object)
+{
+ _vte_debug_print(VTE_DEBUG_DRAW, "Widget snapshot\n");
+
+ auto rect = terminal()->allocated_rect();
+ auto region = vte::take_freeable(cairo_region_create_rectangle(rect));
+ auto grect = vte::graphene::make_rect(rect);
+ auto cr = vte::take_freeable(gtk_snapshot_append_cairo(snapshot_object, &grect));
+ terminal()->draw(cr.get(), region.get());
+}
+
+#endif /* VTE_GTK == 4 */
+
+#if VTE_GTK == 3
+
+void
Widget::style_updated() noexcept
{
- auto padding = GtkBorder{};
- auto context = gtk_widget_get_style_context(gtk());
- gtk_style_context_get_padding(context, gtk_style_context_get_state(context),
- &padding);
- m_terminal->set_border_padding(&padding);
+ _vte_debug_print(VTE_DEBUG_STYLE, "Widget style changed\n");
+
+ padding_changed();
auto aspect = float{};
gtk_widget_style_get(gtk(), "cursor-aspect-ratio", &aspect, nullptr);
@@ -742,13 +1152,48 @@ Widget::style_updated() noexcept
m_terminal->widget_style_updated();
}
+#endif /* VTE_GTK == 3 */
+
+#if VTE_GTK == 4
+
+void
+Widget::system_setting_changed(GtkSystemSetting setting)
+{
+ _vte_debug_print(VTE_DEBUG_STYLE, "Widget system settings %d changed\n", int(setting));
+
+ switch (setting) {
+ case GTK_SYSTEM_SETTING_DISPLAY:
+ display_changed();
+ break;
+
+ case GTK_SYSTEM_SETTING_DPI:
+ break;
+
+ case GTK_SYSTEM_SETTING_FONT_CONFIG:
+ break;
+
+ case GTK_SYSTEM_SETTING_FONT_NAME:
+ break;
+
+ case GTK_SYSTEM_SETTING_ICON_THEME:
+ break;
+
+ default:
+ break;
+ }
+}
+
+#endif /* VTE_GTK == 4 */
+
void
Widget::unmap() noexcept
{
m_terminal->widget_unmap();
+#if VTE_GTK == 3
if (m_event_window)
gdk_window_hide(m_event_window);
+#endif
}
void
@@ -756,16 +1201,17 @@ Widget::unrealize() noexcept
{
m_terminal->widget_unrealize();
+ // FIXMEgtk4 only withdraw content from clipboard, not unselect?
if (m_clipboard) {
terminal()->widget_clipboard_data_clear(*m_clipboard);
m_clipboard->disown();
+ m_clipboard.reset();
}
if (m_primary_clipboard) {
terminal()->widget_clipboard_data_clear(*m_primary_clipboard);
m_primary_clipboard->disown();
+ m_primary_clipboard.reset();
}
- m_clipboard.reset();
- m_primary_clipboard.reset();
m_default_cursor.reset();
m_invisible_cursor.reset();
@@ -779,15 +1225,30 @@ Widget::unrealize() noexcept
0, 0, NULL, NULL,
this);
m_terminal->im_preedit_reset();
+#if VTE_GTK == 3
gtk_im_context_set_client_window(m_im_context.get(), nullptr);
+#elif VTE_GTK == 4
+ gtk_im_context_set_client_widget(m_im_context.get(), nullptr);
+#endif
m_im_context.reset();
+#if VTE_GTK == 3
/* Destroy input window */
gtk_widget_unregister_window(m_widget, m_event_window);
gdk_window_destroy(m_event_window);
m_event_window = nullptr;
+#endif /* VTE_GTK == 3 */
}
+#if VTE_GTK == 4
+
+void
+Widget::unroot()
+{
+}
+
+#endif /* VTE_GTK == 4 */
+
} // namespace platform
} // namespace vte
diff --git a/src/widget.hh b/src/widget.hh
index ede09be3..813b3625 100644
--- a/src/widget.hh
+++ b/src/widget.hh
@@ -20,6 +20,8 @@
#include <memory>
#include <optional>
#include <string>
+#include <tuple>
+#include <utility>
#include <variant>
#include "vteterminal.h"
@@ -95,7 +97,7 @@ protected:
unsigned modifiers,
unsigned keyval,
unsigned keycode,
- uint8_t group,
+ unsigned group,
bool is_modifier) noexcept
: EventBase{type},
m_platform_event{gdk_event},
@@ -126,12 +128,23 @@ public:
constexpr auto is_key_press() const noexcept { return type() == Type::eKEY_PRESS; }
constexpr auto is_key_release() const noexcept { return type() == Type::eKEY_RELEASE; }
+ bool matches(unsigned keyval,
+ unsigned modifiers) const noexcept
+ {
+#if VTE_GTK == 3
+ return false; // FIXMEgtk3
+#elif VTE_GTK == 4
+ return gdk_key_event_matches(platform_event(),
+ keyval, GdkModifierType(modifiers)) == GDK_KEY_MATCH_EXACT;
+#endif
+ }
+
private:
GdkEvent* m_platform_event;
unsigned m_modifiers;
unsigned m_keyval;
unsigned m_keycode;
- uint8_t m_group;
+ unsigned m_group;
bool m_is_modifier;
}; // class KeyEvent
@@ -154,7 +167,7 @@ protected:
MouseEvent() noexcept = default;
constexpr MouseEvent(Type type,
- unsigned press_count,
+ int press_count,
unsigned modifiers,
Button button,
double x,
@@ -190,7 +203,7 @@ public:
constexpr auto is_mouse_release() const noexcept { return type() == Type::eMOUSE_RELEASE; }
private:
- unsigned m_press_count;
+ int m_press_count;
unsigned m_modifiers;
Button m_button;
double m_x;
@@ -257,24 +270,60 @@ public:
void unrealize() noexcept;
void map() noexcept;
void unmap() noexcept;
+ void state_flags_changed(GtkStateFlags old_flags);
+ void direction_changed(GtkTextDirection old_direction) noexcept;
+ bool query_tooltip(int x,
+ int y,
+ bool keyboard,
+ GtkTooltip* tooltip) noexcept;
+
+ void connect_settings();
+ void padding_changed();
+ void settings_changed();
+
+#if VTE_GTK == 3
void style_updated() noexcept;
void draw(cairo_t *cr) noexcept { m_terminal->widget_draw(cr); }
void get_preferred_width(int *minimum_width,
- int *natural_width) const noexcept { m_terminal->widget_get_preferred_width(minimum_width, natural_width); }
+ int *natural_width) const noexcept { m_terminal->widget_measure_width(minimum_width, natural_width); }
void get_preferred_height(int *minimum_height,
- int *natural_height) const noexcept { m_terminal->widget_get_preferred_height(minimum_height, natural_height); }
- void size_allocate(GtkAllocation *allocation) noexcept;
-
- void focus_in(GdkEventFocus *event) noexcept { m_terminal->widget_focus_in(); }
- void focus_out(GdkEventFocus *event) noexcept { m_terminal->widget_focus_out(); }
- bool key_press(GdkEventKey *event) noexcept { return m_terminal->widget_key_press(key_event_from_gdk(event)); }
- bool key_release(GdkEventKey *event) noexcept { return m_terminal->widget_key_release(key_event_from_gdk(event)); }
- bool button_press(GdkEventButton *event) noexcept { return m_terminal->widget_mouse_press(mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
- bool button_release(GdkEventButton *event) noexcept { return m_terminal->widget_mouse_release(mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
- void enter(GdkEventCrossing *event) noexcept { m_terminal->widget_mouse_enter(mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
- void leave(GdkEventCrossing *event) noexcept { m_terminal->widget_mouse_leave(mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
- bool scroll(GdkEventScroll *event) noexcept { return m_terminal->widget_mouse_scroll(scroll_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
- bool motion_notify(GdkEventMotion *event) noexcept { return m_terminal->widget_mouse_motion(mouse_event_from_gdk(reinterpret_cast<GdkEvent*>(event))); }
+ int *natural_height) const noexcept { m_terminal->widget_measure_height(minimum_height, natural_height); }
+ void size_allocate(GtkAllocation *allocation);
+
+ void event_focus_in(GdkEventFocus *event);
+ void event_focus_out(GdkEventFocus *event);
+ bool event_key_press(GdkEventKey *event);
+ bool event_key_release(GdkEventKey *event);
+ bool event_button_press(GdkEventButton *event);
+ bool event_button_release(GdkEventButton *event);
+ void event_enter(GdkEventCrossing *event);
+ void event_leave(GdkEventCrossing *event);
+ bool event_scroll(GdkEventScroll *event);
+ bool event_motion_notify(GdkEventMotion *event);
+
+ void screen_changed (GdkScreen *previous_screen) noexcept;
+#endif /* VTE_GTK == 3 */
+
+#if VTE_GTK == 4
+ void size_allocate(int width,
+ int height,
+ int baseline);
+ void root();
+ void unroot();
+ void measure(GtkOrientation orientation,
+ int for_size,
+ int* minimum,
+ int* natural,
+ int* minimum_baseline,
+ int* natural_baseline);
+ std::pair<bool, bool> compute_expand();
+ void css_changed(GtkCssStyleChange* change);
+ void system_setting_changed(GtkSystemSetting setting);
+ void snapshot(GtkSnapshot* snapshot_object);
+ bool contains(double x,
+ double y);
+ void display_changed() noexcept;
+#endif /* VTE_GTK == 4 */
void grab_focus() noexcept { gtk_widget_grab_focus(gtk()); }
@@ -291,17 +340,14 @@ public:
void copy(vte::platform::ClipboardType type,
vte::platform::ClipboardFormat format) noexcept { m_terminal->widget_copy(type, format); }
- void screen_changed (GdkScreen *previous_screen) noexcept;
- void settings_changed() noexcept;
-
void beep() noexcept;
- void set_hadjustment(vte::glib::RefPtr<GtkAdjustment>&& adjustment) noexcept { m_hadjustment = std::move(adjustment); }
- void set_vadjustment(vte::glib::RefPtr<GtkAdjustment>&& adjustment) { terminal()->widget_set_vadjustment(std::move(adjustment)); }
+ void set_hadjustment(vte::glib::RefPtr<GtkAdjustment> adjustment) noexcept { m_hadjustment = std::move(adjustment); }
+ void set_vadjustment(vte::glib::RefPtr<GtkAdjustment> adjustment) { terminal()->widget_set_vadjustment(std::move(adjustment)); }
auto hadjustment() noexcept { return m_hadjustment.get(); }
auto vadjustment() noexcept { return terminal()->vadjustment(); }
- void set_hscroll_policy(GtkScrollablePolicy policy) noexcept { m_hscroll_policy = policy; }
- void set_vscroll_policy(GtkScrollablePolicy policy) noexcept { m_vscroll_policy = policy; }
+ void set_hscroll_policy(GtkScrollablePolicy policy);
+ void set_vscroll_policy(GtkScrollablePolicy policy);
auto hscroll_policy() const noexcept { return m_hscroll_policy; }
auto vscroll_policy() const noexcept { return m_vscroll_policy; }
auto padding() const noexcept { return terminal()->padding(); }
@@ -346,12 +392,15 @@ public:
return terminal()->regex_match_check(column, row, tag);
}
+#if VTE_GTK == 3
+
char* regex_match_check(GdkEvent* event,
int* tag)
{
return terminal()->regex_match_check(mouse_event_from_gdk(event), tag);
}
+
bool regex_match_check_extra(GdkEvent* event,
vte::base::Regex const** regexes,
size_t n_regexes,
@@ -367,6 +416,8 @@ public:
return terminal()->hyperlink_check(mouse_event_from_gdk(event));
}
+#endif /* VTE_GTK */
+
bool should_emit_signal(int id) noexcept;
bool set_sixel_enabled(bool enabled) noexcept { return m_terminal->set_sixel_enabled(enabled); }
@@ -381,7 +432,9 @@ protected:
eHyperlink
};
+#if VTE_GTK == 3
GdkWindow* event_window() const noexcept { return m_event_window; }
+#endif
bool realized() const noexcept
{
@@ -415,10 +468,12 @@ public: // FIXMEchpe
void im_preedit_changed() noexcept;
private:
+ KeyEvent key_event_from_gdk(GdkEvent* event) const;
+#if VTE_GTK == 3
unsigned read_modifiers_from_gdk(GdkEvent* event) const noexcept;
- KeyEvent key_event_from_gdk(GdkEventKey* event) const;
MouseEvent mouse_event_from_gdk(GdkEvent* event) const /* throws */;
ScrollEvent scroll_event_from_gdk(GdkEvent* event) const /* throws */;
+#endif
void clipboard_request_received_cb(Clipboard const& clipboard,
std::string_view const& text);
@@ -432,8 +487,12 @@ private:
vte::terminal::Terminal* m_terminal;
+#if VTE_GTK == 3
/* Event window */
GdkWindow *m_event_window;
+#endif
+
+ vte::glib::RefPtr<GtkSettings> m_settings{nullptr};
/* Cursors */
vte::glib::RefPtr<GdkCursor> m_default_cursor;