mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-11 21:03:05 +08:00
arm: LimitNotifyEvents around the four paste sites
This commit is contained in:
parent
bb936e972c
commit
4db9163a7d
295
plans/ARM64_Flicker_Analysis.md
Normal file
295
plans/ARM64_Flicker_Analysis.md
Normal file
@ -0,0 +1,295 @@
|
||||
# ARM64 Flicker Analysis — Notepad3 Editor Pane
|
||||
|
||||
**Scope:** Slow, visible flicker in the Scintilla editor pane on Qualcomm ARM64 devices, strongly correlated with paste operations, aggravated by Windows 11 25H2, behaving differently across GDI vs. D2D rendering. A recent ARM64 mitigation reduced but did not eliminate the problem.
|
||||
|
||||
**Date:** 2026-04-24
|
||||
**Repository state:** branch `dev_master`, tip `d6d5f41b5`
|
||||
|
||||
---
|
||||
|
||||
## 1. Problem statement
|
||||
|
||||
- Affects: Notepad3 on Windows-on-ARM (Snapdragon / Qualcomm Adreno GPUs).
|
||||
- Trigger: most visible during copy/paste into the editor pane; also reported on theme / DPI / color-scheme transitions.
|
||||
- OS sensitivity: worse on Windows 11 25H2 than on 23H2/24H2.
|
||||
- Rendering-mode sensitivity: flicker pattern differs between GDI (`SC_TECHNOLOGY_DEFAULT`) and D2D variants.
|
||||
- After the recent ARM64 fix: reduced but still present.
|
||||
|
||||
---
|
||||
|
||||
## 2. What the recent ARM64 fix actually does
|
||||
|
||||
Two application-level changes (no Scintilla patches were needed for the fix itself):
|
||||
|
||||
| Change | Location | Effect |
|
||||
|---|---|---|
|
||||
| Main window carries `WS_EX_COMPOSITED` on ARM64 only | `src/Notepad3.c:1914-1918` | DWM double-buffers the parent bottom-up. |
|
||||
| Default `RenderingTechnology = SC_TECHNOLOGY_DIRECTWRITERETAIN` (2) on ARM64 | `src/Config/Config.cpp:1332-1338` | Scintilla uses a GDI-compatible retained `ID2D1DCRenderTarget` instead of a DXGI flip swap chain. |
|
||||
|
||||
Pre-existing and unchanged by that fix:
|
||||
|
||||
- The **status bar also has `WS_EX_COMPOSITED`** unconditionally (`src/Notepad3.c:3314-3323`). On ARM64 this means the paint path now has **nested** composited surfaces (main + status).
|
||||
- `scintilla/np3_patches/upstream_558/001_undo_selection_redraw.patch` adds an extra `Redraw()` after undo-selection restore — relevant because paste is an undoable action.
|
||||
|
||||
---
|
||||
|
||||
## 3. Cause model — why paste specifically, why 25H2, why Adreno
|
||||
|
||||
A paste is not a single repaint; it is a **storm of paint triggers** arriving in the same few milliseconds, coinciding with a DWM state that Adreno/25H2 handles poorly:
|
||||
|
||||
1. `SciCall_Paste()` modifies many lines atomically → Scintilla issues at least one full-visible-range `Redraw()`.
|
||||
2. `SCN_MODIFIED` fires → `EnableDocChangeNotification()` (`src/Notepad3.c:374-381`) calls `EditUpdateVisibleIndicators()` → additional margin / marker invalidates.
|
||||
3. The same callback calls `UpdateStatusbar(false)`. This is deferred via a timer, but the deferred path at `src/Notepad3.c:10818-10833` does:
|
||||
|
||||
```c
|
||||
SendMessage(Globals.hwndStatus, WM_SETREDRAW, FALSE, 0);
|
||||
// ... SB_SETPARTS / SB_SETMINHEIGHT / StatusSetText ...
|
||||
SendMessage(Globals.hwndStatus, WM_SETREDRAW, TRUE, 0);
|
||||
InvalidateRect(Globals.hwndStatus, NULL, TRUE); // note TRUE
|
||||
```
|
||||
|
||||
4. `SCN_UPDATEUI` fires → caret / selection repaint + status update.
|
||||
5. Auto-scroll into view if the caret moves below the visible region → another full pane invalidate.
|
||||
6. If the paste lands inside an active "mark all occurrences" region, `MarkAllOccurrences` queues and fires shortly after.
|
||||
7. On undo, the patched `Redraw()` from `upstream_558/001` fires again.
|
||||
|
||||
On Intel/AMD + recent Win11 builds, DWM collapses this into ~1 frame. On **Adreno + 25H2**, DWM appears to present the parent composited buffer and Scintilla's own D2D surface on *different ticks*, exposing the composited buffer (background colour) between Scintilla's `BeginDraw`/`EndDraw` pairs. `DIRECTWRITERETAIN` reduces this because the retained target keeps the previous frame visible across the gap — but if the parent composited buffer is invalidated by a secondary update (status bar) mid-burst, a flash is still visible.
|
||||
|
||||
**Why the GDI vs. D2D behaviour differs:**
|
||||
|
||||
| Mode | Mechanism | Interaction with `WS_EX_COMPOSITED` |
|
||||
|---|---|---|
|
||||
| `SC_TECHNOLOGY_DEFAULT` (0, GDI) | No swap chain; WM_PAINT-driven | Parent composition mostly wins; flicker is background-erase-driven. |
|
||||
| `SC_TECHNOLOGY_DIRECTWRITE` (1) | DXGI swap chain on Scintilla's HWND | Scintilla presents independently of DWM compositor → heavy flicker on Adreno/25H2. |
|
||||
| `SC_TECHNOLOGY_DIRECTWRITERETAIN` (2) | GDI-compatible D2D; retained target | Current ARM64 default; compromise — presented via GDI on WM_PAINT. |
|
||||
| `SC_TECHNOLOGY_DIRECTWRITEDC` (3) | `ID2D1DCRenderTarget` over a DC from WM_PAINT | Fully parented into GDI; `WS_EX_COMPOSITED` can buffer the result end-to-end. |
|
||||
|
||||
---
|
||||
|
||||
## 4. Remaining suspects, ranked by likelihood
|
||||
|
||||
### A. Status-bar invalidation with `bErase = TRUE` during paste bursts — **high suspicion**
|
||||
|
||||
`src/Notepad3.c:10833`:
|
||||
|
||||
```c
|
||||
InvalidateRect(Globals.hwndStatus, NULL, TRUE);
|
||||
```
|
||||
|
||||
The status bar is `SBT_OWNERDRAW | WS_EX_COMPOSITED`. Passing `TRUE` forces a `WM_ERASEBKGND` cycle on a window that owner-draws its own background — wasted work that also invalidates the parent composited buffer. Every paste triggers this path. Matches the paste-coupling pattern exactly.
|
||||
|
||||
### B. Nested `WS_EX_COMPOSITED` (main + status bar) — **medium-high suspicion**
|
||||
|
||||
Main window on ARM64 and the status bar (always) both carry `WS_EX_COMPOSITED`. DWM documentation warns against combining `WS_EX_COMPOSITED` with child windows that do their own buffered rendering; having **two layers** of compositor-buffering along the paint path is a known problematic combination on newer DWM builds. The status-bar flag predates the ARM64 fix and wasn't revisited when the parent flag was added.
|
||||
|
||||
### C. `SC_TECHNOLOGY_DIRECTWRITERETAIN` is a half-measure — **medium suspicion**
|
||||
|
||||
Mode 2 uses `ID2D1DCRenderTarget` + the retain-usage bit but still presents via GDI on WM_PAINT, with its own back buffer. Mode 3 (`DIRECTWRITEDC`) hands the DC from the HWND's WM_PAINT straight through, which is what `WS_EX_COMPOSITED` expects. On some 25H2 builds the retained target fails to be invalidated between paste-triggered paints, leaving a stale tile that the next paint flashes over. Would explain "helped a bit, still flickers".
|
||||
|
||||
### D. `MsgThemeChanged` uses `RDW_ERASE | RDW_ALLCHILDREN` — **low-medium suspicion**
|
||||
|
||||
`src/Notepad3.c:3478`:
|
||||
|
||||
```c
|
||||
RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
|
||||
```
|
||||
|
||||
Correct for a theme change, but `MsgDPIChanged` re-invokes `MsgThemeChanged`, and 25H2 has been observed to fire spurious DPI / colour-scheme change messages more eagerly (dark mode toggles, accent changes, HDR transitions). Note the contradiction with `src/DarkMode/ListViewUtil.hpp:64`, which deliberately omits `RDW_ERASE` for exactly this reason — the main-window path is the outlier. Relevant only if the user reports flicker on non-paste events too.
|
||||
|
||||
### E. `LimitNotifyEvents` / `RestoreNotifyEvents` is not used around paste — **medium suspicion**
|
||||
|
||||
`src/Notepad3.h:182` defines a macro that suppresses `SCN_*` notifications and toggles `WM_SETREDRAW` on the edit window. It is used for bulk edits (sort, encode, etc.) — but **paste uses `UndoTransActionBegin` only**, which groups undo but does nothing for notification throttling. Each inserted chunk can still trigger a full notify / repaint cycle. Especially relevant for paste of large clipboard contents.
|
||||
|
||||
### F. `SciCall_SetBufferedDraw` is never called — **low suspicion**
|
||||
|
||||
Declared at `src/SciCall.h:166-167` but never invoked. In GDI mode and `DIRECTWRITEDC` mode this flag enables Scintilla's own offscreen bitmap buffering; under D2D modes 1 and 2 Scintilla ignores it. Relevant only when experimenting with `DIRECTWRITEDC`.
|
||||
|
||||
---
|
||||
|
||||
## 5. Recommended experiments (ordered, cheapest first)
|
||||
|
||||
Each step isolates one hypothesis. Validate with the reporter after each.
|
||||
|
||||
1. **Flip the status-bar erase flag.** Change `InvalidateRect(Globals.hwndStatus, NULL, TRUE)` → `FALSE` at `src/Notepad3.c:10833`. Zero risk (owner-drawn control paints its own background). Targets suspect **A**.
|
||||
2. **Remove `WS_EX_COMPOSITED` from the status bar on ARM64** (or everywhere). Targets suspect **B**. If flicker worsens on non-ARM64, revert; on ARM64 with the parent already composited, the status-bar flag is almost certainly redundant.
|
||||
3. **Ask the reporter to set `RenderingTechnology=3` (`DIRECTWRITEDC`) in their INI.** Single-line INI change, no rebuild needed. If it fixes flicker, make it the ARM64 default (targets suspect **C**). If it worsens paste flicker, keep mode 2 and move on.
|
||||
4. **Wrap the paste path in `LimitNotifyEvents` / `RestoreNotifyEvents`** (targets suspect **E**):
|
||||
|
||||
```c
|
||||
case IDM_EDIT_PASTE:
|
||||
if (SciCall_CanPaste()) {
|
||||
if (s_flagPasteBoard) { s_bLastCopyFromMe = true; }
|
||||
LimitNotifyEvents();
|
||||
UndoTransActionBegin();
|
||||
SciCall_Paste();
|
||||
EndUndoTransAction();
|
||||
RestoreNotifyEvents();
|
||||
}
|
||||
break;
|
||||
```
|
||||
|
||||
The macro already toggles `WM_SETREDRAW` on `Globals.hwndEdit` and invalidates once at the end. This collapses the paste burst into a single repaint — directly targeting the paste-specific complaint.
|
||||
|
||||
5. **Audit `_DelayUpdateStatusbar` throttle interval for ARM64.** If ≤16 ms, multiple fires occur inside a single frame; ~50 ms during paste bursts is safer.
|
||||
6. **Long term:** introduce a `Settings2.ARM64FlickerWorkaround` umbrella flag bundling whichever of (1)–(4) prove necessary, so end-users on affected hardware can opt in without a rebuild. (Document per repo convention: `Build/Notepad3.ini` commented entry + prose in `readme/config/Configuration.md`.)
|
||||
|
||||
---
|
||||
|
||||
## 6. What not to do
|
||||
|
||||
- **Don't add `WM_ERASEBKGND` handlers.** The architecture deliberately relies on OS + Scintilla painting; intercepting becomes a maintenance rabbit hole.
|
||||
- **Don't drop `WS_EX_COMPOSITED` from the main window on ARM64 without a replacement.** It is doing real work; the problem is the downstream invalidation traffic, not the flag itself.
|
||||
- **Don't add `DwmFlush()` calls.** Tempting but wrong — serializes against DWM at significant cost and typically hides the symptom rather than fixing it.
|
||||
|
||||
---
|
||||
|
||||
## 7. Bottom line
|
||||
|
||||
The dominant remaining contributor is almost certainly a **paste-driven cascade of secondary invalidations** (status bar with `bErase=TRUE`, double-composited surfaces, un-throttled `SCN_*` notifications) interacting with an already-fragile DWM path on Adreno + 25H2. The recent ARM64 fix (`WS_EX_COMPOSITED` + `DIRECTWRITERETAIN`) addressed the *Scintilla* side; what remains is the **peripheral paint traffic around each paste** that the parent composited buffer has to keep up with.
|
||||
|
||||
Cheapest first move: change the `TRUE` erase flag at `src/Notepad3.c:10833` to `FALSE`, and wrap `IDM_EDIT_PASTE` in `LimitNotifyEvents` / `RestoreNotifyEvents`. Those two together are ~5 lines and target the two most load-bearing suspects.
|
||||
|
||||
---
|
||||
|
||||
## Appendix A — Key files and line references
|
||||
|
||||
| Concern | File | Line(s) |
|
||||
|---|---|---|
|
||||
| ARM64 `WS_EX_COMPOSITED` on main window | `src/Notepad3.c` | 1914-1918 |
|
||||
| ARM64 default render technology | `src/Config/Config.cpp` | 1332-1338 |
|
||||
| Render-tech applied to Scintilla | `src/Notepad3.c` | 2578-2579 |
|
||||
| Render-tech runtime switch | `src/Notepad3.c` | 6701-6708 |
|
||||
| Render-tech INI load | `src/Config/Config.cpp` | 1826 |
|
||||
| `MsgThemeChanged` | `src/Notepad3.c` | 3432-3484 |
|
||||
| Status-bar creation (WS_EX_COMPOSITED) | `src/Notepad3.c` | 3314-3323 |
|
||||
| Status-bar update (erase TRUE) | `src/Notepad3.c` | 10818-10833 |
|
||||
| `IDM_EDIT_PASTE` handler | `src/Notepad3.c` | 5222-5231 |
|
||||
| `UndoTransActionBegin` / `EndUndoTransAction` | `src/Notepad3.h` | 188-189 |
|
||||
| `LimitNotifyEvents` / `RestoreNotifyEvents` | `src/Notepad3.h` | 182 |
|
||||
| `EnableDocChangeNotification` (post-modify callback) | `src/Notepad3.c` | 374-381 |
|
||||
| DarkMode redraw without `RDW_ERASE` | `src/DarkMode/ListViewUtil.hpp` | 64, 126 |
|
||||
| Undo-selection Redraw patch | `scintilla/np3_patches/upstream_558/001_undo_selection_redraw.patch` | — |
|
||||
|
||||
## Appendix B — Scintilla rendering technology constants
|
||||
|
||||
| Constant | Value | Underlying target | Swap model |
|
||||
|---|---|---|---|
|
||||
| `SC_TECHNOLOGY_DEFAULT` | 0 | GDI | `WM_PAINT` BitBlt |
|
||||
| `SC_TECHNOLOGY_DIRECTWRITE` | 1 | DXGI flip swap chain | Independent present |
|
||||
| `SC_TECHNOLOGY_DIRECTWRITERETAIN` | 2 | `ID2D1DCRenderTarget` + retain | Via GDI on `WM_PAINT` |
|
||||
| `SC_TECHNOLOGY_DIRECTWRITEDC` | 3 | `ID2D1DCRenderTarget` on caller DC | Via `WM_PAINT` DC |
|
||||
|
||||
---
|
||||
|
||||
## Appendix C — `SciCall_SetBufferedDraw` deep-dive
|
||||
|
||||
Follow-up investigation: could suspect F (Scintilla's own buffered-draw flag) be a useful ARM64-only lever? Answer: **no, not a promising path**. Detailed reasoning below, grounded in the vendored Scintilla sources under `scintilla/`.
|
||||
|
||||
### C.1 What the flag does
|
||||
|
||||
**Default value:** `true`, set in `EditView::EditView()` at `scintilla/src/EditView.cxx:186`.
|
||||
|
||||
**Upstream comment** (`scintilla/src/EditView.h:60-62`):
|
||||
|
||||
> "In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to the screen. This avoids flashing but is about 30% slower."
|
||||
|
||||
**Mechanism (GDI path):** when on, Scintilla allocates two persistent pixmaps per view (`Editor.cxx:1861-1866`):
|
||||
|
||||
- `pixmapLine` — width of the client area, height of one line
|
||||
- `pixmapSelMargin` — fixed-column width, full client height
|
||||
|
||||
In the paint loop, each line is drawn into `pixmapLine` and then `BitBlt`-ed onto the window DC (`EditView.cxx:2490-2614`, `SurfaceGDI.cxx:638-644`). When off, Scintilla draws directly to the window DC under an explicit `SetClip`/`PopClip` (`Editor.cxx:1910-1957`).
|
||||
|
||||
### C.2 The auto-override that kills this lever
|
||||
|
||||
Every `SCI_SETTECHNOLOGY` handler (`scintilla/win32/ScintillaWin.cxx:2280-2308`) forcibly assigns:
|
||||
|
||||
```cpp
|
||||
view.bufferedDraw = technologyNew == Technology::Default;
|
||||
```
|
||||
|
||||
Practical consequence:
|
||||
|
||||
| `SetTechnology` argument | `bufferedDraw` becomes |
|
||||
|---|---|
|
||||
| `SC_TECHNOLOGY_DEFAULT` (0, GDI) | `true` |
|
||||
| `SC_TECHNOLOGY_DIRECTWRITE` (1) | `false` |
|
||||
| `SC_TECHNOLOGY_DIRECTWRITERETAIN` (2) — **ARM64 default** | `false` |
|
||||
| `SC_TECHNOLOGY_DIRECTWRITEDC` (3) | `false` |
|
||||
|
||||
So any `SciCall_SetBufferedDraw(true)` we emit must come **after** `SciCall_SetTechnology`, and must be re-applied on every runtime tech switch (`Notepad3.c:6701-6708`), every `MsgThemeChanged`, and every `MsgDPIChanged` (the latter re-enters `MsgThemeChanged`).
|
||||
|
||||
### C.3 Benefits
|
||||
|
||||
- **GDI mode (0):** real benefit — per-line pixmap isolation reduces intra-line flicker. But already on by default, so Notepad3 does not need to touch it.
|
||||
- **D2D modes (1, 2, 3, 4):** the flag is technically wired (`SurfaceD2D::Copy` uses `pRenderTarget->DrawBitmap`, `SurfaceD2D.cxx:989-1000`), so forcing it on would allocate per-line D2D bitmap render targets. Functionally works, but adds a stage to the pipeline rather than eliminating one.
|
||||
- **None of these targets the actual ARM64 failure mode** (DWM compositor present misalignment between the parent composited buffer and Scintilla's D2D surface).
|
||||
|
||||
### C.4 Disadvantages
|
||||
|
||||
- **~30% slower paint** (upstream's own number).
|
||||
- **Extra GDI handles / D2D bitmaps** — two persistent pixmaps held per view, reallocated on every resize, tech change, or `DropGraphics()`.
|
||||
- **Silently clobbered** by every `SetTechnology` call — fragile to maintain.
|
||||
- **Adds a third buffer stage on ARM64.** Main window already has `WS_EX_COMPOSITED` (parent composited buffer) and Scintilla has its retained D2D target. Inserting a per-line Scintilla pixmap makes three stages of buffering competing for GPU bandwidth — plausibly worse on Adreno, not better.
|
||||
- **`WM_ERASEBKGND` is already suppressed** inside Scintilla's own wndproc (`ScintillaWin.cxx:2472-2473: return 1`), so the classical "avoid background flash" benefit is already paid for without this flag.
|
||||
|
||||
### C.5 Would ARM-gating `SciCall_SetBufferedDraw(true)` help?
|
||||
|
||||
Almost certainly not:
|
||||
|
||||
1. ARM64 default is `DIRECTWRITERETAIN`. Scintilla auto-disables `bufferedDraw` when that tech is set. Without re-applying after every `SetTechnology`, the call is a no-op.
|
||||
2. The reported symptom is compositor-present misalignment, not per-line paint cadence. Buffered draw operates at the paint-cadence layer and cannot influence DWM composition ordering.
|
||||
3. Adding a third buffer layer increases GPU work on a platform whose GPU/compositor pipeline is the root bottleneck.
|
||||
|
||||
### C.6 Verdict
|
||||
|
||||
Not pursued. The flag is a pre-DWM GDI-era flicker mitigation; it does not reach the layer where the ARM64 + 25H2 + Adreno symptom actually lives. Leverage points B and C remain the right next moves and are pursued in the code changes dated 2026-04-24.
|
||||
|
||||
### C.7 Key references
|
||||
|
||||
| Concern | File | Line(s) |
|
||||
|---|---|---|
|
||||
| `bufferedDraw` default = `true` | `scintilla/src/EditView.cxx` | 186 |
|
||||
| Auto-override on `SCI_SETTECHNOLOGY` | `scintilla/win32/ScintillaWin.cxx` | 2303 |
|
||||
| Pixmap allocation | `scintilla/src/Editor.cxx` | 1861-1866 |
|
||||
| GDI `BitBlt` copy | `scintilla/win32/SurfaceGDI.cxx` | 638-644 |
|
||||
| D2D `DrawBitmap` copy | `scintilla/win32/SurfaceD2D.cxx` | 989-1000 |
|
||||
| Clip branches on flag | `scintilla/src/Editor.cxx` | 1910-1957 |
|
||||
| Scintilla swallows `WM_ERASEBKGND` | `scintilla/win32/ScintillaWin.cxx` | 2472-2473 |
|
||||
|
||||
---
|
||||
|
||||
## Appendix D — Applied changes from leverage points B and E (2026-04-24)
|
||||
|
||||
After shipping leverage points A (status-bar erase flag) and the initial E wrap on `IDM_EDIT_PASTE`, the remaining paste sites and leverage point B were applied. Leverage point C was prepared but then reverted — see Appendix E.
|
||||
|
||||
**Leverage point B — un-nest `WS_EX_COMPOSITED` on ARM64** (`src/Notepad3.c:3314-3327`). The status bar drops its own `WS_EX_COMPOSITED` on ARM64 only; on that platform the main window already composites its children bottom-up, so the status bar's own flag only created a nested compositor stage. Non-ARM64 platforms retain the existing flag unchanged.
|
||||
|
||||
**Leverage point E extended — `LimitNotifyEvents` / `RestoreNotifyEvents` around all four `SciCall_Paste()` sites.** Same pattern as the earlier `IDM_EDIT_PASTE` change: collapse the `SCN_MODIFIED` / `SCN_UPDATEUI` burst into one end-of-paste invalidate. Scope matches the existing `UndoTransActionBegin` / `EndUndoTransAction` block exactly at each site; no wider refactoring.
|
||||
|
||||
| Site | File:Line | Trigger |
|
||||
|---|---|---|
|
||||
| `IDM_EDIT_PASTE` | `src/Notepad3.c:5233-5237` | Menu / Ctrl+V (shipped earlier) |
|
||||
| `EditSwapClipboard()` | `src/Edit.c:936-954` | `IDM_EDIT_SWAP` |
|
||||
| New-from-clipboard at startup | `src/Notepad3.c:2140-2148` | `/c` command-line flag |
|
||||
| `PasteBoardTimerProc()` | `src/Notepad3.c:12464-12499` | `/B` pasteboard-monitor mode, each clipboard change |
|
||||
|
||||
All four sites retain their `UndoTransActionBegin`/`EndUndoTransAction` undo grouping unchanged; the new macros wrap around the existing undo wrap.
|
||||
|
||||
---
|
||||
|
||||
## Appendix E — Leverage point C not applied as a default change (2026-04-24)
|
||||
|
||||
**Decision:** the ARM64 default rendering technology stays at `SC_TECHNOLOGY_DIRECTWRITERETAIN` (2). A brief switch to `SC_TECHNOLOGY_DIRECTWRITEDC` (3) was reverted on the same day.
|
||||
|
||||
**Rationale:**
|
||||
|
||||
1. The original recommendation in section 5 was to test mode 3 **as an INI-side experiment first**, then only promote it to default if the reporter confirmed improvement. Flipping the default without that validation skipped the decision gate.
|
||||
2. Project preference is to stay on D2D rendering paths. Although mode 3 still uses DirectWrite for glyph rendering, its presentation path (`ID2D1DCRenderTarget` blitting via GDI on `WM_PAINT`) is GDI-composed at the final stage. This is closer in character to the GDI mode (0) that is considered "not usable" than to modes 1 and 2, which use proper D2D render targets.
|
||||
3. `DIRECTWRITERETAIN` (2) remains the best compromise among the D2D-only options: it keeps the retained back buffer that mitigates the Adreno + 25H2 compositor misalignment, without routing the final stage through GDI.
|
||||
|
||||
**What this means for further investigation:**
|
||||
|
||||
- Mode 3 is *not* promoted to default.
|
||||
- It may still be tested ad-hoc by individual users via INI (`RenderingTechnology=3`) without a rebuild.
|
||||
- Next ARM64 levers to try while staying on D2D: the three deferred `SciCall_Paste` wrapping sites (`EditSwapClipboard` at `src/Edit.c:943,946`, startup `/c` at `src/Notepad3.c:2144`, `PasteBoardTimerProc` at `src/Notepad3.c:12488`); and possibly raising the clamp at `Config.cpp:1329` to expose `SC_TECHNOLOGY_DIRECT_WRITE_1` (4) as an experimental option.
|
||||
@ -933,6 +933,7 @@ bool EditSwapClipboard(HWND hwnd, bool bSkipUnicodeCheck)
|
||||
DocPos const iCurPos = SciCall_GetCurrentPos();
|
||||
DocPos const iAnchorPos = SciCall_GetAnchor();
|
||||
|
||||
LimitNotifyEvents();
|
||||
UndoTransActionBegin();
|
||||
|
||||
char* pszText = NULL;
|
||||
@ -950,6 +951,7 @@ bool EditSwapClipboard(HWND hwnd, bool bSkipUnicodeCheck)
|
||||
pszText = NULL;
|
||||
|
||||
EndUndoTransAction();
|
||||
RestoreNotifyEvents();
|
||||
|
||||
if (!Sci_IsMultiOrRectangleSelection()) {
|
||||
//~UndoTransActionBegin();
|
||||
|
||||
@ -2137,6 +2137,7 @@ HWND InitInstance(const HINSTANCE hInstance, int nCmdShow)
|
||||
bool bAutoIndent2 = Settings.AutoIndent;
|
||||
Settings.AutoIndent = 0;
|
||||
EditJumpTo(-1, 0);
|
||||
LimitNotifyEvents();
|
||||
UndoTransActionBegin();
|
||||
if (!Sci_IsDocEmpty()) {
|
||||
SciCall_NewLine();
|
||||
@ -2144,6 +2145,7 @@ HWND InitInstance(const HINSTANCE hInstance, int nCmdShow)
|
||||
SciCall_Paste();
|
||||
SciCall_NewLine();
|
||||
EndUndoTransAction();
|
||||
RestoreNotifyEvents();
|
||||
Settings.AutoIndent = bAutoIndent2;
|
||||
if (s_flagJumpTo) {
|
||||
SciCall_SetYCaretPolicy(s_iCaretPolicyV | CARET_JUMPS, Settings2.CurrentLineVerticalSlop);
|
||||
@ -3312,7 +3314,11 @@ void CreateBars(HWND hwnd, HINSTANCE hInstance)
|
||||
|
||||
//~Globals.hwndStatus = CreateStatusWindow(dwStatusbarStyle, NULL, hwnd, IDC_STATUSBAR);
|
||||
Globals.hwndStatus = CreateWindowEx(
|
||||
#if defined(_M_ARM64)
|
||||
0, // parent already has WS_EX_COMPOSITED on ARM64; avoid nested compositor stage
|
||||
#else
|
||||
WS_EX_COMPOSITED, // => double-buffering avoids flickering
|
||||
#endif
|
||||
STATUSCLASSNAME, // name of status bar class
|
||||
(PCTSTR)NULL, // no text when first created
|
||||
dwStatusbarStyle, // creates a visible child window
|
||||
@ -12455,6 +12461,7 @@ void CALLBACK PasteBoardTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD
|
||||
if (SciCall_CanPaste()) {
|
||||
bool bAutoIndent2 = Settings.AutoIndent;
|
||||
Settings.AutoIndent = 0;
|
||||
LimitNotifyEvents();
|
||||
UndoTransActionBegin();
|
||||
|
||||
// Paste at the current caret position. Pre-pend the configured
|
||||
@ -12489,6 +12496,7 @@ void CALLBACK PasteBoardTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD
|
||||
}
|
||||
SciCall_Paste();
|
||||
EndUndoTransAction();
|
||||
RestoreNotifyEvents();
|
||||
Sci_ScrollSelectionToView();
|
||||
Settings.AutoIndent = bAutoIndent2;
|
||||
s_dwLastPasteSeqNo = dwCurrentSeqNo;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user