Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

X11:无边框窗口逐帧 glfwSetWindowPos 拖动被 WM 钳制在屏幕内;Wayland 构建无法拖动

Aperta
#89 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 2 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
18/100
Tipo di issue
Funzionalità
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
cpp, linux
Ambito
desktop

Direzione di ricerca

Start with the public surface in include/eui/window.h and the core::window implementation, then trace how the title-bar drag currently calls glfwSetWindowPos each frame. The proposed beginWindowMove and beginWindowResize would need a per-backend implementation: X11 via _NET_WM_MOVERESIZE, with Wayland and Windows/macOS returning false. Done means beginWindowMove returns true on X11 so the app drops its own drag loop, while other backends return false and the existing per-frame fallback still works.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

X11:无边框窗口用逐帧 glfwSetWindowPos 拖动会被窗口管理器钳制在屏幕内;Wayland 构建则完全无法拖动

EUI-NEO v0.6.0-dev(ff1e757),bundled GLFW(GLFW_BUILD_X11=ON / GLFW_BUILD_WAYLAND=OFF),无边框窗口(.decorated(false))+ 自绘标题栏。Ubuntu 24.04,GNOME 46 Wayland 会话(XWayland),Mutter 46.2。

复现方式

使用 .decorated(false) 的应用按常规方式实现自绘标题栏拖动:

  1. 在标题栏按下时记录窗口原点与指针原点。
  2. 拖动过程中每帧调用 glfwSetWindowPos(window, startX + dx, startY + dy)。

预期:窗口跟随指针,并且和原生标题栏拖动一样可以拖出屏幕边缘(也能享受原生贴边分屏)。

实际:窗口只在完全位于工作区内时跟随指针;到达任意屏幕边缘就卡住,永远无法超出。同样的代码在原生 Wayland GLFW 构建下拖动完全无效。

根因

  • X11:glfwSetWindowPos 每帧发起 XMoveWindow,每次移动都以客户端 ConfigureRequest 形式到达窗口管理器。Mutter 将其视为非用户动作的配置请求,由 constrain_fully_onscreen(src/core/constraints.c,优先级 PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA)把位置推回可用显示器区域。该约束的豁免条件恰好解释了为什么 WM 原生拖动不受影响:info->is_user_action(交互式移动)、dock/desktop 窗口、全屏窗口。逐帧 XMoveWindow 循环在 WM 眼里不是用户动作,于是被钳制。
  • Wayland:客户端根本没有定位权限,_glfwSetWindowPosWayland 是文档化的 no-op(GLFW_FEATURE_UNAVAILABLE),这种拖动循环在原理上就不可能工作。唯一正确的机制是 xdg_toplevel.move。

所以这不是 GLFW 或 WM 的 bug,而是缺失的窗口能力:拥有自绘 chrome 的 EUI 应用没有任何途径把拖动交给合成器,而每个无边框应用要么接受边缘钳制,要么自己在应用层重写一遍 WM 协议代码。

建议方案

在 core::window 增加一个小能力,经 include/eui/window.h 暴露:

namespace eui::window {
// 请窗口管理器/合成器接管交互式移动/缩放。
// 当前平台/后端无法委托时返回 false,调用方保留自己的程序化回退。
bool beginWindowMove(Handle window);
bool beginWindowResize(Handle window, WindowResizeEdge edge);
}
  • GLFW/X11:向根窗口发送 EWMH _NET_WM_MOVERESIZE ClientMessage(direction 8 = MOVE,或对应 SIZE_* 方向;source indication 1 = application;指针根坐标用 XQueryPointer 获取),发送前按规范先释放按钮的隐式 grab。之后由 WM 执行交互式移动/缩放:无逐帧往返、允许部分拖出屏幕、原生吸附/分屏白拿。
  • GLFW/Wayland:xdg_toplevel.move/resize 需要按下时的 seat serial,只有后端内部持有。如果暂时拿不到,就返回 false 并在文档说明;X11 构建已经能拿到正确行为。
  • SDL2/X11:经 SDL_SysWMinfo 发送同一条消息。
  • Windows/macOS:返回 false(程序化循环在这些平台本来就可用)。

应用侧只需改一行:标题栏按下时调用 beginWindowMove,返回 true 就停用自己的拖动循环。

验收标准

  • GNOME / XWayland:无边框窗口按自绘标题栏拖动可以拖出屏幕边缘,并像原生拖动一样触发贴边分屏。
  • 自绘边缘拖手缩放同样委托给 WM。
  • 无法满足的平台/后端返回 false,既有逐帧回退保持可用。
  • 有边框窗口与非 Linux 平台行为不变。
Lingua principale
C++
Stelle
2k
Fork
177
Merge medio
19h 58m
PR unite (30g)
9

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di sudoevolve/EUI-NEO

Tutte le issue di sudoevolve/EUI-NEO

Issue simili

Altre issue su C++

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.