mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-07-30 19:51:55 -07:00
Compare commits
52 Commits
v0.2.0beta
...
v0.3.0beta
Author | SHA1 | Date | |
---|---|---|---|
|
f99ad521a4 | ||
|
9486a230c7 | ||
|
6f3b004199 | ||
|
19b17b590c | ||
|
f9c8a72e46 | ||
|
e11cb8b328 | ||
|
7b568d7ad8 | ||
|
a2f718059b | ||
|
feb0499597 | ||
|
601abc7e92 | ||
|
7451890fd7 | ||
|
f5cdb5b95e | ||
|
7afcf656bd | ||
|
6daa866beb | ||
|
9447fcd603 | ||
|
9acf15efd7 | ||
|
b5a100379e | ||
|
4f76d5d8d7 | ||
|
8d850b0ce1 | ||
|
0f28d2ae55 | ||
|
d2451aea4b | ||
|
680705ff91 | ||
|
300fc2ab0f | ||
|
02210d3d96 | ||
|
879345c1e9 | ||
|
1e3bea5e70 | ||
|
f64cae2b7f | ||
|
c433b14e3d | ||
|
8d1c495878 | ||
|
4264a0b08d | ||
|
40ab062a3c | ||
|
35bcea38e3 | ||
|
1ccb944509 | ||
|
c600249aee | ||
|
6d6e967a8d | ||
|
970018248f | ||
|
f6b8a96621 | ||
|
8e8d5a99c2 | ||
|
471654d791 | ||
|
679e36d82e | ||
|
0f8712ed64 | ||
|
3e28a8b690 | ||
|
8de7cc5a8d | ||
|
e73df80782 | ||
|
0d7131d30e | ||
|
d2e0b7c22a | ||
|
c1193ee483 | ||
|
042e79b888 | ||
|
0055efc4f1 | ||
|
df722cbb86 | ||
|
68f7e565e6 | ||
|
48a3b1c514 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -13,6 +13,6 @@ assignees: ''
|
||||
**Images/videos/anything that would help**
|
||||
|
||||
|
||||
Please attach a log (it's in /tmp/hypr/hyprland.log) and, if crashing, a crashdump (coredumpctl, then coredumpctl info <pid>)
|
||||
Please attach a log (it's in /tmp/hypr/[INSTANCE SIGNATURE]/hyprland.log, if you are unsure of the instance signature, grab the one thats the most recently modified) and, if crashing, a crashdump (coredumpctl, then coredumpctl info <pid>)
|
||||
|
||||
*Please do NOT attach coredumps from any packaged version of Hyprland (AUR, etc.). Compile manually, and THEN attach a coredump of that.*
|
||||
|
7
.github/workflows/nix-update.yaml
vendored
7
.github/workflows/nix-update.yaml
vendored
@@ -1,9 +1,6 @@
|
||||
name: "Nix: update lockfile"
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 */14 * *'
|
||||
workflow_dispatch:
|
||||
on: [push, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
update:
|
||||
@@ -19,7 +16,7 @@ jobs:
|
||||
auto-optimise-store = true
|
||||
experimental-features = nix-command flakes
|
||||
- name: Update lockfile
|
||||
run: nix flake update
|
||||
run: nix/update-inputs.sh
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: "[gha] bump flake inputs"
|
||||
|
2
Makefile
2
Makefile
@@ -126,4 +126,4 @@ config:
|
||||
cd wlroots && meson ./build --prefix=/usr --buildtype=release
|
||||
cd wlroots && ninja -C build/
|
||||
|
||||
cd wlroots && sudo cp ./build/libwlroots.so.11032 /usr/lib/
|
||||
cd wlroots && sudo ninja -C build/ install
|
||||
|
18
README.md
18
README.md
@@ -37,10 +37,9 @@ For Hyprland without the `land` part, see [Hypr], the Xorg window manager.
|
||||
|
||||
# Notice
|
||||
|
||||
This project is still in its early development, expect bugs.
|
||||
|
||||
Once you get it working though, it's pretty stable.<br/>
|
||||
Hyprland is still in pretty early development compared to some other Wayland compositors.
|
||||
|
||||
Although Hyprland is pretty stable, it may have some bugs.
|
||||
|
||||
### Help Wanted
|
||||
|
||||
@@ -51,17 +50,20 @@ Try it out and report bugs / suggestions!
|
||||
|
||||
- Easily expandable and readable codebase
|
||||
- Config reloaded instantly upon saving
|
||||
- Bezier-curve window animations
|
||||
- Custom bezier curve based animations
|
||||
- Workspaces protocol support
|
||||
- wlr_ext workspaces protocol support
|
||||
- Dual Kawase blur
|
||||
- Window fade in / out
|
||||
- Fully dynamic workspaces
|
||||
- Closely follows wlroots-git
|
||||
- Bundled wlroots
|
||||
- Window / layer fade in / out
|
||||
- Tiling / floating / fullscreen windows
|
||||
- Special Workspace (Scratchpad)
|
||||
- Window / monitor rules
|
||||
- Socket-based IPC
|
||||
- Event System for bash scripts
|
||||
- Rounded corners
|
||||
- Damage tracking ( *Experimental* )
|
||||
- Moving / resizing
|
||||
- Full Damage tracking
|
||||
- Docks support
|
||||
|
||||
<br>
|
||||
|
47
aur/PKGBUILD
47
aur/PKGBUILD
@@ -2,20 +2,59 @@
|
||||
|
||||
_pkgname="hyprland"
|
||||
pkgname="${_pkgname}"
|
||||
pkgver="0.1.1beta"
|
||||
pkgrel=2
|
||||
pkgver="0.2.2beta"
|
||||
pkgrel=3
|
||||
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
|
||||
arch=(any)
|
||||
url="https://github.com/vaxerski/Hyprland"
|
||||
license=('BSD')
|
||||
depends=(libxcb xcb-proto xcb-util xcb-util-keysyms libxfixes libx11 libxcomposite xorg-xinput libxrender pixman wayland-protocols wlroots-git cairo pango)
|
||||
makedepends=(git cmake ninja gcc gdb)
|
||||
depends=(
|
||||
libxcb
|
||||
xcb-proto
|
||||
xcb-util
|
||||
xcb-util-keysyms
|
||||
libxfixes
|
||||
libx11
|
||||
libxcomposite
|
||||
xorg-xinput
|
||||
libxrender
|
||||
pixman
|
||||
wayland-protocols
|
||||
cairo
|
||||
pango
|
||||
polkit
|
||||
glslang
|
||||
libinput
|
||||
libxcb
|
||||
libxkbcommon
|
||||
opengl-driver
|
||||
pixman
|
||||
wayland
|
||||
xcb-util-errors
|
||||
xcb-util-renderutil
|
||||
xcb-util-wm
|
||||
seatd
|
||||
vulkan-icd-loader
|
||||
vulkan-validation-layers
|
||||
xorg-xwayland)
|
||||
makedepends=(
|
||||
git
|
||||
cmake
|
||||
ninja
|
||||
gcc
|
||||
gdb
|
||||
meson
|
||||
vulkan-headers
|
||||
wayland-protocols
|
||||
xorgproto)
|
||||
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/vaxerski/hyprland/archive/v${pkgver}.tar.gz")
|
||||
sha256sums=('SKIP')
|
||||
conflicts=("${_pkgname}-git" "${_pkgname}" "${_pkgname}-bin")
|
||||
options=(!makeflags !buildflags)
|
||||
|
||||
build() {
|
||||
cd "$srcdir/Hyprland-$pkgver"
|
||||
git submodule update --init
|
||||
make all
|
||||
}
|
||||
|
||||
|
55
aur/PKGBUILD-bin
Normal file
55
aur/PKGBUILD-bin
Normal file
@@ -0,0 +1,55 @@
|
||||
# Maintainer: ThatOneCalculator <kainoa@t1c.dev>
|
||||
|
||||
_pkgname="hyprland"
|
||||
pkgname="${_pkgname}-bin"
|
||||
pkgver="0.2.2beta"
|
||||
pkgrel=3
|
||||
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
|
||||
arch=(any)
|
||||
url="https://github.com/vaxerski/Hyprland"
|
||||
license=('BSD')
|
||||
depends=(
|
||||
libxcb
|
||||
xcb-proto
|
||||
xcb-util
|
||||
xcb-util-keysyms
|
||||
libxfixes
|
||||
libx11
|
||||
libxcomposite
|
||||
xorg-xinput
|
||||
libxrender
|
||||
pixman
|
||||
wayland-protocols
|
||||
cairo
|
||||
pango
|
||||
polkit
|
||||
glslang
|
||||
libinput
|
||||
libxcb
|
||||
libxkbcommon
|
||||
opengl-driver
|
||||
pixman
|
||||
wayland
|
||||
xcb-util-errors
|
||||
xcb-util-renderutil
|
||||
xcb-util-wm
|
||||
seatd
|
||||
vulkan-icd-loader
|
||||
vulkan-validation-layers
|
||||
xorg-xwayland)
|
||||
source=("${pkgname}-${pkgver}.tar.gz::https://github.com/vaxerski/Hyprland/releases/download/v${pkgver}/v${pkgver}.tar.gz")
|
||||
sha256sums=('SKIP')
|
||||
conflicts=("${_pkgname}-git" "${_pkgname}" "${_pkgname}-bin")
|
||||
|
||||
package() {
|
||||
cd "$srcdir/Hyprland-$pkgver"
|
||||
mkdir -p "${pkgdir}/usr/share/wayland-sessions"
|
||||
mkdir -p "${pkgdir}/usr/share/hyprland"
|
||||
install -Dm755 ./Hyprland -t "${pkgdir}/usr/bin"
|
||||
install -Dm755 ./hyprctl -t "${pkgdir}/usr/bin"
|
||||
install -Dm755 ./libwlroots.so.11032 -t "${pkgdir}/usr/lib"
|
||||
install -Dm644 assets/*.png -t "${pkgdir}/usr/share/hyprland"
|
||||
install -Dm644 example/hyprland.desktop -t "${pkgdir}/usr/share/wayland-sessions"
|
||||
install -Dm644 example/hyprland.conf -t "${pkgdir}/usr/share/hyprland"
|
||||
install -Dm644 LICENSE -t "${pkgdir}/usr/share/licenses/${_pkgname}"
|
||||
}
|
@@ -2,15 +2,53 @@
|
||||
|
||||
_pkgname="hyprland"
|
||||
pkgname="${_pkgname}-git"
|
||||
pkgver=r568.g632d00c
|
||||
pkgrel=1
|
||||
pkgver=r615.g119e776
|
||||
pkgrel=4
|
||||
pkgdesc="Hyprland is a dynamic tiling Wayland compositor based on wlroots that doesn't sacrifice on its looks."
|
||||
arch=(any)
|
||||
url="https://github.com/vaxerski/Hyprland"
|
||||
license=('BSD')
|
||||
depends=(libxcb xcb-proto xcb-util xcb-util-keysyms libxfixes libx11 libxcomposite xorg-xinput libxrender pixman wayland-protocols wlroots-git cairo pango)
|
||||
makedepends=(git cmake ninja gcc gdb)
|
||||
depends=(
|
||||
libxcb
|
||||
xcb-proto
|
||||
xcb-util
|
||||
xcb-util-keysyms
|
||||
libxfixes
|
||||
libx11
|
||||
libxcomposite
|
||||
xorg-xinput
|
||||
libxrender
|
||||
pixman
|
||||
wayland-protocols
|
||||
cairo
|
||||
pango
|
||||
polkit
|
||||
glslang
|
||||
libinput
|
||||
libxcb
|
||||
libxkbcommon
|
||||
opengl-driver
|
||||
pixman
|
||||
wayland
|
||||
xcb-util-errors
|
||||
xcb-util-renderutil
|
||||
xcb-util-wm
|
||||
seatd
|
||||
vulkan-icd-loader
|
||||
vulkan-validation-layers
|
||||
xorg-xwayland)
|
||||
makedepends=(
|
||||
git
|
||||
cmake
|
||||
ninja
|
||||
gcc
|
||||
gdb
|
||||
meson
|
||||
vulkan-headers
|
||||
wayland-protocols
|
||||
xorgproto)
|
||||
source=("${_pkgname}::git+https://github.com/vaxerski/Hyprland.git")
|
||||
conflicts=("${_pkgname}-git" "${_pkgname}" "${_pkgname}-bin")
|
||||
sha256sums=('SKIP')
|
||||
options=(!makeflags !buildflags)
|
||||
|
||||
@@ -24,6 +62,7 @@ pkgver() {
|
||||
|
||||
build() {
|
||||
cd "${srcdir}/${_pkgname}"
|
||||
git submodule update --init
|
||||
make all
|
||||
}
|
||||
|
||||
|
@@ -27,7 +27,7 @@ general {
|
||||
col.active_border=0x66ee1111
|
||||
col.inactive_border=0x66333333
|
||||
|
||||
damage_tracking=full # experimental, monitor is 100% fine, but full might have some minor bugs, especially with high blur settings!
|
||||
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
|
||||
}
|
||||
|
||||
decoration {
|
||||
|
12
flake.lock
generated
12
flake.lock
generated
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1653581809,
|
||||
"narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=",
|
||||
"lastModified": 1653931853,
|
||||
"narHash": "sha256-O3wncIouj9x7gBPntzHeK/Hkmm9M1SGlYq7JI7saTAE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "83658b28fe638a170a19b8933aa008b30640fbd1",
|
||||
"rev": "f1c167688a6f81f4a51ab542e5f476c8c595e457",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -26,11 +26,11 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1653733431,
|
||||
"narHash": "sha256-0JwNH2E9XlMVa7ZCsqxazpKwpZ2rW5QQjbk0DdZxa48=",
|
||||
"lastModified": 1653658290,
|
||||
"narHash": "sha256-zZaona39DOZNL93A1KG3zAi8vDttJBirxacq24hWCn4=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "93ee4c7684050807e959bb3b6d57826a72fba8c2",
|
||||
"rev": "75d31509db8c28e8379fe9570118ef8c82284581",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -36,7 +36,7 @@
|
||||
version = mkVersion inputs.wlroots.lastModifiedDate;
|
||||
src = inputs.wlroots;
|
||||
});
|
||||
default = pkgsFor.${system}.callPackage ./default.nix {
|
||||
default = pkgsFor.${system}.callPackage ./nix/default.nix {
|
||||
version = mkVersion self.lastModifiedDate;
|
||||
inherit (self.packages.${system}) wlroots;
|
||||
};
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
formatter = genSystems (system: pkgsFor.${system}.alejandra);
|
||||
|
||||
nixosModules.default = import ./module.nix self;
|
||||
nixosModules.default = import ./nix/module.nix self;
|
||||
|
||||
# Deprecated
|
||||
overlays.default = _: prev: {
|
||||
|
@@ -23,6 +23,7 @@ usage: hyprctl [command] [(opt)args]
|
||||
clients
|
||||
activewindow
|
||||
layers
|
||||
devices
|
||||
dispatch
|
||||
keyword
|
||||
version
|
||||
@@ -44,12 +45,25 @@ void request(std::string arg) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get the instance signature
|
||||
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||
|
||||
if (!instanceSig) {
|
||||
std::cout << "HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string instanceSigStr = std::string(instanceSig);
|
||||
|
||||
sockaddr_un serverAddress = {0};
|
||||
serverAddress.sun_family = AF_UNIX;
|
||||
strcpy(serverAddress.sun_path, "/tmp/hypr/.socket.sock");
|
||||
|
||||
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.socket.sock";
|
||||
|
||||
strcpy(serverAddress.sun_path, socketPath.c_str());
|
||||
|
||||
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
||||
std::cout << "Couldn't connect to /tmp/hypr/.socket.sock. (3) Is Hyprland running?";
|
||||
std::cout << "Couldn't connect to " << socketPath << ". (3)";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -117,6 +131,7 @@ int main(int argc, char** argv) {
|
||||
else if (!strcmp(argv[1], "activewindow")) request("activewindow");
|
||||
else if (!strcmp(argv[1], "layers")) request("layers");
|
||||
else if (!strcmp(argv[1], "version")) request("version");
|
||||
else if (!strcmp(argv[1], "devices")) request("devices");
|
||||
else if (!strcmp(argv[1], "reload")) request("reload");
|
||||
else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv);
|
||||
else if (!strcmp(argv[1], "keyword")) keywordRequest(argc, argv);
|
||||
|
@@ -24,7 +24,7 @@
|
||||
stdenv.mkDerivation {
|
||||
pname = "hyprland";
|
||||
inherit version;
|
||||
src = ./.;
|
||||
src = ../.;
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
@@ -52,8 +52,12 @@ stdenv.mkDerivation {
|
||||
["-DCMAKE_BUILD_TYPE=Release"]
|
||||
++ lib.optional (!enableXWayland) "-DNO_XWAYLAND=true";
|
||||
|
||||
# enables building with nix-supplied wlroots instead of submodule
|
||||
prePatch = ''
|
||||
make config
|
||||
sed -Ei 's/"\.\.\/wlroots\/include\/([a-zA-Z0-9./_-]+)"/<\1>/g' src/includes.hpp
|
||||
'';
|
||||
postPatch = ''
|
||||
make protocols
|
||||
'';
|
||||
|
||||
postBuild = ''
|
19
nix/update-inputs.sh
Executable file
19
nix/update-inputs.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#moreutils nixpkgs#jq -c bash
|
||||
|
||||
# get wlroots revision from submodule
|
||||
SUB_REV=$(git submodule status | awk '{ print substr($1,2)}')
|
||||
# and from lockfile
|
||||
CRT_REV=$(jq < flake.lock '.nodes.wlroots.locked.rev' -r)
|
||||
|
||||
if [ $SUB_REV != $CRT_REV ]; then
|
||||
# update nixpkgs to latest version
|
||||
nix flake lock --update-input nixpkgs
|
||||
|
||||
# update wlroots to submodule revision
|
||||
nix flake lock --override-input wlroots "gitlab:wlroots/wlroots/$SUB_REV?host=gitlab.freedesktop.org"
|
||||
|
||||
# remove "dirty" mark from lockfile
|
||||
jq < flake.lock 'del(.nodes.wlroots.original.rev)' | sponge flake.lock
|
||||
else
|
||||
echo "wlroots is up to date!"
|
||||
fi
|
@@ -1,11 +1,16 @@
|
||||
#include "Compositor.hpp"
|
||||
|
||||
CCompositor::CCompositor() {
|
||||
unlink("/tmp/hypr/hyprland.log");
|
||||
unlink("/tmp/hypr/hyprlandd.log");
|
||||
unlink("/tmp/hypr/.hyprlandrq");
|
||||
m_szInstanceSignature = GIT_COMMIT_HASH + std::string("_") + std::to_string(time(NULL));
|
||||
|
||||
system("mkdir -p /tmp/hypr");
|
||||
Debug::init(m_szInstanceSignature);
|
||||
|
||||
Debug::log(LOG, "Instance Signature: %s", m_szInstanceSignature.c_str());
|
||||
|
||||
setenv("HYPRLAND_INSTANCE_SIGNATURE", m_szInstanceSignature.c_str(), true);
|
||||
|
||||
const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature;
|
||||
mkdir(INSTANCEPATH.c_str(), S_IRWXU | S_IRWXG);
|
||||
|
||||
m_sWLDisplay = wl_display_create();
|
||||
|
||||
@@ -314,6 +319,15 @@ bool CCompositor::windowExists(CWindow* pWindow) {
|
||||
|
||||
CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
||||
const auto PMONITOR = getMonitorFromVector(pos);
|
||||
|
||||
if (PMONITOR->specialWorkspaceOpen) {
|
||||
for (auto& w : m_lWindows) {
|
||||
wlr_box box = {w.m_vRealPosition.vec().x, w.m_vRealPosition.vec().y, w.m_vRealSize.vec().x, w.m_vRealSize.vec().y};
|
||||
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_bIsMapped && !w.m_bIsFloating && !w.m_bHidden)
|
||||
return &w;
|
||||
}
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
@@ -332,6 +346,15 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
||||
|
||||
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
||||
const auto PMONITOR = getMonitorFromVector(pos);
|
||||
|
||||
if (PMONITOR->specialWorkspaceOpen) {
|
||||
for (auto& w : m_lWindows) {
|
||||
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
||||
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bIsFloating && !w.m_bHidden)
|
||||
return &w;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& w : m_lWindows) {
|
||||
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
||||
if (w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w.m_iWorkspaceID == PMONITOR->activeWorkspace && !w.m_bIsFloating && !w.m_bHidden)
|
||||
@@ -343,6 +366,16 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
||||
|
||||
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
const auto PMONITOR = getMonitorFromVector(pos);
|
||||
|
||||
// special workspace
|
||||
if (PMONITOR->specialWorkspaceOpen) {
|
||||
for (auto& w : m_lWindows) {
|
||||
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
||||
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && w.m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w.m_bHidden)
|
||||
return &w;
|
||||
}
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
@@ -362,6 +395,14 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
CWindow* CCompositor::windowFromCursor() {
|
||||
const auto PMONITOR = getMonitorFromCursor();
|
||||
|
||||
if (PMONITOR->specialWorkspaceOpen) {
|
||||
for (auto& w : m_lWindows) {
|
||||
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
|
||||
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w.m_bIsMapped)
|
||||
return &w;
|
||||
}
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto w = m_lWindows.rbegin(); w != m_lWindows.rend(); w++) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
@@ -576,6 +617,9 @@ bool CCompositor::isWorkspaceVisible(const int& w) {
|
||||
for (auto& m : m_lMonitors) {
|
||||
if (m.activeWorkspace == w)
|
||||
return true;
|
||||
|
||||
if (m.specialWorkspaceOpen && w == SPECIAL_WORKSPACE_ID)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -595,6 +639,14 @@ void CCompositor::sanityCheckWorkspaces() {
|
||||
if ((getWindowsOnWorkspace(it->m_iID) == 0 && !isWorkspaceVisible(it->m_iID))) {
|
||||
it = m_lWorkspaces.erase(it);
|
||||
}
|
||||
|
||||
if (it->m_iID == SPECIAL_WORKSPACE_ID && getWindowsOnWorkspace(it->m_iID) == 0) {
|
||||
for (auto& m : m_lMonitors) {
|
||||
m.specialWorkspaceOpen = false;
|
||||
}
|
||||
|
||||
it = m_lWorkspaces.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1006,8 +1058,9 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMoni
|
||||
|
||||
if (SWITCHINGISACTIVE) { // if it was active, preserve its' status. If it wasn't, don't.
|
||||
Debug::log(LOG, "moveWorkspaceToMonitor: SWITCHINGISACTIVE, active %d -> %d", pMonitor->activeWorkspace, pWorkspace->m_iID);
|
||||
|
||||
getWorkspaceByID(pMonitor->activeWorkspace)->startAnim(false, false);
|
||||
|
||||
if (const auto PWORKSPACE = getWorkspaceByID(pMonitor->activeWorkspace); PWORKSPACE)
|
||||
getWorkspaceByID(pMonitor->activeWorkspace)->startAnim(false, false);
|
||||
|
||||
pMonitor->activeWorkspace = pWorkspace->m_iID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(pMonitor->ID);
|
||||
@@ -1021,4 +1074,19 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, SMonitor* pMoni
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
|
||||
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
|
||||
bool CCompositor::workspaceIDOutOfBounds(const int& id) {
|
||||
int lowestID = 99999;
|
||||
int highestID = -99999;
|
||||
|
||||
for (auto& w : m_lWorkspaces) {
|
||||
if (w.m_iID < lowestID)
|
||||
lowestID = w.m_iID;
|
||||
|
||||
if (w.m_iID > highestID)
|
||||
highestID = w.m_iID;
|
||||
}
|
||||
|
||||
return std::clamp(id, lowestID, highestID) != id;
|
||||
}
|
@@ -63,6 +63,7 @@ public:
|
||||
|
||||
|
||||
const char* m_szWLDisplaySocket;
|
||||
std::string m_szInstanceSignature = "";
|
||||
|
||||
std::list<SMonitor> m_lMonitors;
|
||||
std::list<CWindow> m_lWindows;
|
||||
@@ -129,6 +130,7 @@ public:
|
||||
void moveWindowToWorkspace(CWindow*, const std::string&);
|
||||
int getNextAvailableMonitorID();
|
||||
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
|
||||
bool workspaceIDOutOfBounds(const int&);
|
||||
|
||||
private:
|
||||
void initAllSignals();
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
struct SWindowSpecialRenderData {
|
||||
float alpha = 1.f;
|
||||
float alphaInactive = -1.f; // -1 means unset
|
||||
};
|
||||
|
||||
struct SWindowAdditionalConfigData {
|
||||
|
@@ -45,6 +45,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["decoration:active_opacity"].floatValue = 1;
|
||||
configValues["decoration:inactive_opacity"].floatValue = 1;
|
||||
configValues["decoration:fullscreen_opacity"].floatValue = 1;
|
||||
configValues["decoration:multisample_edges"].intValue = 0;
|
||||
|
||||
configValues["dwindle:pseudotile"].intValue = 0;
|
||||
configValues["dwindle:col.group_border"].intValue = 0x66777700;
|
||||
@@ -80,6 +81,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["input:repeat_rate"].intValue = 25;
|
||||
configValues["input:repeat_delay"].intValue = 600;
|
||||
configValues["input:natural_scroll"].intValue = 0;
|
||||
configValues["input:numlock_by_default"].intValue = 0;
|
||||
configValues["input:touchpad:disable_while_typing"].intValue = 1;
|
||||
|
||||
configValues["input:follow_mouse"].intValue = 1;
|
||||
|
@@ -34,7 +34,7 @@ general {
|
||||
col.active_border=0x66ee1111
|
||||
col.inactive_border=0x66333333
|
||||
|
||||
damage_tracking=full # experimental, monitor is 100% fine, but full might have some minor bugs, especially with high blur settings!
|
||||
damage_tracking=full # leave it on full unless you hate your GPU and want to make it suffer
|
||||
}
|
||||
|
||||
decoration {
|
||||
|
@@ -26,7 +26,7 @@ std::string monitorsRequest() {
|
||||
std::string clientsRequest() {
|
||||
std::string result = "";
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i, %i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\n",
|
||||
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\n",
|
||||
&w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().y, w.m_iWorkspaceID, (w.m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID)->m_szName.c_str()), (int)w.m_bIsFloating, w.m_iMonitorID);
|
||||
}
|
||||
return result;
|
||||
@@ -47,7 +47,7 @@ std::string activeWindowRequest() {
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return "Invalid";
|
||||
|
||||
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i, %i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\n",
|
||||
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\n",
|
||||
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,24 @@ std::string layersRequest() {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string devicesRequest() {
|
||||
std::string result = "";
|
||||
|
||||
result += "mice:\n";
|
||||
|
||||
for (auto& m : g_pInputManager->m_lMice) {
|
||||
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
|
||||
}
|
||||
|
||||
result += "\n\nKeyboards:\n";
|
||||
|
||||
for (auto& k : g_pInputManager->m_lKeyboards) {
|
||||
result += getFormat("\tKeyboard at %x:\n\t\t%s\n", &k, k.keyboard->name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string versionRequest() {
|
||||
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + GIT_DIRTY + " (" + GIT_COMMIT_MESSAGE + ").\nflags: (if any)\n";
|
||||
|
||||
@@ -186,6 +204,8 @@ std::string getReply(std::string request) {
|
||||
return versionRequest();
|
||||
else if (request == "reload")
|
||||
return reloadRequest();
|
||||
else if (request == "devices")
|
||||
return devicesRequest();
|
||||
else if (request.find("dispatch") == 0)
|
||||
return dispatchRequest(request);
|
||||
else if (request.find("keyword") == 0)
|
||||
@@ -246,11 +266,11 @@ void HyprCtl::startHyprCtlSocket() {
|
||||
return;
|
||||
}
|
||||
|
||||
unlink("/tmp/hypr/.socket.sock");
|
||||
|
||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||
|
||||
strcpy(SERVERADDRESS.sun_path, "/tmp/hypr/.socket.sock");
|
||||
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket.sock";
|
||||
|
||||
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||
|
||||
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
||||
|
||||
@@ -262,7 +282,7 @@ void HyprCtl::startHyprCtlSocket() {
|
||||
|
||||
char readBuffer[1024] = {0};
|
||||
|
||||
Debug::log(LOG, "Hypr socket started.");
|
||||
Debug::log(LOG, "Hypr socket started at %s", socketPath.c_str());
|
||||
|
||||
while(1) {
|
||||
const auto ACCEPTEDCONNECTION = accept(SOCKET, (sockaddr*)&clientAddress, &clientSize);
|
||||
|
@@ -1,15 +1,22 @@
|
||||
#include "Log.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
void Debug::init(std::string IS) {
|
||||
if (ISDEBUG)
|
||||
logFile = "/tmp/hypr/" + IS + "/hyprlandd.log";
|
||||
else
|
||||
logFile = "/tmp/hypr/" + IS + "/hyprland.log";
|
||||
}
|
||||
|
||||
void Debug::log(LogLevel level, const char* fmt, ...) {
|
||||
|
||||
// log to a file
|
||||
const std::string DEBUGPATH = ISDEBUG ? "/tmp/hypr/hyprlandd.log" : "/tmp/hypr/hyprland.log";
|
||||
std::ofstream ofs;
|
||||
ofs.open(DEBUGPATH, std::ios::out | std::ios::app);
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
|
||||
switch (level) {
|
||||
case LOG:
|
||||
|
@@ -12,5 +12,8 @@ enum LogLevel {
|
||||
};
|
||||
|
||||
namespace Debug {
|
||||
void init(std::string IS);
|
||||
void log(LogLevel level, const char* fmt, ...);
|
||||
|
||||
inline std::string logFile;
|
||||
};
|
@@ -64,4 +64,6 @@
|
||||
#endif
|
||||
#ifndef GIT_DIRTY
|
||||
#define GIT_DIRTY "?"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define SPECIAL_WORKSPACE_ID -99
|
@@ -160,6 +160,12 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
geomFixed = {layersurface->geometry.x, layersurface->geometry.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
|
||||
layersurface->geometry = geomFixed; // because the surface can overflow... for some reason?
|
||||
}
|
||||
|
||||
void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||
|
@@ -65,6 +65,10 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
if (monitorRule.disabled) {
|
||||
wlr_output_enable(OUTPUT, 0);
|
||||
wlr_output_commit(OUTPUT);
|
||||
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromName(std::string(OUTPUT->name)); PMONITOR) {
|
||||
listener_monitorDestroy(nullptr, PMONITOR->output);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -110,18 +114,27 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
wlr_ext_workspace_group_handle_v1_output_enter(PNEWMONITOR->pWLRWorkspaceGroupHandle, PNEWMONITOR->output);
|
||||
|
||||
// Workspace
|
||||
const auto WORKSPACEID = monitorRule.defaultWorkspaceID == -1 && !g_pCompositor->getWorkspaceByID(monitorRule.defaultWorkspaceID) ? g_pCompositor->m_lWorkspaces.size() + 1 /* Cuz workspaces doesnt have the new one yet and we start with 1 */ : monitorRule.defaultWorkspaceID;
|
||||
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
|
||||
const auto PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
|
||||
const auto WORKSPACEID = monitorRule.defaultWorkspaceID == -1 ? g_pCompositor->m_lWorkspaces.size() + 1 /* Cuz workspaces doesnt have the new one yet and we start with 1 */ : monitorRule.defaultWorkspaceID;
|
||||
|
||||
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
// We are required to set the name here immediately
|
||||
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, std::to_string(WORKSPACEID).c_str());
|
||||
Debug::log(LOG, "New monitor: WORKSPACEID %d, exists: %d", WORKSPACEID, (int)(PNEWWORKSPACE != nullptr));
|
||||
|
||||
if (PNEWWORKSPACE) {
|
||||
// workspace exists, move it to the newly connected monitor
|
||||
g_pCompositor->moveWorkspaceToMonitor(PNEWWORKSPACE, PNEWMONITOR);
|
||||
} else {
|
||||
g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID);
|
||||
PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
|
||||
|
||||
PNEWWORKSPACE->m_iID = WORKSPACEID;
|
||||
PNEWWORKSPACE->m_szName = std::to_string(WORKSPACEID);
|
||||
// We are required to set the name here immediately
|
||||
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, std::to_string(WORKSPACEID).c_str());
|
||||
|
||||
PNEWWORKSPACE->m_iID = WORKSPACEID;
|
||||
PNEWWORKSPACE->m_szName = std::to_string(WORKSPACEID);
|
||||
}
|
||||
|
||||
PNEWMONITOR->activeWorkspace = PNEWWORKSPACE->m_iID;
|
||||
|
||||
PNEWMONITOR->scale = monitorRule.scale;
|
||||
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||
@@ -132,7 +145,9 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
//
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||
g_pCompositor->m_pLastMonitor = PNEWMONITOR;
|
||||
g_pCompositor->m_pLastMonitor = PNEWMONITOR;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("monitoradded", PNEWMONITOR->szName));
|
||||
|
||||
// ready to process cuz we have a monitor
|
||||
g_pCompositor->m_bReadyToProcess = true;
|
||||
@@ -332,6 +347,8 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str());
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("monitorremoved", pMonitor->szName));
|
||||
|
||||
g_pCompositor->m_lMonitors.remove(*pMonitor);
|
||||
|
||||
// update the pMostHzMonitor
|
||||
|
@@ -134,7 +134,7 @@ void Events::listener_mapPopupXDG(void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "New XDG Popup mapped at %d %d", (int)PPOPUP->lx, (int)PPOPUP->ly);
|
||||
|
||||
PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP);
|
||||
PPOPUP->pSurfaceTree = SubsurfaceTree::createTreeRoot(PPOPUP->popup->base->surface, addPopupGlobalCoords, PPOPUP, PPOPUP->parentWindow);
|
||||
|
||||
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode %x", PPOPUP->pSurfaceTree);
|
||||
}
|
||||
|
@@ -25,10 +25,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
PWINDOW->m_bMappedX11 = true;
|
||||
PWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
|
||||
PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceOpen ? SPECIAL_WORKSPACE_ID : PMONITOR->activeWorkspace;
|
||||
PWINDOW->m_bIsMapped = true;
|
||||
PWINDOW->m_bReadyToDelete = false;
|
||||
PWINDOW->m_bFadingOut = false;
|
||||
@@ -73,16 +73,23 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
// window rules
|
||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(PWINDOW);
|
||||
std::string requestedWorkspace = "";
|
||||
bool workspaceSilent = false;
|
||||
|
||||
for (auto& r : WINDOWRULES) {
|
||||
if (r.szRule.find("monitor") == 0) {
|
||||
try {
|
||||
const long int MONITOR = std::stoi(r.szRule.substr(r.szRule.find(" ")));
|
||||
const auto MONITORSTR = r.szRule.substr(r.szRule.find(" "));
|
||||
|
||||
if (MONITOR >= (long int)g_pCompositor->m_lMonitors.size() || MONITOR < (long int)0)
|
||||
PWINDOW->m_iMonitorID = 0;
|
||||
else
|
||||
PWINDOW->m_iMonitorID = MONITOR;
|
||||
if (MONITORSTR == "unset") {
|
||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
} else {
|
||||
const long int MONITOR = std::stoi(MONITORSTR);
|
||||
if (MONITOR >= (long int)g_pCompositor->m_lMonitors.size() || MONITOR < (long int)0)
|
||||
PWINDOW->m_iMonitorID = 0;
|
||||
else
|
||||
PWINDOW->m_iMonitorID = MONITOR;
|
||||
}
|
||||
|
||||
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID)->activeWorkspace;
|
||||
|
||||
@@ -91,11 +98,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
Debug::log(ERR, "Rule monitor failed, rule: %s -> %s | err: %s", r.szRule.c_str(), r.szValue.c_str(), e.what());
|
||||
}
|
||||
} else if (r.szRule.find("workspace") == 0) {
|
||||
// switch to workspace
|
||||
g_pKeybindManager->m_mDispatchers["workspace"](r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
// check if it isnt unset
|
||||
const auto WORKSPACERQ = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
|
||||
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
|
||||
PWINDOW->m_iWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
||||
if (WORKSPACERQ == "unset") {
|
||||
requestedWorkspace = "";
|
||||
} else {
|
||||
requestedWorkspace = WORKSPACERQ;
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Rule workspace matched by window %x, %s applied.", PWINDOW, r.szValue.c_str());
|
||||
} else if (r.szRule.find("float") == 0) {
|
||||
@@ -114,7 +124,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
} else if (r.szRule.find("opacity") == 0) {
|
||||
try {
|
||||
PWINDOW->m_sSpecialRenderData.alpha = std::stof(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
std::string alphaPart = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
|
||||
if (alphaPart.find_first_of(' ') != std::string::npos) {
|
||||
// we have a comma, 2 values
|
||||
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' ')));
|
||||
PWINDOW->m_sSpecialRenderData.alphaInactive = std::stof(alphaPart.substr(alphaPart.find_first_of(' ') + 1));
|
||||
} else {
|
||||
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart);
|
||||
}
|
||||
} catch(std::exception& e) {
|
||||
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
|
||||
}
|
||||
@@ -124,6 +142,25 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
if (requestedWorkspace != "") {
|
||||
// process requested workspace
|
||||
if (requestedWorkspace.find_first_of(' ') != std::string::npos) {
|
||||
// check for silent
|
||||
if (requestedWorkspace.find("silent") != std::string::npos) {
|
||||
workspaceSilent = true;
|
||||
}
|
||||
|
||||
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
|
||||
}
|
||||
|
||||
if (!workspaceSilent) {
|
||||
g_pKeybindManager->m_mDispatchers["workspace"](requestedWorkspace);
|
||||
|
||||
PWINDOW->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
|
||||
PWINDOW->m_iWorkspaceID = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
||||
}
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFloating) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW);
|
||||
PWINDOW->m_bCreatedOverFullscreen = true;
|
||||
@@ -178,7 +215,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
if (!PWINDOW->m_bNoFocus)
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
|
||||
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW);
|
||||
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
|
||||
|
||||
Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree);
|
||||
|
||||
@@ -197,6 +234,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
// do the animation thing
|
||||
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false);
|
||||
|
||||
if (workspaceSilent) {
|
||||
// move the window
|
||||
if (g_pCompositor->m_pLastWindow == PWINDOW) {
|
||||
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
|
||||
} else {
|
||||
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!");
|
||||
}
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
|
||||
}
|
||||
|
||||
|
@@ -149,8 +149,6 @@ public:
|
||||
return false; // unreachable
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void warp() {
|
||||
switch (m_eVarType) {
|
||||
case AVARTYPE_FLOAT: {
|
||||
@@ -170,6 +168,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Vector2D m_vValue = Vector2D(0,0);
|
||||
float m_fValue = 0;
|
||||
CColor m_cValue;
|
||||
|
@@ -46,16 +46,35 @@ void wlr_signal_emit_safe(struct wl_signal *signal, void *data) {
|
||||
}
|
||||
|
||||
std::string getFormat(const char *fmt, ...) {
|
||||
char buf[2048] = "";
|
||||
char buf[LOGMESSAGESIZE] = "";
|
||||
char* outputStr;
|
||||
int logLen;
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
vsprintf(buf, fmt, args);
|
||||
|
||||
logLen = vsnprintf(buf, sizeof buf, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return std::string(buf);
|
||||
if ((long unsigned int)logLen < sizeof buf) {
|
||||
outputStr = strdup(buf);
|
||||
} else {
|
||||
outputStr = (char*)malloc(logLen + 1);
|
||||
|
||||
if (!outputStr) {
|
||||
printf("CRITICAL: Cannot alloc size %d for log! (Out of memory?)", logLen + 1);
|
||||
return "";
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(outputStr, logLen + 1U, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
std::string output = std::string(outputStr);
|
||||
|
||||
free(outputStr);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void scaleBox(wlr_box* box, float scale) {
|
||||
@@ -125,7 +144,10 @@ bool isDirection(const std::string& arg) {
|
||||
|
||||
int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
int result = INT_MAX;
|
||||
if (in.find("name:") == 0) {
|
||||
if (in.find("special") == 0) {
|
||||
outName = "special";
|
||||
return SPECIAL_WORKSPACE_ID;
|
||||
} else if (in.find("name:") == 0) {
|
||||
const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1);
|
||||
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
|
||||
if (!WORKSPACE) {
|
||||
@@ -135,8 +157,59 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
}
|
||||
outName = WORKSPACENAME;
|
||||
} else {
|
||||
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
|
||||
outName = std::to_string(result);
|
||||
if (in[0] == 'm') {
|
||||
// monitor relative
|
||||
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
|
||||
|
||||
// result now has +/- what we should move on mon
|
||||
int remains = (int)result;
|
||||
int currentID = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
||||
int searchID = currentID;
|
||||
|
||||
while (remains != 0) {
|
||||
if (remains < 0)
|
||||
searchID--;
|
||||
else
|
||||
searchID++;
|
||||
|
||||
if (g_pCompositor->workspaceIDOutOfBounds(searchID)){
|
||||
// means we need to wrap around
|
||||
int lowestID = 99999;
|
||||
int highestID = -99999;
|
||||
|
||||
for (auto& w : g_pCompositor->m_lWorkspaces) {
|
||||
if (w.m_iID < lowestID)
|
||||
lowestID = w.m_iID;
|
||||
|
||||
if (w.m_iID > highestID)
|
||||
highestID = w.m_iID;
|
||||
}
|
||||
|
||||
if (remains < 0)
|
||||
searchID = highestID;
|
||||
else
|
||||
searchID = lowestID;
|
||||
}
|
||||
|
||||
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(searchID); PWORKSPACE && PWORKSPACE->m_iID != SPECIAL_WORKSPACE_ID) {
|
||||
if (PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
currentID = PWORKSPACE->m_iID;
|
||||
|
||||
if (remains < 0)
|
||||
remains++;
|
||||
else
|
||||
remains--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = currentID;
|
||||
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
|
||||
|
||||
} else {
|
||||
result = std::clamp((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1, INT_MAX);
|
||||
outName = std::to_string(result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@@ -29,6 +29,9 @@ struct SMonitor {
|
||||
wlr_output_damage* damage = nullptr;
|
||||
bool needsFrameSkip = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
||||
// for the special workspace
|
||||
bool specialWorkspaceOpen = false;
|
||||
|
||||
// Double-linked list because we need to have constant mem addresses for signals
|
||||
// We have to store pointers and use raw new/delete because they might be moved between them
|
||||
|
@@ -20,12 +20,13 @@ void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
|
||||
}
|
||||
}
|
||||
|
||||
SSurfaceTreeNode* createTree(wlr_surface* pSurface) {
|
||||
SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
|
||||
SubsurfaceTree::surfaceTreeNodes.push_back(SSurfaceTreeNode());
|
||||
|
||||
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.back();
|
||||
|
||||
PNODE->pSurface = pSurface;
|
||||
PNODE->pWindowOwner = pWindow;
|
||||
|
||||
PNODE->hyprListener_newSubsurface.initCallback(&pSurface->events.new_subsurface, &Events::listener_newSubsurfaceNode, PNODE, "SurfaceTreeNode");
|
||||
PNODE->hyprListener_commit.initCallback(&pSurface->events.commit, &Events::listener_commitSubsurface, PNODE, "SurfaceTreeNode");
|
||||
@@ -42,16 +43,21 @@ SSurfaceTreeNode* createTree(wlr_surface* pSurface) {
|
||||
return PNODE;
|
||||
}
|
||||
|
||||
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface) {
|
||||
const auto PNODE = createTree(surface);
|
||||
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface, CWindow* pWindow) {
|
||||
const auto PNODE = createTree(surface, pWindow);
|
||||
PNODE->pParent = pParent;
|
||||
PNODE->pSubsurface = pSubsurface;
|
||||
|
||||
Debug::log(LOG, "Creating a subsurface Node! (pWindow: %x)", pWindow);
|
||||
|
||||
return PNODE;
|
||||
}
|
||||
|
||||
SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data) {
|
||||
const auto PNODE = createTree(pSurface);
|
||||
SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data, CWindow* pWindow) {
|
||||
const auto PNODE = createTree(pSurface, pWindow);
|
||||
|
||||
Debug::log(LOG, "Creating a surfaceTree Root! (pWindow: %x)", pWindow);
|
||||
|
||||
PNODE->offsetfn = fn;
|
||||
PNODE->globalOffsetData = data;
|
||||
|
||||
@@ -120,6 +126,8 @@ void Events::listener_newSubsurfaceNode(void* owner, void* data) {
|
||||
PNEWSUBSURFACE->hyprListener_unmap.initCallback(&PSUBSURFACE->events.unmap, &Events::listener_unmapSubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||
PNEWSUBSURFACE->hyprListener_destroy.initCallback(&PSUBSURFACE->events.destroy, &Events::listener_destroySubsurface, PNEWSUBSURFACE, "Subsurface");
|
||||
|
||||
PNEWSUBSURFACE->pWindowOwner = pNode->pWindowOwner;
|
||||
|
||||
wlr_subsurface* existingWlrSubsurface;
|
||||
wl_list_for_each(existingWlrSubsurface, &PSUBSURFACE->surface->current.subsurfaces_below, current.link) {
|
||||
listener_newSubsurfaceNode(pNode, existingWlrSubsurface);
|
||||
@@ -134,7 +142,7 @@ void Events::listener_mapSubsurface(void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface);
|
||||
|
||||
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface);
|
||||
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner);
|
||||
}
|
||||
|
||||
void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||
@@ -162,6 +170,14 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||
void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
SSurfaceTreeNode* pNode = (SSurfaceTreeNode*)owner;
|
||||
|
||||
// no damaging if it's not visible
|
||||
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) {
|
||||
if (g_pConfigManager->getInt("debug:log_damage"))
|
||||
Debug::log(LOG, "Refusing to commit damage from %x because it's invisible.", pNode->pWindowOwner);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int lx = 0, ly = 0;
|
||||
|
||||
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <list>
|
||||
|
||||
struct SSubsurface;
|
||||
class CWindow;
|
||||
|
||||
typedef void (*applyGlobalOffsetFn)(void *, int *, int *);
|
||||
|
||||
@@ -21,6 +22,7 @@ struct SSurfaceTreeNode {
|
||||
|
||||
applyGlobalOffsetFn offsetfn;
|
||||
void *globalOffsetData;
|
||||
CWindow* pWindowOwner = nullptr;
|
||||
|
||||
bool operator==(const SSurfaceTreeNode& rhs) {
|
||||
return pSurface == rhs.pSurface;
|
||||
@@ -37,13 +39,15 @@ struct SSubsurface {
|
||||
DYNLISTENER(unmap);
|
||||
DYNLISTENER(destroy);
|
||||
|
||||
CWindow* pWindowOwner = nullptr;
|
||||
|
||||
bool operator==(const SSubsurface& rhs) {
|
||||
return pSubsurface == rhs.pSubsurface;
|
||||
}
|
||||
};
|
||||
|
||||
namespace SubsurfaceTree {
|
||||
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*);
|
||||
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*, CWindow* pWindow = nullptr);
|
||||
void destroySurfaceTree(SSurfaceTreeNode*);
|
||||
|
||||
inline std::list<SSurfaceTreeNode> surfaceTreeNodes;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include "Workspace.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
CWorkspace::CWorkspace(int monitorID) {
|
||||
CWorkspace::CWorkspace(int monitorID, bool special) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
|
||||
|
||||
if (!PMONITOR) {
|
||||
@@ -10,16 +10,20 @@ CWorkspace::CWorkspace(int monitorID) {
|
||||
}
|
||||
|
||||
m_iMonitorID = monitorID;
|
||||
|
||||
m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
|
||||
|
||||
// set geometry here cuz we can
|
||||
wl_array_init(&m_wlrCoordinateArr);
|
||||
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x;
|
||||
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y;
|
||||
wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr);
|
||||
wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false);
|
||||
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false);
|
||||
m_bIsSpecialWorkspace = special;
|
||||
|
||||
if (!special) {
|
||||
m_pWlrHandle = wlr_ext_workspace_handle_v1_create(PMONITOR->pWLRWorkspaceGroupHandle);
|
||||
|
||||
// set geometry here cuz we can
|
||||
wl_array_init(&m_wlrCoordinateArr);
|
||||
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.x;
|
||||
*reinterpret_cast<int*>(wl_array_add(&m_wlrCoordinateArr, sizeof(int))) = (int)PMONITOR->vecPosition.y;
|
||||
wlr_ext_workspace_handle_v1_set_coordinates(m_pWlrHandle, &m_wlrCoordinateArr);
|
||||
wlr_ext_workspace_handle_v1_set_hidden(m_pWlrHandle, false);
|
||||
wlr_ext_workspace_handle_v1_set_urgent(m_pWlrHandle, false);
|
||||
}
|
||||
|
||||
m_vRenderOffset.m_pWorkspace = this;
|
||||
m_vRenderOffset.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:workspaces_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces")->intValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE);
|
||||
@@ -53,6 +57,18 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
m_fAlpha.setValueAndWarp(255.f);
|
||||
m_fAlpha = 0.f;
|
||||
}
|
||||
} else if (ANIMSTYLE == "slidevert") {
|
||||
// fallback is slide
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
|
||||
m_fAlpha.setValueAndWarp(255.f); // fix a bug, if switching from fade -> slide.
|
||||
|
||||
if (in) {
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y));
|
||||
m_vRenderOffset = Vector2D(0, 0);
|
||||
} else {
|
||||
m_vRenderOffset = Vector2D(0, left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y);
|
||||
}
|
||||
} else {
|
||||
// fallback is slide
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
@@ -82,7 +98,7 @@ void CWorkspace::setActive(bool on) {
|
||||
void CWorkspace::moveToMonitor(const int& id) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(id);
|
||||
|
||||
if (!PMONITOR)
|
||||
if (!PMONITOR || m_bIsSpecialWorkspace)
|
||||
return;
|
||||
|
||||
wlr_ext_workspace_handle_v1_set_active(m_pWlrHandle, false);
|
||||
|
@@ -10,7 +10,7 @@ enum eFullscreenMode : uint8_t {
|
||||
|
||||
class CWorkspace {
|
||||
public:
|
||||
CWorkspace(int monitorID);
|
||||
CWorkspace(int monitorID, bool special = false);
|
||||
~CWorkspace();
|
||||
|
||||
// Workspaces ID-based have IDs > 0
|
||||
@@ -29,6 +29,9 @@ public:
|
||||
CAnimatedVariable m_vRenderOffset;
|
||||
CAnimatedVariable m_fAlpha;
|
||||
|
||||
// "scratchpad"
|
||||
bool m_bIsSpecialWorkspace = false;
|
||||
|
||||
// user-set
|
||||
bool m_bDefaultFloating = false;
|
||||
bool m_bDefaultPseudo = false;
|
||||
|
@@ -160,10 +160,20 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
|
||||
}
|
||||
}
|
||||
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
||||
if (PWORKSPACE->m_bIsSpecialWorkspace) {
|
||||
// if special, we adjust the coords a bit
|
||||
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * 0.8f) / 2.f;
|
||||
PWINDOW->m_vRealSize = calcSize * 0.8f;
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * 0.8f);
|
||||
} else {
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
||||
@@ -184,7 +194,7 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
||||
SDwindleNodeData* OPENINGON;
|
||||
const auto MONFROMCURSOR = g_pCompositor->getMonitorFromCursor();
|
||||
|
||||
if (PMONITOR->ID == MONFROMCURSOR->ID && PNODE->workspaceID == PMONITOR->activeWorkspace) {
|
||||
if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (PNODE->workspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen))) {
|
||||
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(g_pInputManager->getMouseCoordsInternal()));
|
||||
|
||||
// happens on reserved area
|
||||
@@ -196,6 +206,11 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
||||
|
||||
Debug::log(LOG, "OPENINGON: %x, Workspace: %i, Monitor: %i", OPENINGON, PNODE->workspaceID, PMONITOR->ID);
|
||||
|
||||
if (OPENINGON && OPENINGON->workspaceID != PNODE->workspaceID) {
|
||||
// special workspace handling
|
||||
OPENINGON = getFirstNodeOnWorkspace(PNODE->workspaceID);
|
||||
}
|
||||
|
||||
// if it's the first, it's easy. Make it fullscreen.
|
||||
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
|
||||
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
@@ -356,8 +371,21 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
return;
|
||||
|
||||
if (PMONITOR->specialWorkspaceOpen) {
|
||||
const auto TOPNODE = getMasterNodeOnWorkspace(SPECIAL_WORKSPACE_ID);
|
||||
|
||||
if (TOPNODE && PMONITOR) {
|
||||
TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
TOPNODE->recalcSizePosRecursive();
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore any recalc events if we have a fullscreen window.
|
||||
if (!PWORKSPACE || PWORKSPACE->m_bHasFullscreenWindow)
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
return;
|
||||
|
||||
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
@@ -424,6 +452,13 @@ void CHyprDwindleLayout::onBeginDragWindow() {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
|
||||
return;
|
||||
}
|
||||
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = false;
|
||||
|
||||
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
||||
|
11
src/main.cpp
11
src/main.cpp
@@ -3,6 +3,7 @@
|
||||
#include "Compositor.hpp"
|
||||
#include "config/ConfigManager.hpp"
|
||||
#include "init/initHelpers.hpp"
|
||||
#include <iostream>
|
||||
|
||||
// I am a bad bad boy and have used some global vars here,
|
||||
// just for this file
|
||||
@@ -19,17 +20,19 @@ int main(int argc, char** argv) {
|
||||
ignoreSudo = true;
|
||||
}
|
||||
|
||||
system("mkdir -p /tmp/hypr");
|
||||
|
||||
if (!ignoreSudo) {
|
||||
if (Init::isSudo()) {
|
||||
Debug::log(CRIT, "Hyprland shall not be run as the root user. If you really want to, use the --i-am-really-stupid flag.");
|
||||
return 1;
|
||||
std::cout << "Hyprland shall not be run as the root user. If you really want to, use the --i-am-really-stupid flag.\n";
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
Debug::log(WARN, "Running with ignored root checks, I surely hope you know what you're doing.");
|
||||
std::cout << "Running with ignored root checks, I surely hope you know what you're doing.\n";
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Welcome to Hyprland!");
|
||||
std::cout << "Welcome to Hyprland!\n";
|
||||
|
||||
// let's init the compositor.
|
||||
// it initializes basic Wayland stuff in the constructor.
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "EventManager.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -26,10 +27,9 @@ void CEventManager::startThread() {
|
||||
return;
|
||||
}
|
||||
|
||||
unlink("/tmp/hypr/.socket2.sock");
|
||||
|
||||
sockaddr_un SERVERADDRESS = {.sun_family = AF_UNIX};
|
||||
strcpy(SERVERADDRESS.sun_path, "/tmp/hypr/.socket2.sock");
|
||||
std::string socketPath = "/tmp/hypr/" + g_pCompositor->m_szInstanceSignature + "/.socket2.sock";
|
||||
strcpy(SERVERADDRESS.sun_path, socketPath.c_str());
|
||||
|
||||
bind(SOCKET, (sockaddr*)&SERVERADDRESS, SUN_LEN(&SERVERADDRESS));
|
||||
|
||||
@@ -41,7 +41,7 @@ void CEventManager::startThread() {
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
|
||||
Debug::log(LOG, "Hypr socket 2 started.");
|
||||
Debug::log(LOG, "Hypr socket 2 started at %s", socketPath.c_str());
|
||||
|
||||
// set the socket nonblock
|
||||
int flags = fcntl(SOCKET, F_GETFL, 0);
|
||||
|
@@ -105,7 +105,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
// then, we check if the workspace doesnt have a fullscreen window
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface) {
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !foundSurface && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
|
||||
surfacePos = pFoundWindow->m_vRealPosition.vec();
|
||||
@@ -113,7 +113,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
// only check floating because tiled cant be over fullscreen
|
||||
for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); w++) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) {
|
||||
if (((w->m_bIsFloating && w->m_bIsMapped && w->m_bCreatedOverFullscreen) || (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) {
|
||||
pFoundWindow = &(*w);
|
||||
|
||||
if (!pFoundWindow->m_bIsX11) {
|
||||
@@ -285,10 +285,31 @@ void CInputManager::setKeyboardLayout() {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PLASTKEEB = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
|
||||
|
||||
// TODO: configure devices one by one
|
||||
for (auto& k : m_lKeyboards)
|
||||
for (auto& k : m_lKeyboards) {
|
||||
wlr_keyboard_set_keymap(k.keyboard->keyboard, KEYMAP);
|
||||
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, k.keyboard->keyboard);
|
||||
|
||||
wlr_keyboard_modifiers wlrMods = {0};
|
||||
|
||||
if (g_pConfigManager->getInt("input:numlock_by_default") == 1) {
|
||||
// lock numlock
|
||||
const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM);
|
||||
|
||||
if (IDX != XKB_MOD_INVALID)
|
||||
wlrMods.locked |= (uint32_t)1 << IDX;
|
||||
}
|
||||
|
||||
if (wlrMods.locked != 0) {
|
||||
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlrMods);
|
||||
}
|
||||
}
|
||||
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, PLASTKEEB);
|
||||
|
||||
xkb_keymap_unref(KEYMAP);
|
||||
xkb_context_unref(CONTEXT);
|
||||
|
||||
|
@@ -36,12 +36,11 @@ public:
|
||||
|
||||
SDrag m_sDrag;
|
||||
|
||||
std::list<SConstraint> m_lConstraints;
|
||||
std::list<SConstraint> m_lConstraints;
|
||||
std::list<SKeyboard> m_lKeyboards;
|
||||
std::list<SMouse> m_lMice;
|
||||
|
||||
private:
|
||||
|
||||
std::list<SKeyboard> m_lKeyboards;
|
||||
std::list<SMouse> m_lMice;
|
||||
private:
|
||||
|
||||
void mouseMoveUnified(uint32_t, bool refocus = false);
|
||||
};
|
||||
|
@@ -23,6 +23,7 @@ CKeybindManager::CKeybindManager() {
|
||||
m_mDispatchers["exit"] = exitHyprland;
|
||||
m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor;
|
||||
m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor;
|
||||
m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace;
|
||||
}
|
||||
|
||||
void CKeybindManager::addKeybind(SKeybind kb) {
|
||||
@@ -153,6 +154,10 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
|
||||
if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) {
|
||||
ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating;
|
||||
|
||||
if (ACTIVEWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
|
||||
moveActiveToWorkspace(std::to_string(g_pCompositor->getMonitorFromID(ACTIVEWINDOW->m_iMonitorID)->activeWorkspace));
|
||||
}
|
||||
|
||||
ACTIVEWINDOW->m_vRealPosition.setValue(ACTIVEWINDOW->m_vRealPosition.vec() + Vector2D(5, 5));
|
||||
ACTIVEWINDOW->m_vSize = ACTIVEWINDOW->m_vRealPosition.vec() - Vector2D(10, 10);
|
||||
|
||||
@@ -191,12 +196,20 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
|
||||
const auto PWORKSPACETOCHANGETO = g_pCompositor->getWorkspaceByID(workspaceToChangeTo);
|
||||
|
||||
if (workspaceToChangeTo == SPECIAL_WORKSPACE_ID)
|
||||
PWORKSPACETOCHANGETO->m_iMonitorID = PMONITOR->ID;
|
||||
|
||||
// if it's not visible, make it visible.
|
||||
if (!g_pCompositor->isWorkspaceVisible(workspaceToChangeTo)) {
|
||||
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
|
||||
|
||||
// change it
|
||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||
PMONITOR->specialWorkspaceOpen = false;
|
||||
|
||||
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||
else
|
||||
PMONITOR->specialWorkspaceOpen = true;
|
||||
|
||||
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
|
||||
// and that'd be annoying as hell
|
||||
@@ -219,7 +232,6 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
if (!m_bSuppressWorkspaceChangeEvents)
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName));
|
||||
}
|
||||
|
||||
|
||||
// If the monitor is not the one our cursor's at, warp to it.
|
||||
if (PMONITOR != g_pCompositor->getMonitorFromCursor()) {
|
||||
@@ -260,20 +272,26 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE)
|
||||
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
|
||||
|
||||
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID);
|
||||
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID, workspaceToChangeTo == SPECIAL_WORKSPACE_ID);
|
||||
const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
|
||||
|
||||
// start anim on new workspace
|
||||
PWORKSPACE->startAnim(true, ANIMTOLEFT);
|
||||
|
||||
// We are required to set the name here immediately
|
||||
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, workspaceName.c_str());
|
||||
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, workspaceName.c_str());
|
||||
|
||||
PWORKSPACE->m_iID = workspaceToChangeTo;
|
||||
PWORKSPACE->m_iMonitorID = PMONITOR->ID;
|
||||
PWORKSPACE->m_szName = workspaceName;
|
||||
|
||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||
|
||||
PMONITOR->specialWorkspaceOpen = false;
|
||||
|
||||
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||
else
|
||||
PMONITOR->specialWorkspaceOpen = true;
|
||||
|
||||
// we need to move XWayland windows to narnia or otherwise they will still process our cursor and shit
|
||||
// and that'd be annoying as hell
|
||||
@@ -319,14 +337,19 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||
|
||||
const auto OLDWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
// hack
|
||||
std::string unusedName;
|
||||
const auto WORKSPACEID = getWorkspaceIDFromString(args, unusedName);
|
||||
|
||||
if (WORKSPACEID == PWINDOW->m_iWorkspaceID) {
|
||||
Debug::log(LOG, "Not moving to workspace because it didn't change.");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||
|
||||
g_pKeybindManager->changeworkspace(args);
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
@@ -368,6 +391,17 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
||||
}
|
||||
|
||||
// undo the damage if we are moving to the special workspace
|
||||
if (WORKSPACEID == SPECIAL_WORKSPACE_ID) {
|
||||
changeworkspace(std::to_string(OLDWORKSPACE->m_iID));
|
||||
OLDWORKSPACE->startAnim(true, true, true);
|
||||
toggleSpecialWorkspace("");
|
||||
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true);
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors)
|
||||
m.specialWorkspaceOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
@@ -746,5 +780,50 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
if (!PWORKSPACE) {
|
||||
Debug::log(ERR, "moveWorkspaceToMonitor workspace doesn't exist!");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
|
||||
}
|
||||
|
||||
void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
|
||||
if (g_pCompositor->getWindowsOnWorkspace(SPECIAL_WORKSPACE_ID) == 0) {
|
||||
Debug::log(LOG, "Can't open empty special workspace!");
|
||||
return;
|
||||
}
|
||||
|
||||
bool open = false;
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
if (m.specialWorkspaceOpen) {
|
||||
open = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (open)
|
||||
Debug::log(LOG, "Toggling special workspace to closed");
|
||||
else
|
||||
Debug::log(LOG, "Toggling special workspace to open");
|
||||
|
||||
if (open) {
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
if (m.specialWorkspaceOpen != !open) {
|
||||
m.specialWorkspaceOpen = !open;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
|
||||
|
||||
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
||||
|
||||
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(true, true);
|
||||
}
|
||||
|
||||
g_pInputManager->refocus();
|
||||
}
|
@@ -53,6 +53,7 @@ private:
|
||||
static void exitHyprland(std::string);
|
||||
static void moveCurrentWorkspaceToMonitor(std::string);
|
||||
static void moveWorkspaceToMonitor(std::string);
|
||||
static void toggleSpecialWorkspace(std::string);
|
||||
|
||||
friend class CCompositor;
|
||||
};
|
||||
|
@@ -269,6 +269,7 @@ void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
|
||||
glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round);
|
||||
glUniform1i(glGetUniformLocation(m_shQUAD.program, "primitiveMultisample"), (int)(g_pConfigManager->getInt("decoration:multisample_edges") == 1 && round != 0));
|
||||
|
||||
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
@@ -304,7 +305,7 @@ void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float al
|
||||
scissor((wlr_box*)nullptr);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border) {
|
||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border, bool noAA) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
|
||||
@@ -362,6 +363,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(glGetUniformLocation(shader->program, "radius"), round);
|
||||
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(g_pConfigManager->getInt("decoration:multisample_edges") == 1 && round != 0 && !border && !noAA));
|
||||
|
||||
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
@@ -598,7 +600,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
glStencilFunc(GL_ALWAYS, 1, -1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
renderTextureInternalWithDamage(tex, pBox, a, &damage, round);
|
||||
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true);
|
||||
|
||||
// then stop
|
||||
glStencilFunc(GL_EQUAL, 1, -1);
|
||||
@@ -637,7 +639,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, i
|
||||
box->width += 2 * thick;
|
||||
box->height += 2 * thick;
|
||||
|
||||
round += thick; // cuz yeah
|
||||
round += thick * m_RenderData.pMonitor->scale; // cuz yeah
|
||||
|
||||
// only draw on non-stencild.
|
||||
glStencilFunc(GL_NOTEQUAL, 1, -1);
|
||||
|
@@ -110,7 +110,7 @@ private:
|
||||
// returns the out FB, can be either Mirror or MirrorSwap
|
||||
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
|
||||
|
||||
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false);
|
||||
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false, bool noAA = false);
|
||||
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
|
||||
};
|
||||
|
||||
|
@@ -31,7 +31,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output);
|
||||
}
|
||||
|
||||
bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
|
||||
bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
|
||||
wlr_box geometry = pWindow->getFullWindowBoundingBox();
|
||||
|
||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
|
||||
@@ -46,6 +46,30 @@ bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
|
||||
return true;
|
||||
|
||||
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return false;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
return true;
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m.ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
|
||||
return true;
|
||||
|
||||
if (m.specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -70,6 +94,21 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWor
|
||||
renderWindow(&w, pMonitor, time, true);
|
||||
}
|
||||
|
||||
// and then special windows
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
|
||||
continue;
|
||||
|
||||
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(&w, pMonitor))
|
||||
continue;
|
||||
|
||||
// render the bad boy
|
||||
renderWindow(&w, pMonitor, time, true);
|
||||
}
|
||||
|
||||
// and the overlay layers
|
||||
if (pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL) {
|
||||
// on non-full we draw the bar and shit
|
||||
@@ -112,7 +151,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
||||
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
|
||||
|
||||
// apply window special data
|
||||
renderdata.alpha *= pWindow->m_sSpecialRenderData.alpha;
|
||||
if (pWindow->m_sSpecialRenderData.alphaInactive == -1)
|
||||
renderdata.alpha *= pWindow->m_sSpecialRenderData.alpha;
|
||||
else
|
||||
renderdata.alpha *= pWindow == g_pCompositor->m_pLastWindow ? pWindow->m_sSpecialRenderData.alpha : pWindow->m_sSpecialRenderData.alphaInactive;
|
||||
|
||||
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
|
||||
|
||||
@@ -176,7 +218,10 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
||||
continue;
|
||||
|
||||
if (w.m_bIsFloating)
|
||||
continue; // floating are in second pass
|
||||
continue; // floating are in the second pass
|
||||
|
||||
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
continue; // special are in the third pass
|
||||
|
||||
if (!shouldRenderWindow(&w, PMONITOR))
|
||||
continue;
|
||||
@@ -193,6 +238,24 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
||||
if (!w.m_bIsFloating)
|
||||
continue;
|
||||
|
||||
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(&w, PMONITOR))
|
||||
continue;
|
||||
|
||||
// render the bad boy
|
||||
renderWindow(&w, PMONITOR, time, true);
|
||||
}
|
||||
|
||||
// and then special
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
|
||||
continue;
|
||||
|
||||
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(&w, PMONITOR))
|
||||
continue;
|
||||
|
||||
|
@@ -29,6 +29,8 @@ public:
|
||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||
void damageMonitor(SMonitor*);
|
||||
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
|
||||
bool shouldRenderWindow(CWindow*, SMonitor*);
|
||||
bool shouldRenderWindow(CWindow*);
|
||||
|
||||
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);
|
||||
|
||||
|
@@ -26,6 +26,8 @@ uniform vec2 bottomRight;
|
||||
uniform vec2 fullSize;
|
||||
uniform float radius;
|
||||
|
||||
uniform int primitiveMultisample;
|
||||
|
||||
void main() {
|
||||
if (radius == 0.0) {
|
||||
gl_FragColor = v_color;
|
||||
@@ -38,15 +40,57 @@ void main() {
|
||||
// we're close left
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
// top
|
||||
if (distance(topLeft, pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(topLeft, pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = v_color * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
// bottom
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = v_color * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,15 +98,57 @@ void main() {
|
||||
// we're close right
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
// top
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = v_color * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
// bottom
|
||||
if (distance(bottomRight, pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(bottomRight, pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = v_color * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,6 +180,8 @@ uniform float radius;
|
||||
|
||||
uniform int discardOpaque;
|
||||
|
||||
uniform int primitiveMultisample;
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 pixColor = texture2D(tex, v_texcoord);
|
||||
@@ -109,15 +197,57 @@ void main() {
|
||||
// we're close left
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
// top
|
||||
if (distance(topLeft, pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(topLeft, pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
// bottom
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,15 +255,57 @@ void main() {
|
||||
// we're close right
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
// top
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
// bottom
|
||||
if (distance(bottomRight, pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(bottomRight, pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,12 +326,16 @@ uniform float radius;
|
||||
|
||||
uniform int discardOpaque;
|
||||
|
||||
uniform int primitiveMultisample;
|
||||
|
||||
void main() {
|
||||
|
||||
if (discardOpaque == 1 && alpha == 1.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 pixColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
|
||||
|
||||
vec2 pixCoord = fullSize * v_texcoord;
|
||||
|
||||
@@ -167,15 +343,57 @@ void main() {
|
||||
// we're close left
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
// top
|
||||
if (distance(topLeft, pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(topLeft, pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
// bottom
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,20 +401,62 @@ void main() {
|
||||
// we're close right
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
// top
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
// bottom
|
||||
if (distance(bottomRight, pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(bottomRight, pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0) * alpha;
|
||||
gl_FragColor = pixColor * alpha;
|
||||
})#";
|
||||
|
||||
inline const std::string FRAGBLUR1 = R"#(
|
||||
@@ -261,6 +521,8 @@ uniform float radius;
|
||||
|
||||
uniform int discardOpaque;
|
||||
|
||||
uniform int primitiveMultisample;
|
||||
|
||||
void main() {
|
||||
|
||||
vec4 pixColor = texture2D(texture0, v_texcoord);
|
||||
@@ -276,15 +538,57 @@ void main() {
|
||||
// we're close left
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
// top
|
||||
if (distance(topLeft, pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(topLeft, pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(topLeft, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(topLeft, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
// bottom
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(vec2(topLeft[0], bottomRight[1]), pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(topLeft[0], bottomRight[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -292,15 +596,57 @@ void main() {
|
||||
// we're close right
|
||||
if (pixCoord[1] < topLeft[1]) {
|
||||
// top
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(vec2(bottomRight[0], topLeft[1]), pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(vec2(bottomRight[0], topLeft[1]), pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
// bottom
|
||||
if (distance(bottomRight, pixCoord) > radius) {
|
||||
discard;
|
||||
return;
|
||||
|
||||
float topLeftDistance = distance(bottomRight, pixCoord);
|
||||
|
||||
if (topLeftDistance > radius - 1.0) {
|
||||
if (primitiveMultisample == 0 && topLeftDistance > radius) {
|
||||
discard;
|
||||
return;
|
||||
} else if (primitiveMultisample == 1) {
|
||||
float distances = 0.0;
|
||||
if (distance(bottomRight, pixCoord + vec2(0.25, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.75, 0.25)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.25, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
if (distance(bottomRight, pixCoord + vec2(0.75, 0.75)) < radius) { distances = distances + 1.0; }
|
||||
|
||||
if (distances == 0.0) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = pixColor * distances;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user