Compare commits

..

52 Commits

Author SHA1 Message Date
vaxerski
f99ad521a4 Updated issue templates 2022-06-03 17:52:22 +02:00
vaxerski
9486a230c7 Log to the instance folder 2022-06-03 17:48:07 +02:00
vaxerski
6f3b004199 IPC and log changes, introduce signature 2022-06-03 17:41:57 +02:00
vaxerski
19b17b590c fix moveactivetoworkspace with same workspace 2022-06-03 11:19:17 +02:00
vaxerski
f9c8a72e46 dont enable AA by default 2022-06-02 23:03:13 +02:00
vaxerski
e11cb8b328 Added antialiasing to outer edges
simplified, stupidly fast MSAA for rounded edges
2022-06-02 22:58:54 +02:00
vaxerski
7b568d7ad8 configure keyboards one by one 2022-06-02 20:31:47 +02:00
vaxerski
a2f718059b fucking typo 2022-06-02 19:50:46 +02:00
vaxerski
feb0499597 Merge pull request #144 from fufexan/main
Fix Nix build and add updater
2022-06-02 19:47:54 +02:00
vaxerski
601abc7e92 Added locking numlock 2022-06-02 19:47:11 +02:00
Mihai Fufezan
7451890fd7 nix: replace paths dynamically 2022-06-02 19:10:56 +03:00
vaxerski
f5cdb5b95e Fix special in m+1 m-1 2022-06-02 16:54:19 +02:00
vaxerski
7afcf656bd Added hyprctl devices 2022-06-02 13:59:33 +02:00
Mihai Fufezan
6daa866beb nix/updater: only update wlroots on rev change 2022-06-02 00:09:28 +03:00
Mihai Fufezan
9447fcd603 fix Nix build and add updater
- move unnecessary toplevel files to nix/
- added patch that ignores the submodule (revert)
- add update script run by a workflow
2022-06-01 23:52:08 +03:00
vaxerski
9acf15efd7 README changes 2022-06-01 22:00:46 +02:00
vaxerski
b5a100379e reject drag on fullscreen workspace 2022-06-01 21:13:10 +02:00
vaxerski
4f76d5d8d7 destroy monitor on disabled 2022-06-01 21:10:12 +02:00
vaxerski
8d850b0ce1 Added workspace/monitor unset and workspace silent rules 2022-06-01 21:04:06 +02:00
vaxerski
0f28d2ae55 fix stupid error in anim styles 2022-06-01 20:51:21 +02:00
vaxerski
d2451aea4b use overflowing coords when surface unmaps 2022-06-01 13:38:33 +02:00
vaxerski
680705ff91 [gha] bump flake inputs 2022-06-01 00:50:00 +00:00
vaxerski
300fc2ab0f Merge pull request #140 from ThatOneCalculator/main
More AUR stuff
2022-05-31 22:49:15 +02:00
Kainoa Kanter
02210d3d96 Update PKGBUILD-bin 2022-05-31 13:46:09 -07:00
Kainoa Kanter
879345c1e9 Update PKGBUILD-git 2022-05-31 13:46:00 -07:00
Kainoa Kanter
1e3bea5e70 Update PKGBUILD 2022-05-31 13:45:51 -07:00
Kainoa Kanter
f64cae2b7f Update PKGBUILD-bin 2022-05-31 13:32:59 -07:00
Kainoa Kanter
c433b14e3d Update PKGBUILD 2022-05-31 13:32:38 -07:00
Kainoa Kanter
8d1c495878 Update PKGBUILD-git 2022-05-31 13:32:26 -07:00
Kainoa Kanter
4264a0b08d Update PKGBUILD 2022-05-31 13:26:03 -07:00
Kainoa Kanter
40ab062a3c Update PKGBUILD-bin 2022-05-31 13:25:49 -07:00
Kainoa Kanter
35bcea38e3 0.2.1beta 2022-05-31 13:19:26 -07:00
Kainoa Kanter
1ccb944509 0.2.1beta 2022-05-31 13:19:15 -07:00
Kainoa Kanter
c600249aee Merge branch 'vaxerski:main' into main 2022-05-31 13:18:36 -07:00
Kainoa Kanter
6d6e967a8d Update PKGBUILD-git 2022-05-31 13:17:02 -07:00
vaxerski
970018248f Don't damage surfaces coming from not rendered windows 2022-05-31 22:16:13 +02:00
Kainoa Kanter
f6b8a96621 Update PKGBUILD 2022-05-31 13:15:57 -07:00
Kainoa Kanter
8e8d5a99c2 Add bin 2022-05-31 13:15:41 -07:00
vaxerski
471654d791 remove monitor recommended dt from config 2022-05-31 21:05:46 +02:00
vaxerski
679e36d82e fix border size on scaled outputs 2022-05-31 20:38:45 +02:00
vaxerski
0f8712ed64 fix crash in moveWorkspaceToMonitor 2022-05-31 18:47:32 +02:00
vaxerski
3e28a8b690 added slidevert for workspaces 2022-05-31 17:56:33 +02:00
vaxerski
8de7cc5a8d opacity windowrule support 2 values 2022-05-31 17:35:50 +02:00
vaxerski
e73df80782 Add mon in mon out events and fix crash 2022-05-31 17:17:44 +02:00
vaxerski
0d7131d30e fix typo in hyprctl clients and activewindow 2022-05-31 16:52:28 +02:00
vaxerski
d2e0b7c22a render special over fullscreen 2022-05-31 14:20:41 +02:00
vaxerski
c1193ee483 updated readme features 2022-05-31 14:15:28 +02:00
vaxerski
042e79b888 fix fatal crash 2022-05-31 14:04:11 +02:00
vaxerski
0055efc4f1 Added a special workspace 2022-05-31 14:01:00 +02:00
vaxerski
df722cbb86 Added relative monitor workspace offset 2022-05-31 12:33:08 +02:00
vaxerski
68f7e565e6 Use existing default mon workspace if available on connect 2022-05-31 12:10:34 +02:00
vaxerski
48a3b1c514 fix oopsie 2022-05-31 11:02:54 +02:00
46 changed files with 1199 additions and 189 deletions

View File

@@ -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.*

View File

@@ -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"

View File

@@ -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

View File

@@ -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>

View File

@@ -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
View 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}"
}

View File

@@ -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
}

View File

@@ -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
View File

@@ -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": {

View File

@@ -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: {

View File

@@ -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);

View File

@@ -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
View 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

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -9,6 +9,7 @@
struct SWindowSpecialRenderData {
float alpha = 1.f;
float alphaInactive = -1.f; // -1 means unset
};
struct SWindowAdditionalConfigData {

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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:

View File

@@ -12,5 +12,8 @@ enum LogLevel {
};
namespace Debug {
void init(std::string IS);
void log(LogLevel level, const char* fmt, ...);
inline std::string logFile;
};

View File

@@ -64,4 +64,6 @@
#endif
#ifndef GIT_DIRTY
#define GIT_DIRTY "?"
#endif
#endif
#define SPECIAL_WORKSPACE_ID -99

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
};

View File

@@ -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();
}

View File

@@ -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;
};

View File

@@ -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);

View File

@@ -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);
};

View File

@@ -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;

View File

@@ -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&);

View File

@@ -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;
}
}
}
}