Skip to content

#540: #448-C: Flip GTK main loop from Relm4 to ShellApp runner; delete Relm4 scaffolding (sub-task 3/3 of #448) - #543

Merged
JDonaghy merged 4 commits into
developfrom
issue-540-448-c-flip-gtk-main-loop-from-relm4-to-s
Jun 29, 2026
Merged

#540: #448-C: Flip GTK main loop from Relm4 to ShellApp runner; delete Relm4 scaffolding (sub-task 3/3 of #448)#543
JDonaghy merged 4 commits into
developfrom
issue-540-448-c-flip-gtk-main-loop-from-relm4-to-s

Conversation

@JDonaghy

Copy link
Copy Markdown
Owner

Closes #540

Automated merge from the coordinator for assignment b4a96ef88e99 on issue #540.

Worker branch: issue-540-448-c-flip-gtk-main-loop-from-relm4-to-sdevelop.

JDonaghy and others added 4 commits June 28, 2026 16:26
- Delete impl SimpleComponent for App (~3 059 lines): removes fn init,
  the Relm4 view! macro, and fn update
- Add App::new(file_path) constructor containing engine init, CSS load,
  file watcher and MsgSender setup that used to live in fn init
- Implement impl quadraui::ShellApp for App: render_content renders
  editor windows, tab bar, status bar and command line via Backend trait
  calls; handle routes UiEvent variants to existing Msg/dispatch handlers;
  tick drains the MsgSender queue and calls handle_poll_tick; setup seeds
  cached font metrics and captures the runner's GTK window
- Replace RelmApp::from_app().run::<App>() with App::new() +
  ShellConfig::new("VimCode", vec![]) + run_with_shell in pub fn run()
- Remove relm4 from gui feature flag and from [dependencies] in Cargo.toml
- Fix three pre-existing duplicate struct fields in render.rs (focused_index,
  focused_index, table) that were blocking the build
- Suppress newly-dead-code warnings on sidebar/panel draw functions,
  GTK event re-exports, and core engine methods that were previously called
  from the deleted Relm4 scaffolding; all marked with #[allow(dead_code)]
  and a note pointing to the follow-on re-wiring task

Build: cargo build clean (0 warnings)
Tests: cargo test --no-default-features — 2 119 passed, 0 failed
Lint:  cargo clippy -- -D warnings — clean
Fmt:   cargo fmt applied

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Under the old Relm4 path, GTK was initialized inside
RelmApp::create_and_run() before any app code ran.  With the
ShellApp runner it happens inside gapp.run() (called from
run_with_shell()), which is after App::new() returns.

App::new() calls load_css() → CssProvider::new() + Display::default()
and gtk4::Settings::default() — all of which require GTK to already
be initialized.  Adding gtk4::init() in run() before App::new() fixes
the immediate crash reported in the smoke test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three smoke-test failures after the ShellApp flip (#448-C):

1. CRASH ON CLICK — editor_pango_layout() panicked because
   self.drawing_area is always None under the quadraui ShellApp runner
   (the runner owns the single DrawingArea, not vimcode).  Fix: fall back
   to the runner-created Window's pango context (set in setup()), with a
   last-resort FontMap fallback for early-init paths.

2. SIDEBAR COMPLETELY MISSING — ShellConfig was constructed with an
   empty panels list, so the quadraui runner drew no activity bar.  Fix:
   partition the engine's AppShell panels into top / bottom groups and
   pass them to ShellConfig + with_bottom_items().  Also implement
   on_shell_event() to mirror runner panel-switch/hide events back into
   engine.app_shell (so render_content() knows which panel is active),
   and render each panel's content into layout.sidebar_content_bounds
   via the existing Backend-trait populate + render paths.

3. KEYS PRODUCE NO VISIBLE CHANGE — set_viewport_for_window() was
   gated inside an if-let that checked self.drawing_area (always None
   under ShellApp).  The engine's viewport was never updated from the
   render layout, so ensure_cursor_visible used wrong dimensions and
   cursor motion had no effect on the rendered view.  Fix: move the
   viewport-sync block outside the da_size guard; it reads only from
   cached_screen_layout which is populated by render_content() regardless
   of drawing_area state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, icons, settings)

- Status bar blank: render per-window status bars inside the editor-window
  loop by calling render::window_status_line_to_status_bar() for each
  rw.status_line and pushing Surface::StatusBar at bar_y = rect.y +
  rect.height - lh.  global_status_bar is None by default when
  window_status_line=true so per-window bars were never drawn.

- Sluggish input: add self.draw_needed.set(true) unconditionally after the
  MouseDown button-match block and after the DoubleClick dispatch call so
  handle() always returns Reaction::Redraw on mouse events.  The
  ShellApp-mode da.queue_draw() is a no-op; draw_needed is the only signal
  the runner polls.

- Activity bar icons missing: map over engine AppShell panels in run()
  and fill p.icon from crate::icons before building ShellConfig; the
  engine initialises all PanelDefinition.icon fields to "" because it is
  backend-agnostic.

- Settings panel blank: handle AppShellEvent::BottomItemClicked in
  on_shell_event() by calling engine.app_shell.show_panel(id); the runner
  fires BottomItemClicked (not PanelChanged) for bottom-bar items so the
  engine's active panel was never updated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

#448-C: Flip GTK main loop from Relm4 to ShellApp runner; delete Relm4 scaffolding (sub-task 3/3 of #448)

1 participant