Files
ctile/AGENTS.md
prairienerd18 f4433450ff Initial commit — CTile Cinnamon extension
Snap layout overlay for Cinnamon 6.6. Drag a window to the top edge
to reveal a picker with 14 tiling presets (halves, quarters, thirds).
Layout previews use the system theme's accent color and update live
when the theme changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 20:22:24 -05:00

2.6 KiB

Agent guidance for CTile

What this project is

A Cinnamon desktop extension (JavaScript, GJS runtime). There is no build step — files are loaded directly by Cinnamon's JS interpreter.

Repository layout

ctile/
  extension.js    ← all logic; entry points are init(), enable(), disable()
  metadata.json   ← UUID, display name, supported Cinnamon versions
  stylesheet.css  ← St/CSS styles for the overlay and buttons
  README.md
  AGENTS.md

Install by copying the whole directory to ~/.local/share/cinnamon/extensions/ctile@ctile/.

Runtime environment

  • Engine: GJS (GNOME JavaScript, SpiderMonkey-based)
  • Cinnamon version: 6.6.7 · Muffin version: 6.6.3
  • Imports: imports.gi.* for GObject introspection bindings; imports.ui.* for Cinnamon shell modules; imports.mainloop for timers
  • No npm, no bundler, no transpiler — plain ES6 classes work; import/export do not

How to test changes

  1. Copy changed files into the installed location:
    cp ctile@ctile/* ~/.local/share/cinnamon/extensions/ctile@ctile/
    
  2. Reload the extension without restarting Cinnamon:
    dbus-send --session --dest=org.Cinnamon /org/Cinnamon org.Cinnamon.Eval \
      string:'const es = imports.ui.extensionSystem; es.disableExtension("ctile@ctile"); es.enableExtension("ctile@ctile");'
    
  3. Check logs: grep '\[ctile\]' ~/.xsession-errors

Syntax-check JS before deploying:

node --check ctile@ctile/extension.js

Key implementation details

Signal arity (important gotcha)

Muffin 6.6 fires grab-op-begin with four arguments: (display, screen, window, op).
Older Muffin versions used three. Getting this wrong silently breaks everything — the op check never matches and no drag is detected.

Overlay z-ordering

The overlay actor is added to global.stage (not Main.uiGroup) and raised to the top sibling on each show, so it appears above panels and all windows.

Accent color

Read at build time via Gtk.Button().get_style_context().lookup_color('accent_color') and refreshed on both St.ThemeContext 'changed' and Gtk.Settings 'notify::gtk-theme-name' signals.

Pointer tracking during drag

Muffin consumes pointer events during a window drag, so overlay buttons are reactive: false. Hover state is computed manually in a Mainloop.timeout_add poll loop (every 40 ms) by comparing raw pointer coordinates against each button's transformed bounding box.

Overlay visibility logic

  • Show when pointer Y ≤ TRIGGER_Y px below the monitor's top edge
  • Stay visible while pointer is within 20 px of the overlay's bounding box
  • Hide otherwise