diff --git a/content/Hypr Ecosystem/_index.md b/content/Hypr Ecosystem/_index.md index 6cb35280..50fa9c80 100644 --- a/content/Hypr Ecosystem/_index.md +++ b/content/Hypr Ecosystem/_index.md @@ -28,6 +28,7 @@ These docs always target latest -git branch of respective apps. ### Libraries and other utilities +- **[hyprtoolkit](./hyprtoolkit)** - **[hyprcursor](./hyprcursor)** - **[hyprutils](./hyprutils)** - **[hyprlang](./hyprlang)** diff --git a/content/Hypr Ecosystem/hyprtoolkit/_index.md b/content/Hypr Ecosystem/hyprtoolkit/_index.md new file mode 100644 index 00000000..5b6cb658 --- /dev/null +++ b/content/Hypr Ecosystem/hyprtoolkit/_index.md @@ -0,0 +1,30 @@ +--- +weight: 100 +title: hyprtoolkit +--- + +Hyprtoolkit is a GUI toolkit for developing applications that run natively on Wayland. +It's specifically made for Hyprland's needs, but will generally run on any Wayland compositor +that supports modern standards. + +For developer docs, see [development](./development) + +## Configuration + +The general toolkit config is at `~/.config/hypr/hyprtoolkit.conf`. It contains theming and some minor adjustments. + +| variable | description | type | default | +| --- | --- | --- | --- | +| background | background color | color | FF181818 | +| base | base color | color | FF202020 | +| text | text color | color | FFDADADA | +| alternate_base | alternative base color | color | FF272727 | +| bright_text | bright text color | color | FFFFDEDE | +| accent | accent color | color | FF00FFCC | +| accent_secondary | secondary accent color | color | FF0099F0 | +| h1_size | font size for H1 | int | 19 | +| h2_size | font size for H2 | int | 15 | +| h3_size | font size for H3 | int | 13 | +| font_size | font size for regular text elements | int | 11 | +| small_font_size | font size for small text elements | int | 10 | +| icon_theme | name of the icon theme to use, empty for "the first found" | string | empty | diff --git a/content/Hypr Ecosystem/hyprtoolkit/development.md b/content/Hypr Ecosystem/hyprtoolkit/development.md new file mode 100644 index 00000000..212dcef2 --- /dev/null +++ b/content/Hypr Ecosystem/hyprtoolkit/development.md @@ -0,0 +1,133 @@ +--- +weight: 50 +title: Development +--- + +Hyprtoolkit is a pure C++ toolkit. It relies on modern C++ in the Hyprland style (with +hyprutils, etc). + +It's recommended you are familiar with C++ before developing an app. + +## Getting started + +_If you prefer living off of examples, see the `tests/` directory in the hyprtoolkit repo._ + +Start by creating a backend and opening a window: +```cpp +// in this example we are doing this to skip Hyprtoolkit:: +using namespace Hyprtoolkit; + +auto backend = CBackend::create(); +auto window = CWindowBuilder::begin()->appTitle("Hello")->appClass("hyprtoolkit")->commence(); +``` + +this will create (but not yet open) a window handle for you. + +Hyprtoolkit is a retained mode toolkit, so you can define your layout with C++ and forget about it. + +First thing we need is a background rectangle, by doing this: +```cpp +window->m_rootElement->addChild(CRectangleBuilder::begin()->color([] { return backend->getPalette()->m_colors.background; })->commence()); +``` +Remember to always use the palette when possible for your app to adhere to the user's theme. + +All elements are under `hyprtoolkit/elements/`, you can browse through them. Let's add a simple layout with +some buttons: + +```cpp +auto layout = CColumnLayoutBuilder::begin()->size({CDynamicSize::HT_SIZE_PERCENT, CDynamicSize::HT_SIZE_PERCENT, {1.F, 1.F}})->commence(); +layout->setMargin(3); + +window->m_rootElement->addChild(layout); + +layout->addChild(CButtonBuilder::begin() + ->label("Do something") + ->onMainClick([](SP el) { std::println("Did something!"); }) + ->size({CDynamicSize::HT_SIZE_AUTO, CDynamicSize::HT_SIZE_AUTO, {1, 1}}) + ->commence() + ); +layout->addChild(CButtonBuilder::begin() + ->label("Do something else") + ->onMainClick([](SP el) { std::println("Did something else!"); }) + ->size({CDynamicSize::HT_SIZE_AUTO, CDynamicSize::HT_SIZE_AUTO, {1, 1}}) + ->commence() + ); +``` + +This adds a column layout (elements are stacked on top of each other) with two buttons. These buttons have automatic sizing, so will fit their contents. + +Once you are done, add a close callback, open the window and enter the main loop: +```cpp +window->m_events.closeRequest.listenStatic([w = WP{window}] { + w->close(); + backend->destroy(); +}); + +window->open(); + +backend->enterLoop(); +``` + +## Layout system + +The layout system relies on absolute and layout positioning modes. Let's zoom into both: + +### Absolute mode + +This happens when the parent of your element is anything but a `ColumnLayout` or a `RowLayout`. Children are positioned within their parent, accoding to their +position mode. You can set it with `setPositionMode` and add offsets with `setAbsolutePosition`. + +For example: +- `setPositionMode` with `CENTER` will center the child inside the parent. +- `setPositionMode` with `ABSOLUTE` will make it be in the top left corner. +- Adding `setAbsolutePosition` to the above with `{200, 200}` will move it 200 layout px down and right from the top left corner of the parent. + +### Layout mode + +This happens when the parent of your element is a layout. These will attempt to position your child elements. They work similarly to CSS's `flex` and qt's `RowLayout` and `ColumnLayout`, +but will not wrap. If elements overflow and cannot shrink, they will disappear. + +RowLayout positions elements next to each other side-by-side, while ColumnLayout does it top-bottom. + +### Size + +All elements carry a `SizeType`. This tells the layout system how to size the element. +- `ABSOLUTE` takes layout px as size and makes the element rigid. +- `PERCENT` takes a percentage in the form of `(0, 0) - (1, 1)` and will be the size of the parent multiplied by the percentage. +- `AUTO` ignores the passed vector (leave it empty) and instead will always attempt to contain the children\* + +\*_Some elements will force their own sizing, like e.g. Text. Leave them AUTO to avoid confusion._ + +## Elements + +Most elements are self-explanatory. You can explore their builder fns to see what styling / behavior options they +support. + +Each element is created with a `Builder` which is there to maintain ABI stability. After you call `->commence()`, you +will get a `SP` to the newly created object. + +You can rebuild the object at any time by calling `->rebuild()` and you'll get a builder again. +**Remember to call `commence()` after you are done to apply the changes!** + +You do not need to keep the `SP` after adding the element to the tree with `addChild`. + +## Other + +Other, miscellaneous stuff + +### System icons + +Use the `CBackend::systemIcons()` fn to obtain a ref to `ISystemIconFactory` which allows +you to query system icons by name. You can check the obtained result object for seeing if the icon was found. + +Then, you can take that object and slap it into an `ImageElement` to add it to your layout. + +### Additional FDs + +If you have an app that depends on some other loop, e.g. pipewire, dbus, etc. You need to remember +that hyprtoolkit is strictly single-threaded for layout and rendering. You cannot edit the layout from another thread. + +For this, use `CBackend::addFd()` to add a FD to the loop alongside a function that will be called once the fd +is readable. This fn will be called from the main thread, so you can do whatever you want in there. + +