Modules/Graphics/public/WindowFrame.hpp
Шурупов Илья Викторович c06f12103e Replace GLFW with a native Wayland window backend
Graphics now talks to the compositor directly through wayland-client and
xdg-shell instead of GLFW and libdecor. Wayland is the only supported
platform for now.

Architecture:
- WaylandConnection binds the globals (xdg_wm_base, wl_seat, data device,
  viewporter, fractional scale, cursor shape, text-input-v3,
  xdg-decoration) and runs a prepared-read poll loop.
- WaylandWindow owns the surface and toplevel, applies configures
  (size, maximized, tiled, activated), fractional scale through a
  viewport, the window geometry and input region, and starts compositor
  move and resize.
- WaylandSeat handles the pointer (cursor shapes, wheel), the keyboard
  (xkbcommon keymap, compose, key repeat on a timerfd in the same poll),
  the clipboard and IME commits.
- VulkanContext no longer knows about the windowing system: a
  VulkanSurfaceSource supplies instance extensions, the surface and the
  framebuffer extent, and the swapchain switches to premultiplied alpha
  when the surface supports it.
- WindowInputDispatcher feeds EventHandler and input observers;
  ImGuiPlatform replaces imgui_impl_glfw on top of it, including
  cursors, clipboard and the IME rectangle.

The window draws its own frame. WindowFrame holds the geometry: a
transparent shadow margin around the content, rounded corners, an input
region and edge hit-testing for resizing. After the UI and ImGui, a
separate nanovg pass cuts the corners, strokes the outline and paints
the shadow behind the content. Maximized or tiled windows drop the
margin; without compositor alpha the window stays opaque and square but
still resizes from its edges.

Window gains minimize, toggleMaximize, beginMove, beginResize,
showWindowMenu, setCursor, clipboard and text input. Applications keep
their existing API.

Without libdecor, a resize configure reaches the next drawn frame in
1.9 ms median (3.6 ms worst) over a scripted maximize/restore loop;
animated frames stay paced at the display refresh and the idle gallery
uses about 1% of a core.
2026-10-14 22:35:53 +03:00

42 lines
1.3 KiB
C++

#pragma once
#include "Rect.hpp"
#include "WindowTypes.hpp"
namespace tp {
class WindowFrame {
public:
static constexpr halnf kShadowMargin = 18;
static constexpr halnf kCornerRadius = 12;
static constexpr halnf kResizeBorder = 10;
static constexpr halnf kMinimumInnerResizeBorder = 3;
static constexpr halnf kCornerResizeLength = 18;
void setContentSize(Vec2F size) { mContentSize = size; }
void setTiled(bool tiled) { mTiled = tiled; }
void setTranslucent(bool translucent) { mTranslucent = translucent; }
[[nodiscard]] Vec2F contentSize() const { return mContentSize; }
[[nodiscard]] bool isTiled() const { return mTiled; }
[[nodiscard]] bool isTranslucent() const { return mTranslucent; }
[[nodiscard]] bool hasShadow() const { return mTranslucent && !mTiled; }
[[nodiscard]] halnf margin() const { return hasShadow() ? kShadowMargin : 0; }
[[nodiscard]] halnf cornerRadius() const { return hasShadow() ? kCornerRadius : 0; }
[[nodiscard]] Vec2F surfaceSize() const;
[[nodiscard]] RectF contentRect() const;
[[nodiscard]] RectF inputRect() const;
[[nodiscard]] WindowEdge edgeAt(Vec2F surfacePoint) const;
private:
[[nodiscard]] halnf outerResizeBorder() const;
[[nodiscard]] halnf innerResizeBorder() const;
Vec2F mContentSize = { 0, 0 };
bool mTiled = false;
bool mTranslucent = true;
};
}