support for displaying images in webview - #2262
Conversation
when moving the cursor down there was an issue where the screen randomly jumps a few lines down
|
❌ Code Contractor Validation: FAILED 📋 Contract Configuration: contract (Source: Repository)version: 2
trigger:
paths:
- "extensions/**"
- "frontends/**/*.lisp"
- "src/**"
- "tests/**"
- "contrib/**"
- "**/*.asd"
head_branches:
exclude:
- 'revert-*'
validation:
limits:
max_total_changed_lines: 400
max_delete_ratio: 0.5
max_files_changed: 10
severity: warning
ai:
system_prompt: |
You are a senior Common Lisp engineer reviewing code for Lem editor.
Lem is a text editor with multiple frontends (ncurses, SDL2, webview).
Focus on maintainability, consistency with existing code, and Lem-specific conventions.
rules:
# === File Structure ===
- name: defpackage_rule
prompt: |
First form must be `defpackage` or `uiop:define-package`.
Package name should match filename (e.g., `foo.lisp` → `:lem-ext/foo` or `:lem-foo`).
Extensions must use `lem-` prefix (e.g., `:lem-python-mode`).
- name: file_structure_rule
prompt: |
File organization (top to bottom):
1. defpackage
2. defvar/defparameter declarations
3. Key bindings (define-key, define-keys)
4. Class/struct definitions
5. Functions and commands
# === Style ===
- name: loop_keywords_rule
prompt: |
Loop keywords must use colons: `(loop :for x :in list :do ...)`
NOT: `(loop for x in list do ...)`
- name: naming_conventions_rule
prompt: |
Naming conventions:
- Functions/variables: kebab-case (e.g., `find-buffer`)
- Special variables: *earmuffs* (e.g., `*global-keymap*`)
- Constants: +plus-signs+ (e.g., `+default-tab-size+`)
- Predicates: -p suffix for functions (e.g., `buffer-modified-p`)
- Do NOT use -p suffix for user-configurable variables
# === Documentation ===
- name: docstring_rule
prompt: |
Required docstrings for:
- Exported functions, methods, classes
- `define-command` (explain what the command does)
- Generic functions (`:documentation` option)
Important functions should explain "why", not just "what".
severity: warning
# === Lem-Specific ===
- name: internal_symbol_rule
prompt: |
Use exported symbols from `lem` or `lem-core` package.
Avoid `lem::internal-symbol` access.
If internal access is necessary, document why.
- name: error_handling_rule
prompt: |
- `error`: Internal/programming errors
- `editor-error`: User-facing errors (displayed in echo area)
Always use `editor-error` for messages shown to users.
- name: frontend_interface_rule
prompt: |
Frontend-specific code must use `lem-if:*` protocol.
Do not call frontend implementation directly from core.
severity: warning
# === Functional Style ===
- name: functional_style_rule
prompt: |
Prefer explicit function arguments over dynamic variables.
Avoid using `defvar` for state passed between functions.
Exception: Well-documented cases like `*current-buffer*`.
- name: dynamic_symbol_call_rule
prompt: |
Avoid `uiop:symbol-call`. Rethink architecture instead.
If unavoidable, document the reason.
# === Libraries ===
- name: alexandria_usage_rule
prompt: |
Alexandria utilities allowed: `if-let`, `when-let`, `with-gensyms`, etc.
Avoid: `alexandria:curry` (use explicit lambdas)
Avoid: `alexandria-2:*` functions not yet used in codebase
# === Macros ===
- name: macro_style_rule
prompt: |
Keep macros small. For complex logic, use `call-with-*` pattern:
```lisp
(defmacro with-foo (() &body body)
`(call-with-foo (lambda () ,@body)))
```
Prefer `list` over backquote outside macros.💬 Feedback Reply to a violation comment with:
📚 About Code ContractorDeclarative Code Standards That Learn and Improve Define domain-specific validation rules in YAML. Want this for your repo? |
|
this introduces functionality to display in webview, the functionality exists in the sdl2 frontend but not in webview. the functionality so far is very basic and only works properly with images that originate from attributes of virtual text that originates from an overlay, by virtual text i mean the :before-item/:after-item stuff that was introduced in #2230, because the cursor is meant to skip over those virtual items. and currently when the cursor goes over non-virtual images the buffer gets confused. the core currently uses a uniform grid for displaying text which makes it hard to work with arbitrarily sized objects so we round image sizes to multiples of cell sizes. selecting text with cursor doesnt work because images dont align with the buffer flow so the client doesnt properly resolve cursor click position relevant to the text grid. hoping to addess this soon. |
|
example usage: (lem:define-command webview-image-demo () ()
(let* ((image (namestring (asdf:system-relative-pathname :lem #p"resources/lem.png")))
(attr (lem:make-attribute :plist (list :image image :pixel-width 300 :pixel-height 150)))
(buffer (lem:make-buffer "*image-demo*"))
(point (lem:buffer-point buffer)))
(lem:switch-to-buffer buffer)
(lem:erase-buffer buffer)
(lem:insert-string point (format nil "before X after~%more text~%"))
(lem:with-point ((s point)
(e point))
(lem:buffer-start s)
(lem:character-offset s 7)
(lem:move-point e s)
(lem:character-offset e 1)
(let ((ov (lem:make-overlay s e attr)))
(lem:overlay-put
ov
:cursor-enter-functions (list 'lem:move-point-out-of-overlay))))
(lem:buffer-start point))) |
they now report the size of one character cell in the frontend's layout units (1 on terminal and webview, pixels on sdl2)
every frontend measured the same way, so the arithmetic now lives once in physical-line.lisp. frontends keep a method only for what they draw at another size. an image with no size of its own asks for one through the new lem-if:image-natural-size.
lem-if:render-line handed frontends loose objects and left placement to each one. it is replaced by lem-if:render-row, taking a lem-core/display:row with height, fill and per-object placement from layout-row. objects hang from a shared baseline, reported via lem-if:cell-pixel-size and lem-if:object-ascent. extend-to-eol becomes row-fill-x/row-fill-color rather than an object.
cell-width/cell-height report the client's real font metrics instead of 1, so every coordinate the server sends is a pixel. the client sends its metrics with every redraw, so a font change re-lays out the display the way a resize does.
images take an :ascent property, so one can be raised off the baseline. an image that overflows is cropped rather than wrapped; the crop narrows what is shown, not the drawn size.
also fixes a pre-existing bound in the wrapping path that compared y, in the frontend's units, against window-height, a row count.
row fills and the modeline background were sent as an empty put with a width and height, since put was the only notification that could paint a color. put now draws one line of text; draw-block fills a rect.
|
this PR contains more than just 'image support for webview', i unified some of the rendering/layout code between the different frontends. the webview doesnt use a grid of uniform cells anymore, and it mainly uses pixels for sizing things instead of cells, like the sdl2 frontend does. this PR is a follow-up for #2230 |
drawing-object's width and image-object's were one slot, not two.
put filled a background one text line tall while extend-to-eol filled the whole row, so selecting a line with an image on it drew two heights. send the row's top and height with a put on a tall row, paint the image's own attribute behind it, and report the caret on the row's text line when the cursor sits on the image.
No description provided.