Skip to content

Gtk4 merge - #4

Draft
mattrose wants to merge 8 commits into
masterfrom
gtk4-merge
Draft

mattrose wants to merge 8 commits into
masterfrom
gtk4-merge

Conversation

@mattrose

Copy link
Copy Markdown
Owner

No description provided.

mattrose added 8 commits June 30, 2026 23:58
Complete PyGObject GTK3→GTK4 migration covering all core library files,
plugins, and Glade UI files.

Key changes:
- Replace Gtk.Menu/MenuItem with Gio.Menu + Gtk.PopoverMenu + Gio.SimpleActionGroup
- Replace dialog.run() with GLib.MainLoop shim pattern throughout
- Replace old-style signals with Gtk.EventControllerKey/Focus/Scroll/GestureClick
- Replace get_toplevel() with get_root(), window.add() with set_child()
- Replace Gtk.HPaned/VPaned with Gtk.Paned(orientation=...)
- Replace Gdk.color_parse() with Gdk.RGBA + parse()
- Replace FileChooserDialog buttons= param with add_button(); get_filename() with get_file().get_path()
- Replace window-state-event with notify::fullscreened / notify::maximized
- Replace Gtk.events_pending() with GLib.MainContext.default()
- Add KeyEventProxy bridge class in keybindings.py for GTK4 key events
- Port all plugins to new tuple-based menu API: (label, callback, *args)
- Rewrite custom_commands.py and run_cmd_on_match.py dialogs (Grid, Box, set_child)
- Convert both .glade files: GtkAlignment→unwrapped with margins, GtkVBox/HBox/ButtonBox→GtkBox, all <packing>→<layout> with renamed Grid properties (left-attach→column, top-attach→row), requires gtk 4.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- keybindings.py: MOD1_MASK→ALT_MASK, MOD2_MASK→META_MASK, MOD4_MASK→SUPER_MASK;
  remove Gdk.Display.get_keymap() call (no longer available in GTK4)
- window.py: iconify()→minimize() (GTK4 rename)
- terminal.py: remove grab-focus signal (gone in GTK4); replace size-allocate
  with notify::width on VTE widget; update handler signatures accordingly
- paned.py: replace size-allocate with notify::width; update new_size signature
- All VTE files: gi.require_version('Vte', '2.91')→'3.91' for GTK4-compatible VTE
- plugins/mousefree_url_handler.py: port key-press-event→EventControllerKey,
  update on_keypress signature, guard on_focus_in against None terminal
- plugins/remote.py: VTE version bump (already applied by sed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- terminal.py: has-toplevel-focus → is-active (GTK4 property rename on Gtk.Window)
- plugin.py: MOD2_MASK → META_MASK in KeyBindUtil.keyaction() (MOD2_MASK removed in GTK4)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Parent the Gtk.PopoverMenu to the terminal Box widget (not terminal.vte)
and insert the action group on the terminal widget. This avoids VTE's
own event/action handling from interfering with action dispatch.
Translate click coordinates from VTE-space to terminal-space using
translate_coordinates().

Also fix: MOD2_MASK→META_MASK in plugin.py, has-toplevel-focus→is-active
in terminal.py (GTK4 renames), remove xalign keyword from Gtk.Label
constructor and flags= from Gtk.Dialog constructor (both deprecated GTK4).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… widths

- Add CSS at STYLE_PROVIDER_PRIORITY_USER to fix treeview cell text
  invisible on macOS dark mode (GTK4 backend injects light text color
  at ~priority 700, overriding application-level CSS)
- Increase hpaned4 and hpaned1 position from 150px to 200px so the
  Add/Remove/Copy buttons in the left pane are no longer clipped
- Replace GTK2 stock labels (gtk-add, gtk-remove, gtk-save) on layout
  buttons with plain text labels (Add, Remove, Save)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Merges gnome-terminator/terminator master (through v2.1.6, commit 9f2d0b6)
into the GTK4 port. The port was imported as a squashed snapshot with no
shared history, so the merge was performed against upstream 3e748b1 (the
last upstream commit before the port) as the merge base.

Upstream changes brought in:
- Detach Tab action + detach-tab signal/keybinding, deferred tab detach
- Close confirmation on the context-menu Close action
- Ctrl+click URL handling: only act on the initial press, consume the event
- Window title flicker fix for background terminals
- Apply button in preferences
- background_image_span_window option
- Version bump to 2.1.6, changelog/AUTHORS/doc updates

GTK4 adaptations applied during conflict resolution:
- notebook.py: kept GTK4 sizing (no window.move), set_child/present instead
  of add/show_all; dropped the GTK3-only 'drag-failed' handler
- terminal.py: reimplemented the URL click fixes on the GTK4 gesture handler
  (n_press guard + EventSequenceState.CLAIMED); kept background_draw stubbed
  since GTK4 uses snapshot rather than draw; get_root/is_active for the
  title fix
- terminal_popup_menu.py: reapplied close-confirmation and Detach Tab to the
  Gio.Menu/PopoverMenu implementation
- preferences.glade: converted the new widgets off GTK3 <packing>/stock
- tests: retargeted the new upstream tests to GTK 4.0

Deviation from upstream: Notebook.remove() calls detach_tab(widget) rather
than upstream's detach_tab(page_num), which raises TypeError (detach_tab
takes a child widget, not a page index).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUL3apkVJWNu9XDhTu8Jgp
Detach Tab was dead on arrival after the upstream merge: every attempt
logged "could not find tab to detach" and did nothing.

find_tab_root walked up the parent chain until it reached the Notebook,
returning the last widget before it. That holds in GTK3, where a page's
parent is the Notebook itself, but GTK4 interposes an internal GtkStack,
so the walk returned the Stack. detach_tab_to_new_window then rejected it
via page_num(child) == -1.

The function predates the merge, but nothing exercised it on this path
until upstream's new detach code started routing through it.

Resolve the page by asking the notebook which ancestor is actually one of
its pages instead of assuming the shape of the parent chain. Verified by
driving the real Window/Notebook/Terminal objects in a live GTK4 loop:
detach via the notebook API, via emit('detach-tab') (the Shift+Ctrl+D
path), and Notebook.remove() all now work, with the tab reparented into a
visible new window and the source window collapsing back out of its
notebook.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUL3apkVJWNu9XDhTu8Jgp
@mattrose
mattrose marked this pull request as draft September 20, 2026 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant