Compare commits

...

67 Commits

Author SHA1 Message Date
vaxerski
9f1d7f7fc7 properly scan for subsurfaces in fullscreen input refocus 2022-10-30 12:28:37 +00:00
vaxerski
6245c92bd0 avoid creating bound WS-es in moveWorkspaceToMonitor 2022-10-30 12:14:12 +00:00
vaxerski
2e32e202e9 set lastmonitor in onDisconnect 2022-10-29 22:45:01 +01:00
vaxerski
d994ad75e8 revert output smart layout reporting 2022-10-29 17:32:03 +01:00
vaxerski
2caebb3b10 fix default 0 in box passing test 2022-10-29 14:37:33 +01:00
vaxerski
05f3eebd96 avoid layout changes when unnecessary in applyMonitorRule 2022-10-29 12:24:44 +01:00
vaxerski
74d05d0adc ensure VRR for current display only in onConnect 2022-10-28 23:48:48 +01:00
vaxerski
341a0616aa avoid applying offset twice in onConnect 2022-10-28 23:23:23 +01:00
vaxerski
ea7f617df6 remove redundant check 2022-10-28 22:33:47 +01:00
vaxerski
644c64d79d lower IME errors to WARNs 2022-10-28 21:47:08 +01:00
vaxerski
d193d70ecf guard primaryFB tex in end() 2022-10-28 21:46:19 +01:00
vaxerski
9e227a52c0 allow cyclenext on null focus 2022-10-28 21:31:39 +01:00
vaxerski
1a767b021b fix minor focus oopsie 2022-10-28 20:12:17 +01:00
vaxerski
83e4006b16 properly find the constraint window 2022-10-28 19:35:02 +01:00
vaxerski
1759b0483c constrain mouse on focus change 2022-10-28 19:20:12 +01:00
vaxerski
f7174acc48 minor fixes for xwayland refocus 2022-10-28 19:18:10 +01:00
vaxerski
c2cd718e89 ignore pointer constraints in touch 2022-10-27 23:44:23 +01:00
Hilton Chain
c21808dd2d meson: Fallback to 'opengl' when 'GL' is not found.
This patch adds 'opengl' as a fallback to 'GL' for dependency lookup, to
link with libglvnd configured without X11 support.

For OpenGL, libglvnd provides two pkg-config files: `gl.pc' with GLX
support while `opengl.pc' not.  When building without X11 support, the
former won't be installed.
2022-10-28 00:50:58 +03:00
Vaxry
2c2e35eec1 Merge pull request #912 from riley-martin/hyprctl
Improve several hyprctl commands
2022-10-27 16:17:15 +01:00
Riley Martin
c064711d2a Improve hyprctl
Added better help for some hyprctl commands.
Failed commands should now 'fail' by returning a nonzero status to the shell

Fix typos
2022-10-27 10:39:21 -04:00
vaxerski
7d6ccca695 add 10bit support to displays 2022-10-27 13:26:47 +01:00
vaxerski
28c81fc71e add disabling pointer devices 2022-10-27 12:58:10 +01:00
Vaxry
d5a0610ea2 No xwayland overhaul (#920) 2022-10-27 11:26:35 +01:00
vaxerski
4aebb73de0 Added hyprctl cursorpos 2022-10-26 13:19:37 +01:00
vaxerski
46e51a81c4 unrestrict hyprctl message size 2022-10-26 13:11:05 +01:00
vaxerski
83ad59fae7 Allow 100%- for move rule 2022-10-26 12:34:26 +01:00
vaxerski
f9a7b6bf26 default focus_on_activate to false 2022-10-25 18:53:18 +01:00
vaxerski
cdb331076a allow # escaping in config 2022-10-25 14:32:25 +01:00
vaxerski
ba9a8a9ded unify LS unmap focus 2022-10-25 14:19:24 +01:00
vaxerski
34bd2cf803 respect wsbind in workspace silent rules 2022-10-25 10:30:25 +01:00
vaxerski
69f1d7b360 Rework workspace rules 2022-10-24 18:36:31 +01:00
vaxerski
e0bc952c83 minor fix to silent ws rules 2022-10-24 17:00:08 +01:00
vaxerski
cf869d9636 allow nofocus + workspace silent 2022-10-24 12:37:07 +01:00
vaxerski
077c1491a8 respect nofocus in candidate searching 2022-10-24 12:28:41 +01:00
vaxerski
c04563734e Rework candidate finding on close window 2022-10-24 12:25:36 +01:00
vaxerski
1d0d350fc3 fix silent + size windowrules 2022-10-24 12:03:15 +01:00
vaxerski
d55338a3f5 fix debug nest black screen 2022-10-24 11:58:07 +01:00
vaxerski
c6a3092b45 more safety around shutting down and mouse movements 2022-10-24 00:14:42 +01:00
vaxerski
10303259f7 always report sizes after a window unmap 2022-10-22 22:10:34 +01:00
Mihai Fufezan
3dca2fd61e Nix: override wayland-protocols 2022-10-23 00:01:55 +03:00
vaxerski
47eac4be1c disable adaptive sync with no_vfr off 2022-10-22 21:45:17 +01:00
vaxerski
2995867760 Transpose matrices on LEGACY_RENDERER 2022-10-22 21:10:49 +01:00
vaxerski
c132f5a91f [gha] bump flake inputs 2022-10-22 20:02:58 +00:00
vaxerski
24587492dd update wlroots dep 2022-10-22 21:01:45 +01:00
vaxerski
44cee0f5f8 more safety for focus requests 2022-10-22 16:45:33 +01:00
vaxerski
2c714eace5 handle activate requests 2022-10-22 16:43:47 +01:00
vaxerski
0d7d7a970d fix crash in event manager on hangup 2022-10-22 16:15:52 +01:00
Vaxry
3a27ef5e12 Merge pull request #893 from wael444/main
meson.build,CMakeLists.txt: use sh instead of bash
2022-10-22 11:57:36 +01:00
wael
6d273c8e44 CMakeLists.txt: use sh instead of bash 2022-10-22 09:23:52 +03:00
wael
c775153e01 meson.build: use sh instead of bash 2022-10-22 09:23:26 +03:00
vaxerski
b71d7c9007 minor workspace rule parsing fixes 2022-10-21 10:45:12 +01:00
vaxerski
ce5f025428 T1C: window dance compat 2022-10-20 22:38:49 +01:00
vaxerski
6df6aea1ba fix swipe with fullscreen maximized 2022-10-20 20:37:37 +01:00
Kainoa Kanter
ca2d2db0ef Add windowrules for noblur and noshadow (#884) 2022-10-20 20:36:27 +01:00
vaxerski
1ccb0b5f96 bump xdg ver to 5 2022-10-20 18:04:21 +01:00
vaxerski
c2545b3ae6 fix refocus on last window 2022-10-20 18:00:29 +01:00
vaxerski
dada872981 minor swipe on new fixes 2022-10-20 17:52:17 +01:00
vaxerski
1eec5161bd minor fix for swipes from empty workspaces 2022-10-20 15:47:35 +01:00
vaxerski
53c3644c29 fix minor anim issue with swipe new 2022-10-20 15:02:46 +01:00
vaxerski
6d66dde208 added swipe create new 2022-10-20 14:54:32 +01:00
vaxerski
1b349f79ac don't set custom mode in change 2022-10-19 22:12:02 +01:00
vaxerski
da8be82c9a Fix self-noding in changeWindowFloatingMode 2022-10-19 21:32:30 +01:00
vaxerski
8ffd244ef6 fix animate_manual_resizes with moves 2022-10-19 21:17:49 +01:00
vaxerski
bf9d31ce49 fix maximized windows not hiding tiled 2022-10-19 15:17:35 +01:00
vaxerski
98a32f5e52 render layer snapshot without blur 2022-10-19 11:00:59 +01:00
vaxerski
dc1737f128 allow glob wildcard in addreserved 2022-10-17 23:23:07 +01:00
Mihai Fufezan
48634d7e4a Nix & meson: 0.15.3 -> 0.16.0 2022-10-18 01:16:44 +03:00
38 changed files with 893 additions and 225 deletions

View File

@@ -62,7 +62,7 @@ jobs:
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake
- name: Checkout Hyprland
uses: actions/checkout@v3
with:
@@ -73,13 +73,23 @@ jobs:
-Ddefault_library=static
- name: Compile
run: ninja -C obj-x86_64-pc-linux-gnu
# - name: Compress artifacts
# run: |
# mkdir x86_64-pc-linux-gnu
# DESTDIR=$PWD/x86_64-pc-linux-gnu meson install -C obj-x86_64-pc-linux-gnu --tags runtime
# tar -cvf x86_64-pc-linux-gnu.tar.xz x86_64-pc-linux-gnu
# - name: Upload artifacts
# uses: actions/upload-artifact@v3
# with:
# name: Build artifacts (x86_64-pc-linux-gnu)
# path: x86_64-pc-linux-gnu.tar.xz
noxwayland:
name: "Build Hyprland in pure Wayland (Arch)"
runs-on: ubuntu-latest
container:
image: archlinux
steps:
- name: Download dependencies
run: |
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
pacman --noconfirm --noprogressbar -Syyu
pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd
- name: Checkout Hyprland
uses: actions/checkout@v3
with:
submodules: true
- name: Configure
run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja
- name: Compile
run: make config && make release

View File

@@ -5,7 +5,7 @@ project(Hyprland
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
message(STATUS "Configuring Hyprland!")
message(STATUS "Gathering git info")
# Get git info
# hash and branch
@@ -22,27 +22,38 @@ execute_process(
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND bash -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1"
COMMAND sh -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE
OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(
COMMAND bash -c "git diff-index --quiet HEAD -- || echo \"dirty\""
COMMAND sh -c "git diff-index --quiet HEAD -- || echo \"dirty\""
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_DIRTY
OUTPUT_STRIP_TRAILING_WHITESPACE)
#
#
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Configuring Hyprland in Debug with CMake")
add_definitions( -DHYPRLAND_DEBUG )
ELSE()
add_compile_options( -O3 )
message(STATUS "Configuring Hyprland in Release with CMake")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
include_directories(. PRIVATE "subprojects/wlroots/include/")
include_directories(. PRIVATE "subprojects/wlroots/build/include/")
add_compile_options(-std=c++23 -DWLR_USE_UNSTABLE )
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
message(STATUS "Checking deps...")
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput xcb) # we do not check for wlroots, as we provide it ourselves
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput) # we do not check for wlroots, as we provide it ourselves
file(GLOB_RECURSE SRCFILES "src/*.cpp")
@@ -56,15 +67,11 @@ ENDIF(LEGACY_RENDERER MATCHES true)
IF(NO_XWAYLAND MATCHES true)
message(STATUS "Using the NO_XWAYLAND flag, disabling XWayland!")
add_definitions( -DNO_XWAYLAND )
ENDIF(NO_XWAYLAND MATCHES true)
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Configuring Hyprland in Debug with CMake!")
add_definitions( -DHYPRLAND_DEBUG )
ELSE()
add_compile_options( -O3 )
message(STATUS "Configuring Hyprland in Release with CMake!")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "XWAYLAND Enabled (NO_XWAYLAND not defined) checking deps...")
pkg_check_modules(xcbdep REQUIRED xcb)
target_link_libraries(Hyprland xcb)
ENDIF(NO_XWAYLAND MATCHES true)
target_compile_definitions(Hyprland PRIVATE "-DGIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"")
target_compile_definitions(Hyprland PRIVATE "-DGIT_BRANCH=\"${GIT_BRANCH}\"")
@@ -77,6 +84,8 @@ set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
message(STATUS "Setting link libraries")
target_link_libraries(Hyprland PkgConfig::deps)
target_link_libraries(Hyprland
@@ -90,7 +99,9 @@ target_link_libraries(Hyprland
)
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
message(STATUS "Setting debug flags")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -no-pie -fno-builtin")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg -no-pie -fno-builtin")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg -no-pie -fno-builtin")
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)

12
flake.lock generated
View File

@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1665643254,
"narHash": "sha256-IBVWNJxGCsshwh62eRfR6+ry3bSXmulB3VQRzLQo3hk=",
"lastModified": 1666377499,
"narHash": "sha256-dZZCGvWcxc7oGnUgFVf0UeNHsJ4VhkTM0v5JRe8EwR8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ba187fbdc5e35322c7dff556ef2c47bddfd6e8d7",
"rev": "301aada7a64812853f2e2634a530ef5d34505048",
"type": "github"
},
"original": {
@@ -26,11 +26,11 @@
"flake": false,
"locked": {
"host": "gitlab.freedesktop.org",
"lastModified": 1665405587,
"narHash": "sha256-lVL48azhjGA/oEIcUSZQNwomNs0EzPxCcjgzyDST0PM=",
"lastModified": 1666466001,
"narHash": "sha256-ZjxAnqtcGmHQHKL1Z9sIraDnzIqrJleWcJXfPtzAm74=",
"owner": "wlroots",
"repo": "wlroots",
"rev": "221ee83d440fb7dcbfd141ef3a459a5a973331b6",
"rev": "c2d2773df57750081b16d56da13b5015d752cbd7",
"type": "gitlab"
},
"original": {

View File

@@ -20,7 +20,20 @@
"aarch64-linux"
"x86_64-linux"
];
pkgsFor = nixpkgs.legacyPackages;
pkgsFor = genSystems (system: import nixpkgs {
inherit system;
overlays = [(_: prev: {
wayland-protocols = prev.wayland-protocols.overrideAttrs (old: rec {
version = "1.27";
src = prev.fetchurl {
url = "https://gitlab.freedesktop.org/wayland/${old.pname}/-/releases/${version}/downloads/${old.pname}-${version}.tar.xz";
hash = "sha256-kEbxCkJdTioAlloDrPtrP7V1pWUDrHLCuGghxpZTN1w=";
};
});
})];
});
mkDate = longDate: (lib.concatStringsSep "-" [
(builtins.substring 0 4 longDate)
(builtins.substring 4 2 longDate)
@@ -34,7 +47,7 @@
};
hyprland = prev.callPackage ./nix/default.nix {
stdenv = prev.gcc12Stdenv;
version = "0.15.3beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
version = "0.16.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101")) + "_" + (self.shortRev or "dirty");
wlroots = wlroots-hyprland;
};
hyprland-debug = hyprland.override {debug = true;};

View File

@@ -36,6 +36,7 @@ commands:
reload
setcursor
getoption
cursorpos
flags:
-j -> output in JSON
@@ -80,6 +81,7 @@ void request(std::string arg) {
return;
}
std::string reply = "";
char buffer[8192] = {0};
sizeWritten = read(SERVERSOCKET, buffer, 8192);
@@ -89,9 +91,20 @@ void request(std::string arg) {
return;
}
reply += std::string(buffer, sizeWritten);
while (sizeWritten == 8192) {
sizeWritten = read(SERVERSOCKET, buffer, 8192);
if (sizeWritten < 0) {
std::cout << "Couldn't read (5)";
return;
}
reply += std::string(buffer, sizeWritten);
}
close(SERVERSOCKET);
std::cout << std::string(buffer);
std::cout << reply;
}
void requestHyprpaper(std::string arg) {
@@ -145,11 +158,12 @@ void requestHyprpaper(std::string arg) {
std::cout << std::string(buffer);
}
void dispatchRequest(int argc, char** argv) {
int dispatchRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "dispatch requires 2 params";
return;
std::cout << "Usage: hyprctl dispatch <dispatcher> <arg>\n\
Execute a hyprland keybind dispatcher with the given argument";
return 1;
}
std::string rq = "/dispatch";
@@ -158,12 +172,14 @@ void dispatchRequest(int argc, char** argv) {
rq += " " + std::string(argv[i]);
request(rq);
return 0;
}
void keywordRequest(int argc, char** argv) {
int keywordRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "keyword requires 2 params";
return;
std::cout << "Usage: hyprctl keyword <keyword> <arg>\n\
Execute a hyprland keyword with the given argument";
return 1;
}
std::string rq = "/keyword";
@@ -172,28 +188,33 @@ void keywordRequest(int argc, char** argv) {
rq += " " + std::string(argv[i]);
request(rq);
return 0;
}
void hyprpaperRequest(int argc, char** argv) {
int hyprpaperRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "hyprpaper requires 2 params";
return;
std::cout << "Usage: hyprctl hyprpaper <command> <arg>\n\
Execute a hyprpaper command with the given argument";
return 1;
}
std::string rq = std::string(argv[2]) + " " + std::string(argv[3]);
requestHyprpaper(rq);
return 0;
}
void setcursorRequest(int argc, char** argv) {
int setcursorRequest(int argc, char** argv) {
if (argc < 4) {
std::cout << "setcursor requires 2 params";
return;
std::cout << "Usage: hyprctl setcursor <theme> <size>\n\
Sets the cursor theme for everything except GTK and reloads the cursor";
return 1;
}
std::string rq = "setcursor " + std::string(argv[2]) + " " + std::string(argv[3]);
request(rq);
return 0;
}
void batchRequest(std::string arg) {
@@ -253,6 +274,8 @@ int main(int argc, char** argv) {
fullRequest.pop_back(); // remove trailing space
fullRequest = fullArgs + "/" + fullRequest;
int exitStatus = 0;
if (fullRequest.contains("/--batch")) batchRequest(fullRequest);
else if (fullRequest.contains("/monitors")) request(fullRequest);
@@ -266,10 +289,11 @@ int main(int argc, char** argv) {
else if (fullRequest.contains("/devices")) request(fullRequest);
else if (fullRequest.contains("/reload")) request(fullRequest);
else if (fullRequest.contains("/getoption")) request(fullRequest);
else if (fullRequest.contains("/setcursor")) setcursorRequest(argc, argv);
else if (fullRequest.contains("/dispatch")) dispatchRequest(argc, argv);
else if (fullRequest.contains("/keyword")) keywordRequest(argc, argv);
else if (fullRequest.contains("/hyprpaper")) hyprpaperRequest(argc, argv);
else if (fullRequest.contains("/cursorpos")) request(fullRequest);
else if (fullRequest.contains("/setcursor")) exitStatus = setcursorRequest(argc, argv);
else if (fullRequest.contains("/dispatch")) exitStatus = dispatchRequest(argc, argv);
else if (fullRequest.contains("/keyword")) exitStatus = keywordRequest(argc, argv);
else if (fullRequest.contains("/hyprpaper")) exitStatus = hyprpaperRequest(argc, argv);
else if (fullRequest.contains("/--help")) printf("%s", USAGE.c_str());
else {
printf("%s\n", USAGE.c_str());
@@ -277,5 +301,5 @@ int main(int argc, char** argv) {
}
printf("\n");
return 0;
return exitStatus;
}

View File

@@ -1,5 +1,5 @@
project('Hyprland', 'cpp', 'c',
version : '0.15.3beta',
version : '0.16.0beta',
default_options : [
'warning_level=2',
'default_library=static',
@@ -20,8 +20,8 @@ endif
GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip()
GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip()
GIT_COMMIT_MESSAGE = run_command('bash', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip()
GIT_DIRTY = run_command('bash', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip()
GIT_COMMIT_MESSAGE = run_command('sh', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip()
GIT_DIRTY = run_command('sh', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip()
add_project_arguments(
[

View File

@@ -107,7 +107,7 @@ CCompositor::CCompositor() {
m_sWLRScene = wlr_scene_create();
wlr_scene_attach_output_layout(m_sWLRScene, m_sWLROutputLayout);
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 4);
m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 5);
m_sWLRCursor = wlr_cursor_create();
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
@@ -170,6 +170,8 @@ CCompositor::CCompositor() {
m_sWLRTextInputMgr = wlr_text_input_manager_v3_create(m_sWLDisplay);
m_sWLRIMEMgr = wlr_input_method_manager_v2_create(m_sWLDisplay);
m_sWLRActivation = wlr_xdg_activation_v1_create(m_sWLDisplay);
}
CCompositor::~CCompositor() {
@@ -226,6 +228,7 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLROutputPowerMgr->events.set_mode, &Events::listen_powerMgrSetMode, m_sWLROutputPowerMgr, "PowerMgr");
addWLSignal(&m_sWLRIMEMgr->events.input_method, &Events::listen_newIME, m_sWLRIMEMgr, "IMEMgr");
addWLSignal(&m_sWLRTextInputMgr->events.text_input, &Events::listen_newTextInput, m_sWLRTextInputMgr, "TextInputMgr");
addWLSignal(&m_sWLRActivation->events.request_activate, &Events::listen_activateXDG, m_sWLRActivation, "ActivationV1");
if(m_sWRLDRMLeaseMgr)
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
@@ -238,6 +241,8 @@ void CCompositor::cleanup() {
if (!m_sWLDisplay || m_bIsShuttingDown)
return;
m_bIsShuttingDown = true;
m_pLastFocus = nullptr;
m_pLastWindow = nullptr;
@@ -253,8 +258,6 @@ void CCompositor::cleanup() {
m_vWorkspaces.clear();
m_vWindows.clear();
m_bIsShuttingDown = true;
for (auto& m : m_vMonitors) {
g_pHyprOpenGL->destroyMonitorResources(m.get());
@@ -712,6 +715,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
if (windowValidMapped(PLASTWINDOW)) {
updateWindowAnimatedDecorationValues(PLASTWINDOW);
g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
if (PLASTWINDOW->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_activated(PLASTWINDOW->m_phForeignToplevel, false);
}
@@ -720,6 +725,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","});
g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(nullptr);
m_pLastFocus = nullptr;
return;
}
@@ -745,10 +752,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
if (windowValidMapped(PLASTWINDOW)) {
updateWindowAnimatedDecorationValues(PLASTWINDOW);
if (PLASTWINDOW->m_bIsX11) {
wlr_seat_keyboard_notify_clear_focus(m_sSeat.seat);
wlr_seat_pointer_clear_focus(m_sSeat.seat);
}
if (!pWindow->m_bIsX11 || pWindow->m_iX11Type == 1)
g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
if (PLASTWINDOW->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_activated(PLASTWINDOW->m_phForeignToplevel, false);
@@ -771,8 +776,18 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
// Send an event
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(pWindow) + "," + pWindow->m_szTitle});
g_pLayoutManager->getCurrentLayout()->onWindowFocusChange(pWindow);
if (pWindow->m_phForeignToplevel)
wlr_foreign_toplevel_handle_v1_set_activated(pWindow->m_phForeignToplevel, true);
if (!pWindow->m_bIsX11) {
const auto PCONSTRAINT = wlr_pointer_constraints_v1_constraint_for_surface(m_sWLRPointerConstraints, pWindow->m_uSurface.xdg->surface, m_sSeat.seat);
if (PCONSTRAINT)
g_pInputManager->constrainMouse(m_sSeat.mouse, PCONSTRAINT);
}
}
void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
@@ -781,7 +796,7 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
return; // Don't focus when already focused on this.
// Unfocus last surface if should
if (m_pLastFocus && ((m_sSeat.seat->keyboard_state.focused_surface && wlr_surface_is_xdg_surface(m_pLastFocus)) || !pSurface))
if (m_pLastFocus && !pWindowOwner)
g_pXWaylandManager->activateSurface(m_pLastFocus, false);
if (!pSurface) {
@@ -1261,6 +1276,11 @@ bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) {
return false;
}
void checkFocusSurfaceIter(wlr_surface* pSurface, int x, int y, void* data) {
auto pair = (std::pair<wlr_surface*, bool>*)data;
pair->second = pair->second || pSurface == pair->first;
}
CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) {
if (!pMouse->currentConstraint)
return nullptr;
@@ -1268,11 +1288,18 @@ CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) {
const auto PSURFACE = pMouse->currentConstraint->surface;
for (auto& w : m_vWindows) {
if (PSURFACE == g_pXWaylandManager->getWindowSurface(w.get())) {
if (!w->m_bIsX11 && w->m_bIsMapped && !w->isHidden())
continue;
if (w->isHidden() || !w->m_bMappedX11 || !w->m_bIsMapped || !g_pXWaylandManager->getWindowSurface(w.get()))
continue;
return w.get();
if (w->m_bIsX11) {
if (PSURFACE == g_pXWaylandManager->getWindowSurface(w.get()))
return w.get();
} else {
std::pair<wlr_surface*, bool> check = {PSURFACE, false};
wlr_surface_for_each_surface(w->m_uSurface.xdg->surface, checkFocusSurfaceIter, &check);
if (check.second)
return w.get();
}
}
@@ -1549,7 +1576,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni
if (nextWorkspaceOnMonitorID == -1) {
nextWorkspaceOnMonitorID = 1;
while (getWorkspaceByID(nextWorkspaceOnMonitorID))
while (getWorkspaceByID(nextWorkspaceOnMonitorID) || [&]() -> bool { const auto B = g_pConfigManager->getBoundMonitorForWS(std::to_string(nextWorkspaceOnMonitorID)); return B && B != POLDMON; }())
nextWorkspaceOnMonitorID++;
Debug::log(LOG, "moveWorkspaceToMonitor: Plugging gap with new %d", nextWorkspaceOnMonitorID);
@@ -1652,7 +1679,7 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID) {
w->m_bCreatedOverFullscreen = false;
if (w.get() != pWindow && !w->m_bFadingOut && !w->m_bPinned)
w->m_fAlpha = pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL ? 0.f : 255.f;
w->m_fAlpha = pWindow->m_bIsFullscreen ? 0.f : 255.f;
}
}
@@ -1868,3 +1895,24 @@ bool CCompositor::cursorOnReservedArea() {
return !VECINRECT(CURSORPOS, XY1.x, XY1.y, XY2.x, XY2.y);
}
CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, const std::string& name) {
const auto NAME = name == "" ? std::to_string(id) : name;
auto monID = monid;
// check if bound
if (const auto PMONITOR = g_pConfigManager->getBoundMonitorForWS(NAME); PMONITOR) {
monID = PMONITOR->ID;
}
const auto PWORKSPACE = m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(monID, NAME, id == SPECIAL_WORKSPACE_ID)).get();
// We are required to set the name here immediately
if (id != SPECIAL_WORKSPACE_ID)
wlr_ext_workspace_handle_v1_set_name(PWORKSPACE->m_pWlrHandle, NAME.c_str());
PWORKSPACE->m_iID = id;
PWORKSPACE->m_iMonitorID = monID;
return PWORKSPACE;
}

View File

@@ -69,12 +69,13 @@ public:
wlr_output_power_manager_v1* m_sWLROutputPowerMgr;
wlr_input_method_manager_v2* m_sWLRIMEMgr;
wlr_text_input_manager_v3* m_sWLRTextInputMgr;
wlr_xdg_activation_v1* m_sWLRActivation;
// ------------------------------------------------- //
const char* m_szWLDisplaySocket;
std::string m_szInstanceSignature = "";
std::string m_szCurrentSplash = "error";
std::string m_szCurrentSplash = "error";
std::vector<std::shared_ptr<CMonitor>> m_vMonitors;
std::vector<std::shared_ptr<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
@@ -89,17 +90,17 @@ public:
void startCompositor();
void cleanup();
wlr_surface* m_pLastFocus = nullptr;
CWindow* m_pLastWindow = nullptr;
CMonitor* m_pLastMonitor = nullptr;
wlr_surface* m_pLastFocus = nullptr;
CWindow* m_pLastWindow = nullptr;
CMonitor* m_pLastMonitor = nullptr;
SSeat m_sSeat;
bool m_bReadyToProcess = false;
bool m_bSessionActive = true;
bool m_bDPMSStateON = true;
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
bool m_bIsShuttingDown = false;
bool m_bReadyToProcess = false;
bool m_bSessionActive = true;
bool m_bDPMSStateON = true;
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
bool m_bIsShuttingDown = false;
std::deque<uint64_t> m_dProcessPIDsOnShutdown; // stores PIDs of apps to kill later when shutting down
// ------------------------------------------------- //
@@ -165,6 +166,7 @@ public:
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
void forceReportSizesToWindowsOnWorkspace(const int&);
bool cursorOnReservedArea();
CWorkspace* createNewWorkspace(const int&, const int&, const std::string& name = ""); // will be deleted next frame if left empty and unfocused!
std::string explicitConfigPath;

View File

@@ -24,6 +24,9 @@ struct SWindowAdditionalConfigData {
bool forceOpaque = false;
bool forceAllowsInput = false;
bool forceNoAnims = false;
bool forceNoBorder = false;
bool forceNoShadow = false;
bool windowDanceCompat = false;
};
class CWindow {

View File

@@ -60,6 +60,7 @@ void CConfigManager::setDefaultVars() {
configValues["misc:disable_autoreload"].intValue = 0;
configValues["misc:enable_swallow"].intValue = 0;
configValues["misc:swallow_regex"].strValue = STRVAL_EMPTY;
configValues["misc:focus_on_activate"].intValue = 0;
configValues["debug:int"].intValue = 0;
configValues["debug:log_damage"].intValue = 0;
@@ -161,6 +162,7 @@ void CConfigManager::setDefaultVars() {
configValues["gestures:workspace_swipe_invert"].intValue = 1;
configValues["gestures:workspace_swipe_min_speed_to_force"].intValue = 30;
configValues["gestures:workspace_swipe_cancel_ratio"].floatValue = 0.5f;
configValues["gestures:workspace_swipe_create_new"].intValue = 1;
configValues["input:follow_mouse"].intValue = 1;
@@ -191,6 +193,7 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
cfgValues["scroll_method"].strValue = STRVAL_EMPTY;
cfgValues["touch_transform"].intValue = 0;
cfgValues["touch_output"].strValue = STRVAL_EMPTY;
cfgValues["enabled"].intValue = 1; // only for mice / touchpads
}
void CConfigManager::setDefaultAnimationVars() {
@@ -529,6 +532,9 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
if (ARGS[argno] == "mirror") {
newrule.mirrorOf = ARGS[argno + 1];
argno++;
} else if (ARGS[argno] == "bitdepth") {
newrule.enable10bit = ARGS[argno + 1] == "10";
argno++;
} else {
Debug::log(ERR, "Config error: invalid monitor syntax");
parseError = "invalid syntax at \"" + ARGS[argno] + "\"";
@@ -752,12 +758,15 @@ bool windowRuleValid(const std::string& RULE) {
&& RULE.find("monitor") != 0
&& RULE != "nofocus"
&& RULE != "noblur"
&& RULE != "noshadow"
&& RULE != "noborder"
&& RULE != "center"
&& RULE != "opaque"
&& RULE != "forceinput"
&& RULE != "fullscreen"
&& RULE != "pin"
&& RULE != "noanim"
&& RULE != "windowdance"
&& RULE.find("animation") != 0
&& RULE.find("rounding") != 0
&& RULE.find("workspace") != 0);
@@ -1011,13 +1020,26 @@ void CConfigManager::applyUserDefinedVars(std::string& line, const size_t equals
void CConfigManager::parseLine(std::string& line) {
// first check if its not a comment
const auto COMMENTSTART = line.find_first_of('#');
if (COMMENTSTART == 0)
if (line[0] == '#')
return;
// now, cut the comment off
if (COMMENTSTART != std::string::npos)
line = line.substr(0, COMMENTSTART);
// now, cut the comment off. ## is an escape.
for (long unsigned int i = 1; i < line.length(); ++i) {
if (line[i] == '#') {
if (i + 1 < line.length() && line[i + 1] != '#') {
line = line.substr(0, i);
break; // no need to parse more
}
i++;
}
}
size_t startPos = 0;
while ((startPos = line.find("##", startPos)) != std::string::npos) {
line.replace(startPos, 2, "#");
startPos++;
}
// remove shit at the beginning
while (line[0] == ' ' || line[0] == '\t') {
@@ -1199,6 +1221,7 @@ void CConfigManager::loadConfigLoadVars() {
// check
ensureDPMS();
ensureVRR();
}
// Update window border colors
@@ -1530,6 +1553,49 @@ void CConfigManager::ensureDPMS() {
}
}
void CConfigManager::ensureVRR(CMonitor* pMonitor) {
static auto *const PNOVRR = &getConfigValuePtr("misc:no_vfr")->intValue;
auto ensureVRRForDisplay = [&](CMonitor* m) -> void {
if (!*PNOVRR && !m->vrrActive) {
// Adaptive sync (VRR)
wlr_output_enable_adaptive_sync(m->output, 1);
if (!wlr_output_test(m->output)) {
Debug::log(LOG, "Pending output %s does not accept VRR.", m->output->name);
wlr_output_enable_adaptive_sync(m->output, 0);
}
if (!wlr_output_commit(m->output)) {
Debug::log(ERR, "Couldn't commit output %s in ensureVRR -> true", m->output->name);
}
m->vrrActive = true;
Debug::log(LOG, "VRR ensured on %s -> true", m->output->name);
} else if (*PNOVRR && m->vrrActive) {
wlr_output_enable_adaptive_sync(m->output, 0);
if (!wlr_output_commit(m->output)) {
Debug::log(ERR, "Couldn't commit output %s in ensureVRR -> false", m->output->name);
}
m->vrrActive = false;
Debug::log(LOG, "VRR ensured on %s -> false", m->output->name);
}
};
if (pMonitor) {
ensureVRRForDisplay(pMonitor);
return;
}
for (auto& m : g_pCompositor->m_vMonitors) {
ensureVRRForDisplay(m.get());
}
}
SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std::string& name) {
return &animationConfig[name];
}

View File

@@ -38,6 +38,7 @@ struct SMonitorRule {
bool disabled = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
std::string mirrorOf = "";
bool enable10bit = false;
};
struct SMonitorAdditionalReservedArea {
@@ -151,6 +152,7 @@ public:
bool m_bForceReload = false;
bool m_bNoMonitorReload = false;
void ensureDPMS();
void ensureVRR(CMonitor* pMonitor = nullptr);
std::string parseKeyword(const std::string&, const std::string&, bool dynamic = false);

View File

@@ -601,6 +601,23 @@ std::string splashRequest() {
return g_pCompositor->m_szCurrentSplash;
}
std::string cursorPosRequest(HyprCtl::eHyprCtlOutputFormat format) {
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal().floor();
if (format == HyprCtl::FORMAT_NORMAL) {
return getFormat("%i, %i", (int)CURSORPOS.x, (int)CURSORPOS.y);
} else {
return getFormat(R"#(
{
"x": %i,
"y": %i
}
)#", (int)CURSORPOS.x, (int)CURSORPOS.y);
}
return "error";
}
std::string getReply(std::string);
std::string dispatchBatch(std::string request) {
@@ -767,6 +784,8 @@ std::string getReply(std::string request) {
return devicesRequest(format);
else if (request == "splash")
return splashRequest();
else if (request == "cursorpos")
return cursorPosRequest(format);
else if (request.find("dispatch") == 0)
return dispatchRequest(request);
else if (request.find("keyword") == 0)

View File

@@ -42,6 +42,7 @@ namespace Events {
// Surface XDG (window)
LISTENER(newXDGSurface);
LISTENER(activateXDG);
// Window events
DYNLISTENFUNC(commitWindow);
@@ -87,7 +88,6 @@ namespace Events {
LISTENER(requestMouse);
LISTENER(requestSetSel);
LISTENER(requestSetPrimarySel);
DYNLISTENFUNC(activate);
// outputMgr
LISTENER(outputMgrApply);

View File

@@ -199,8 +199,29 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
// refocus if needed
if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus) {
Vector2D surfaceCoords;
SLayerSurface* pFoundLayerSurface = nullptr;
wlr_surface* foundSurface = nullptr;
g_pCompositor->m_pLastFocus = nullptr;
g_pInputManager->refocus();
// find LS-es to focus
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
if (!foundSurface)
foundSurface = g_pCompositor->vectorToLayerSurface(g_pInputManager->getMouseCoordsInternal(), &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
if (!foundSurface) {
// if there isn't any, focus the last window
const auto PLASTWINDOW = g_pCompositor->m_pLastWindow;
g_pCompositor->focusWindow(nullptr);
g_pCompositor->focusWindow(PLASTWINDOW);
} else {
// otherwise, full refocus
g_pInputManager->refocus();
}
}
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};

View File

@@ -45,6 +45,7 @@ void Events::listener_requestSetSel(wl_listener* listener, void* data) {
}
void Events::listener_readyXWayland(wl_listener* listener, void* data) {
#ifndef NO_XWAYLAND
const auto XCBCONNECTION = xcb_connect(g_pXWaylandManager->m_sWLRXWayland->display_name, NULL);
const auto ERR = xcb_connection_has_error(XCBCONNECTION);
if (ERR) {
@@ -72,6 +73,7 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) {
}
xcb_disconnect(XCBCONNECTION);
#endif
}
void Events::listener_requestDrag(wl_listener* listener, void* data) {

View File

@@ -37,8 +37,6 @@ void Events::listener_change(wl_listener* listener, void* data) {
CONFIGHEAD->state.mode = m->output->current_mode;
CONFIGHEAD->state.x = m->vecPosition.x;
CONFIGHEAD->state.y = m->vecPosition.y;
wlr_output_set_custom_mode(m->output, m->vecPixelSize.x, m->vecPixelSize.y, (int)(round(m->refreshRate * 1000)));
}
wlr_output_manager_v1_set_configuration(g_pCompositor->m_sWLROutputMgr, CONFIG);

View File

@@ -114,6 +114,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
bool workspaceSilent = false;
bool requestsFullscreen = PWINDOW->m_bWantsInitialFullscreen || (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL && PWINDOW->m_uSurface.xdg->toplevel->requested.fullscreen);
bool shouldFocus = true;
bool workspaceSpecial = false;
for (auto& r : WINDOWRULES) {
if (r.szRule.find("monitor") == 0) {
@@ -161,10 +162,16 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bNoFocus = true;
} else if (r.szRule == "noblur") {
PWINDOW->m_sAdditionalConfigData.forceNoBlur = true;
} else if (r.szRule == "noborder") {
PWINDOW->m_sAdditionalConfigData.forceNoBorder = true;
} else if (r.szRule == "noshadow") {
PWINDOW->m_sAdditionalConfigData.forceNoShadow = true;
} else if (r.szRule == "fullscreen") {
requestsFullscreen = true;
} else if (r.szRule == "opaque") {
PWINDOW->m_sAdditionalConfigData.forceOpaque = true;
} else if (r.szRule == "windowdance") {
PWINDOW->m_sAdditionalConfigData.windowDanceCompat = true;
} else if (r.szRule == "forceinput") {
PWINDOW->m_sAdditionalConfigData.forceAllowsInput = true;
} else if (r.szRule == "pin") {
@@ -208,16 +215,17 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (requestedWorkspace.contains("silent")) {
workspaceSilent = true;
shouldFocus = false;
}
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
}
if (!shouldFocus && requestedWorkspace == std::to_string(PMONITOR->activeWorkspace))
shouldFocus = true;
}
if (requestedWorkspace == "special") {
workspaceSilent = true;
}
if (requestedWorkspace == "special") {
workspaceSpecial = true;
workspaceSilent = true;
}
if (!workspaceSilent) {
@@ -228,6 +236,44 @@ void Events::listener_mapWindow(void* owner, void* data) {
}
}
if (workspaceSilent) {
// get the workspace
auto PWORKSPACE = g_pCompositor->getWorkspaceByString(requestedWorkspace);
if (!PWORKSPACE) {
std::string workspaceName = "";
int workspaceID = 0;
if (requestedWorkspace.find("name:") == 0) {
workspaceName = requestedWorkspace.substr(5);
workspaceID = g_pCompositor->getNextAvailableNamedWorkspace();
} else if (workspaceSpecial) {
workspaceName = "";
workspaceID = SPECIAL_WORKSPACE_ID;
} else {
try {
workspaceID = std::stoi(requestedWorkspace);
} catch (...) {
workspaceID = -1;
Debug::log(ERR, "Invalid workspace requested in workspace silent rule!");
}
if (workspaceID < 1) {
workspaceID = -1; // means invalid
}
}
if (workspaceID != -1)
PWORKSPACE = g_pCompositor->createNewWorkspace(workspaceID, PWINDOW->m_iMonitorID, workspaceName);
}
if (PWORKSPACE) {
PWINDOW->m_iWorkspaceID = PWORKSPACE->m_iID;
PWINDOW->m_iMonitorID = PWORKSPACE->m_iMonitorID;
}
}
if (PWINDOW->m_bIsFloating) {
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW);
PWINDOW->m_bCreatedOverFullscreen = true;
@@ -290,12 +336,28 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto POSXSTR = VALUE.substr(0, VALUE.find(" "));
const auto POSYSTR = VALUE.substr(VALUE.find(" ") + 1);
const auto POSX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x;
const auto POSY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y;
int posX = 0;
int posY = 0;
if (POSXSTR.find("100%-") == 0) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const auto POSXRAW = POSXSTR.substr(5);
posX = PMONITOR->vecSize.x - (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stoi(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
} else {
posX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.x;
}
if (POSYSTR.find("100%-") == 0) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const auto POSYRAW = POSYSTR.substr(5);
posY = PMONITOR->vecSize.y - (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stoi(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
} else {
posY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->vecSize.y;
}
Debug::log(LOG, "Rule move, applying to window %x", PWINDOW);
PWINDOW->m_vRealPosition = Vector2D(POSX, POSY) + PMONITOR->vecPosition;
PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition;
PWINDOW->setHidden(false);
} catch (...) {
@@ -311,8 +373,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv();
g_pCompositor->moveWindowToTop(PWINDOW);
}
else {
} else {
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
// Set the pseudo size here too so that it doesnt end up being 0x0
@@ -327,7 +388,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bX11ShouldntFocus = false;
}
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && PWINDOW->m_iX11Type != 2) {
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && PWINDOW->m_iX11Type != 2 && !workspaceSilent) {
g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
PWINDOW->m_fDimPercent.setValueAndWarp(*PDIMSTRENGTH);
@@ -352,6 +413,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->hyprListener_activateX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_activate, &Events::listener_activateX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_configureX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_configure, &Events::listener_configureX11, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XWayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_minimize, &Events::listener_requestMinimize, PWINDOW, "Xwayland Window Late");
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, "Xwayland Window Late");
if (PWINDOW->m_iX11Type == 2)
PWINDOW->hyprListener_setGeometryX11U.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_geometry, &Events::listener_unmanagedSetGeometry, PWINDOW, "XWayland Window Late");
@@ -365,22 +428,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto TIMER = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, setAnimToMove, PWINDOW);
wl_event_source_timer_update(TIMER, PWINDOW->m_vRealPosition.getDurationLeftMs() + 5);
if (workspaceSilent) {
// move the window
const auto OLDWORKSPACE = PWINDOW->m_iWorkspaceID;
if (g_pCompositor->m_pLastWindow == PWINDOW) {
if (requestedWorkspace != "special")
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
else
g_pKeybindManager->m_mDispatchers["movetoworkspace"]("special");
} else {
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!");
}
g_pCompositor->forceReportSizesToWindowsOnWorkspace(OLDWORKSPACE);
}
if (requestsFullscreen) {
// fix fullscreen on requested (basically do a switcheroo)
if (PWORKSPACE->m_bHasFullscreenWindow) {
@@ -503,6 +550,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
PWINDOW->hyprListener_configureX11.removeCallback();
PWINDOW->hyprListener_setTitleWindow.removeCallback();
PWINDOW->hyprListener_setGeometryX11U.removeCallback();
PWINDOW->hyprListener_requestMaximize.removeCallback();
PWINDOW->hyprListener_requestMinimize.removeCallback();
}
if (PWINDOW->m_bIsFullscreen) {
@@ -542,13 +591,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
// refocus on a new window if needed
if (wasLastWindow) {
auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f);
if (PWORKSPACE->m_bHasFullscreenWindow && ((!PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bCreatedOverFullscreen) || !PWINDOW->m_bIsFloating))
PWINDOWCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
if (!PWINDOWCANDIDATE || PWINDOW == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->isHidden() || PWINDOWCANDIDATE->m_bX11ShouldntFocus || PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)
PWINDOWCANDIDATE = nullptr;
const auto PWINDOWCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW);
Debug::log(LOG, "On closed window, new focused candidate is %x", PWINDOWCANDIDATE);
@@ -557,6 +600,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
g_pInputManager->refocus();
else
g_pCompositor->focusWindow(PWINDOWCANDIDATE);
} else {
g_pInputManager->refocus();
}
} else {
Debug::log(LOG, "Unmapped was not focused, ignoring a refocus.");
@@ -594,6 +639,9 @@ void Events::listener_unmapWindow(void* owner, void* data) {
// recheck idle inhibitors
g_pInputManager->recheckIdleInhibitorStatus();
// force report all sizes (QT sometimes has an issue with this)
g_pCompositor->forceReportSizesToWindowsOnWorkspace(PWINDOW->m_iWorkspaceID);
}
void Events::listener_commitWindow(void* owner, void* data) {
@@ -670,26 +718,50 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
} else {
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, FULLSCREEN_FULL);
if (!PWINDOW->m_uSurface.xwayland->mapped)
return;
g_pCompositor->setWindowFullscreen(PWINDOW, PWINDOW->m_uSurface.xwayland->fullscreen, FULLSCREEN_FULL);
}
PWINDOW->updateToplevel();
Debug::log(LOG, "Window %x fullscreen to %i", PWINDOW, PWINDOW->m_bIsFullscreen);
g_pXWaylandManager->setWindowFullscreen(PWINDOW, PWINDOW->m_bIsFullscreen);
}
void Events::listener_activate(void* owner, void* data) {
// TODO
void Events::listener_activateXDG(wl_listener* listener, void* data) {
const auto E = (wlr_xdg_activation_v1_request_activate_event*)data;
static auto *const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
Debug::log(LOG, "Activate request for surface at %x", E->surface);
if (!*PFOCUSONACTIVATE || !wlr_surface_is_xdg_surface(E->surface))
return;
const auto PWINDOW = g_pCompositor->getWindowFromSurface(E->surface);
if (!PWINDOW || PWINDOW == g_pCompositor->m_pLastWindow)
return;
g_pCompositor->focusWindow(PWINDOW);
Vector2D middle = PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f;
g_pCompositor->warpCursorTo(middle);
}
void Events::listener_activateX11(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
const auto PWINDOW = (CWindow*)owner;
if (PWINDOW->m_iX11Type == 1 /* Managed */) {
wlr_xwayland_surface_activate(PWINDOW->m_uSurface.xwayland, 1);
}
static auto *const PFOCUSONACTIVATE = &g_pConfigManager->getConfigValuePtr("misc:focus_on_activate")->intValue;
Debug::log(LOG, "X11 Activate request for window %x", PWINDOW);
if (!*PFOCUSONACTIVATE || PWINDOW->m_iX11Type != 1 || PWINDOW == g_pCompositor->m_pLastWindow)
return;
g_pCompositor->focusWindow(PWINDOW);
Vector2D middle = PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f;
g_pCompositor->warpCursorTo(middle);
}
void Events::listener_configureX11(void* owner, void* data) {
@@ -708,7 +780,7 @@ void Events::listener_configureX11(void* owner, void* data) {
return;
}
if (!PWINDOW->m_uSurface.xwayland->mapped) {
if (!PWINDOW->m_uSurface.xwayland->mapped || !PWINDOW->m_bMappedX11) {
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
return;
}
@@ -731,7 +803,8 @@ void Events::listener_configureX11(void* owner, void* data) {
PWINDOW->m_bCreatedOverFullscreen = true;
g_pInputManager->refocus();
if (!PWINDOW->m_sAdditionalConfigData.windowDanceCompat)
g_pInputManager->refocus();
g_pHyprRenderer->damageWindow(PWINDOW);
@@ -814,15 +887,35 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
void Events::listener_requestMaximize(void* owner, void* data) {
const auto PWINDOW = (CWindow*)owner;
const auto EV = (wlr_foreign_toplevel_handle_v1_maximized_event*)data;
Debug::log(LOG, "Maximize request for %x", PWINDOW);
g_pCompositor->setWindowFullscreen(PWINDOW, EV ? EV->maximized : !PWINDOW->m_bIsFullscreen, FULLSCREEN_MAXIMIZED); // this will be rejected if there already is a fullscreen window
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
if (!PWINDOW->m_bIsX11) {
const auto EV = (wlr_foreign_toplevel_handle_v1_maximized_event*)data;
g_pCompositor->setWindowFullscreen(PWINDOW, EV ? EV->maximized : !PWINDOW->m_bIsFullscreen, FULLSCREEN_MAXIMIZED); // this will be rejected if there already is a fullscreen window
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
} else {
if (!PWINDOW->m_bMappedX11 || PWINDOW->m_iX11Type != 1)
return;
g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, FULLSCREEN_MAXIMIZED);
}
}
void Events::listener_requestMinimize(void* owner, void* data) {
// ignore
const auto PWINDOW = (CWindow*)owner;
Debug::log(LOG, "Minimize request for %x", PWINDOW);
// if (PWINDOW->m_bIsX11) {
// if (!PWINDOW->m_bMappedX11 || PWINDOW->m_iX11Type != 1)
// return;
// const auto E = (wlr_xwayland_minimize_event*)data;
// wlr_xwayland_surface_set_minimized(PWINDOW->m_uSurface.xwayland, E->minimize && g_pCompositor->m_pLastWindow != PWINDOW); // fucking DXVK
// }
}
void Events::listener_requestMove(void* owner, void* data) {

View File

@@ -99,10 +99,6 @@ void CMonitor::onConnect(bool noRule) {
wlr_output_enable(output, 1);
// TODO: this doesn't seem to set the X and Y correctly,
// wlr_output_layout_output_coords returns invalid values, I think...
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, output, monitorRule.offset.x, monitorRule.offset.y);
// set mode, also applies
if (!noRule)
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
@@ -136,6 +132,9 @@ void CMonitor::onConnect(bool noRule) {
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName});
// ensure VRR (will enable if necessary)
g_pConfigManager->ensureVRR(this);
}
void CMonitor::onDisconnect() {
@@ -152,6 +151,9 @@ void CMonitor::onDisconnect() {
}
}
if (g_pCompositor->m_pLastMonitor == this)
g_pCompositor->m_pLastMonitor = BACKUPMON;
// remove mirror
if (pMirrorOf) {
pMirrorOf->mirrors.erase(std::find_if(pMirrorOf->mirrors.begin(), pMirrorOf->mirrors.end(), [&](const auto& other) { return other == this; }));

View File

@@ -38,6 +38,8 @@ public:
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
bool dpmsStatus = true;
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
// mirroring
CMonitor* pMirrorOf = nullptr;

View File

@@ -131,6 +131,8 @@ struct SMouse {
bool virt = false;
bool connected = false; // means connected to the cursor
DYNLISTENER(commitConstraint);
DYNLISTENER(destroyMouse);

View File

@@ -0,0 +1,152 @@
#pragma once
#include <wayland-server.h>
typedef unsigned int xcb_atom_t;
struct xcb_icccm_wm_hints_t;
typedef struct {
/** User specified flags */
uint32_t flags;
/** User-specified position */
int32_t x, y;
/** User-specified size */
int32_t width, height;
/** Program-specified minimum size */
int32_t min_width, min_height;
/** Program-specified maximum size */
int32_t max_width, max_height;
/** Program-specified resize increments */
int32_t width_inc, height_inc;
/** Program-specified minimum aspect ratios */
int32_t min_aspect_num, min_aspect_den;
/** Program-specified maximum aspect ratios */
int32_t max_aspect_num, max_aspect_den;
/** Program-specified base size */
int32_t base_width, base_height;
/** Program-specified window gravity */
uint32_t win_gravity;
} xcb_size_hints_t;
typedef unsigned int xcb_window_t;
typedef enum xcb_stack_mode_t {
XCB_STACK_MODE_ABOVE = 0,
XCB_STACK_MODE_BELOW = 1,
XCB_STACK_MODE_TOP_IF = 2,
XCB_STACK_MODE_BOTTOM_IF = 3,
XCB_STACK_MODE_OPPOSITE = 4
} xcb_stack_mode_t;
struct wlr_xwayland {
struct wlr_xwayland_server *server;
struct wlr_xwm *xwm;
struct wlr_xwayland_cursor *cursor;
const char *display_name;
struct wl_display *wl_display;
struct wlr_compositor *compositor;
struct wlr_seat *seat;
void *data;
};
struct wlr_xwayland_surface {
xcb_window_t window_id;
struct wlr_xwm *xwm;
uint32_t surface_id;
struct wl_list link;
struct wl_list stack_link;
struct wl_list unpaired_link;
struct wlr_surface *surface;
int16_t x, y;
uint16_t width, height;
uint16_t saved_width, saved_height;
bool override_redirect;
bool mapped;
char *title;
char *_class;
char *instance;
char *role;
char *startup_id;
pid_t pid;
bool has_utf8_title;
struct wl_list children; // wlr_xwayland_surface::parent_link
struct wlr_xwayland_surface *parent;
struct wl_list parent_link; // wlr_xwayland_surface::children
xcb_atom_t *window_type;
size_t window_type_len;
xcb_atom_t *protocols;
size_t protocols_len;
uint32_t decorations;
xcb_icccm_wm_hints_t *hints;
xcb_size_hints_t *size_hints;
bool pinging;
struct wl_event_source *ping_timer;
// _NET_WM_STATE
bool modal;
bool fullscreen;
bool maximized_vert, maximized_horz;
bool minimized;
bool has_alpha;
struct {
struct wl_signal destroy;
struct wl_signal request_configure;
struct wl_signal request_move;
struct wl_signal request_resize;
struct wl_signal request_minimize;
struct wl_signal request_maximize;
struct wl_signal request_fullscreen;
struct wl_signal request_activate;
struct wl_signal map;
struct wl_signal unmap;
struct wl_signal set_title;
struct wl_signal set_class;
struct wl_signal set_role;
struct wl_signal set_parent;
struct wl_signal set_pid;
struct wl_signal set_startup_id;
struct wl_signal set_window_type;
struct wl_signal set_hints;
struct wl_signal set_decorations;
struct wl_signal set_override_redirect;
struct wl_signal set_geometry;
struct wl_signal ping_timeout;
} events;
};
struct wlr_xwayland_surface_configure_event {
struct wlr_xwayland_surface *surface;
int16_t x, y;
uint16_t width, height;
uint16_t mask; // xcb_config_window_t
};
inline void wlr_xwayland_destroy(wlr_xwayland*) { }
inline void wlr_xwayland_surface_configure(wlr_xwayland_surface*, int, int, int, int) { }
inline bool wlr_surface_is_xwayland_surface(void*) { return false; }
inline void wlr_xwayland_surface_activate(wlr_xwayland_surface*, bool) { }
inline void wlr_xwayland_surface_restack(wlr_xwayland_surface*, int, xcb_stack_mode_t) { }
inline wlr_xwayland_surface* wlr_xwayland_surface_from_wlr_surface(void*) { return nullptr; }
inline void wlr_xwayland_surface_close(wlr_xwayland_surface*) { }
inline void wlr_xwayland_surface_set_fullscreen(wlr_xwayland_surface*, bool) { }
inline void wlr_xwayland_surface_set_minimized(wlr_xwayland_surface *, bool) {}

View File

@@ -22,7 +22,6 @@
#include <filesystem>
#include <climits>
#if true
// wlroots uses dumb-ass shit that makes it not compile on C++, let's fix that.
// https://github.com/swaywm/wlroots/issues/682
@@ -80,13 +79,11 @@ extern "C" {
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/util/log.h>
#include <wlr/xwayland.h>
#include <wlr/util/region.h>
#include <wlr/types/wlr_tablet_pad.h>
#include <wlr/types/wlr_tablet_tool.h>
#include <wlr/types/wlr_tablet_v2.h>
#include <xkbcommon/xkbcommon.h>
#include <X11/Xproto.h>
#include <wlr/render/egl.h>
#include <wlr/render/gles2.h>
#include <wlr/render/wlr_texture.h>
@@ -102,6 +99,13 @@ extern "C" {
#include <wlr/types/wlr_text_input_v3.h>
#include <wlr/types/wlr_touch.h>
#include <wlr/types/wlr_switch.h>
#include <drm_fourcc.h>
#ifndef NO_XWAYLAND
#include <wlr/xwayland.h>
#include <X11/Xproto.h>
#endif
}
#undef delete
@@ -122,6 +126,7 @@ extern "C" {
#ifdef NO_XWAYLAND
#define XWAYLAND false
#include "helpers/XWaylandStubs.hpp"
#else
#define XWAYLAND true
#endif

View File

@@ -26,6 +26,9 @@ void IHyprLayout::onWindowRemoved(CWindow* pWindow) {
} else {
onWindowRemovedTiling(pWindow);
}
if (pWindow == m_pLastTiledWindow)
m_pLastTiledWindow = nullptr;
}
void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) {
@@ -208,7 +211,12 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
if (g_pInputManager->dragMode == MBIND_MOVE) {
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
if (*PANIMATE) {
DRAGGINGWINDOW->m_vRealPosition = m_vBeginDragPositionXY + DELTA;
} else {
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
}
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
} else if (g_pInputManager->dragMode == MBIND_RESIZE) {
@@ -296,6 +304,9 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
pWindow->m_vLastFloatingSize = PSAVEDSIZE;
// move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back.
pWindow->m_vPosition = Vector2D(-999999, -999999);
onWindowCreatedTiling(pWindow);
pWindow->m_vRealPosition.setValue(PSAVEDPOS);
@@ -303,6 +314,9 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
// fix pseudo leaving artifacts
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
if (pWindow == g_pCompositor->m_pLastWindow)
m_pLastTiledWindow = pWindow;
} else {
pWindow->m_vSize = pWindow->m_vRealSize.vec();
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
@@ -317,6 +331,9 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
pWindow->m_sSpecialRenderData.rounding = true;
if (pWindow == m_pLastTiledWindow)
m_pLastTiledWindow = nullptr;
}
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
@@ -339,3 +356,47 @@ void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
g_pHyprRenderer->damageWindow(PWINDOW);
}
void IHyprLayout::onWindowFocusChange(CWindow* pNewFocus) {
m_pLastTiledWindow = pNewFocus && !pNewFocus->m_bIsFloating ? pNewFocus : m_pLastTiledWindow;
}
CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
// although we don't expect nullptrs here, let's verify jic
if (!pWindow)
return nullptr;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
// first of all, if this is a fullscreen workspace,
if (PWORKSPACE->m_bHasFullscreenWindow)
return g_pCompositor->getFullscreenWindowOnWorkspace(pWindow->m_iWorkspaceID);
if (pWindow->m_bIsFloating) {
// the window was floating, let's try the last tiled window.
if (m_pLastTiledWindow && m_pLastTiledWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID)
return m_pLastTiledWindow;
// if we don't, let's try to find any window that is in the middle
if (const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f); PWINDOWCANDIDATE)
return PWINDOWCANDIDATE;
// if not, floating window
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && !w->m_bX11ShouldntFocus && !w->m_bNoFocus)
return w.get();
}
// if there is no candidate, too bad
return nullptr;
}
// if it was a tiled window, we first try to find the window that will replace it.
const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->m_vRealPosition.goalv() + pWindow->m_vRealSize.goalv() / 2.f);
if (!PWINDOWCANDIDATE || pWindow == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->isHidden() || PWINDOWCANDIDATE->m_bX11ShouldntFocus || PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID)
return nullptr;
return PWINDOWCANDIDATE;
}

View File

@@ -123,10 +123,22 @@ public:
*/
virtual std::string getLayoutName() = 0;
/*
Called for getting the next candidate for a focus
*/
virtual CWindow* getNextWindowCandidate(CWindow*);
/*
Internal: called when window focus changes
*/
virtual void onWindowFocusChange(CWindow*);
private:
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;
Vector2D m_vBeginDragPositionXY;
Vector2D m_vBeginDragSizeXY;
int m_iGrabbedCorner = 0;
CWindow* m_pLastTiledWindow = nullptr;
};

View File

@@ -18,6 +18,23 @@
CEventManager::CEventManager() {
}
int fdHandleWrite(int fd, uint32_t mask, void* data) {
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP) {
// remove, hanged up
const auto ACCEPTEDFDS = (std::deque<std::pair<int, wl_event_source*>>*)data;
for (auto it = ACCEPTEDFDS->begin(); it != ACCEPTEDFDS->end(); ) {
if (it->first == fd) {
wl_event_source_remove(it->second); // remove this fd listener
it = ACCEPTEDFDS->erase(it);
} else {
it++;
}
}
}
return 0;
}
void CEventManager::startThread() {
m_tThread = std::thread([&]() {
const auto SOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -46,12 +63,14 @@ void CEventManager::startThread() {
if (ACCEPTEDCONNECTION > 0) {
// new connection!
m_dAcceptedSocketFDs.push_back(ACCEPTEDCONNECTION);
int flagsNew = fcntl(ACCEPTEDCONNECTION, F_GETFL, 0);
fcntl(ACCEPTEDCONNECTION, F_SETFL, flagsNew | O_NONBLOCK);
Debug::log(LOG, "Socket 2 accepted a new client at FD %d", ACCEPTEDCONNECTION);
// add to event loop so we can close it when we need to
m_dAcceptedSocketFDs.push_back({ACCEPTEDCONNECTION, wl_event_loop_add_fd(g_pCompositor->m_sWLEventLoop, ACCEPTEDCONNECTION, WL_EVENT_READABLE, fdHandleWrite, &m_dAcceptedSocketFDs)});
}
ensureFDsValid();
@@ -68,7 +87,7 @@ void CEventManager::ensureFDsValid() {
// pong if all FDs valid
for (auto it = m_dAcceptedSocketFDs.begin(); it != m_dAcceptedSocketFDs.end();) {
auto sizeRead = recv(*it, &readBuf, 1024, 0);
auto sizeRead = recv(it->first, &readBuf, 1024, 0);
if (sizeRead != 0) {
it++;
@@ -90,7 +109,7 @@ void CEventManager::flushEvents() {
for (auto& ev : m_dQueuedEvents) {
std::string eventString = (ev.event + ">>" + ev.data).substr(0, 1022) + "\n";
for (auto& fd : m_dAcceptedSocketFDs) {
write(fd, eventString.c_str(), eventString.length());
write(fd.first, eventString.c_str(), eventString.length());
}
}

View File

@@ -31,7 +31,7 @@ private:
std::mutex eventQueueMutex;
std::deque<SHyprIPCEvent> m_dQueuedEvents;
std::deque<int> m_dAcceptedSocketFDs;
std::deque<std::pair<int, wl_event_source*>> m_dAcceptedSocketFDs;
};
inline std::unique_ptr<CEventManager> g_pEventManager;

View File

@@ -769,7 +769,7 @@ void CKeybindManager::changeworkspace(std::string args) {
if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE)
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
const auto PWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(PMONITOR->ID, workspaceName, workspaceToChangeTo == SPECIAL_WORKSPACE_ID)).get();
const auto PWORKSPACE = g_pCompositor->createNewWorkspace(workspaceToChangeTo, PMONITOR->ID, workspaceName);
if (!isSwitchingToPrevious)
// Remember previous workspace.
@@ -778,13 +778,6 @@ void CKeybindManager::changeworkspace(std::string args) {
// start anim on new workspace
PWORKSPACE->startAnim(true, ANIMTOLEFT);
// We are required to set the name here immediately
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;
PMONITOR->specialWorkspaceOpen = false;
// fix pinned windows
@@ -897,7 +890,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
// and restore it
if (PWINDOW->m_bIsFloating) {
PWINDOW->m_vRealSize.setValue(PSAVEDSIZE);
PWINDOW->m_vRealSize.setValueAndWarp(PSAVEDSIZE);
PWINDOW->m_vRealPosition.setValueAndWarp(PSAVEDPOS - g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID)->vecPosition + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
}
@@ -1429,9 +1422,6 @@ void CKeybindManager::resizeWindow(std::string args) {
}
void CKeybindManager::circleNext(std::string arg) {
if (!g_pCompositor->m_pLastWindow)
return;
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
if (PWINDOWTOCHANGETO == g_pCompositor->m_pLastWindow || !PWINDOWTOCHANGETO)
return;
@@ -1454,6 +1444,17 @@ void CKeybindManager::circleNext(std::string arg) {
}
};
if (!g_pCompositor->m_pLastWindow) {
// if we have a clear focus, find the first window and get the next focusable.
if (g_pCompositor->getWindowsOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace) > 0) {
const auto PWINDOW = g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace), true);
switchToWindow(PWINDOW);
}
return;
}
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow, true));
else

View File

@@ -3,23 +3,23 @@
#include "../events/Events.hpp"
CHyprXWaylandManager::CHyprXWaylandManager() {
if (XWAYLAND) {
m_sWLRXWayland = wlr_xwayland_create(g_pCompositor->m_sWLDisplay, g_pCompositor->m_sWLRCompositor, 1);
#ifndef NO_XWAYLAND
m_sWLRXWayland = wlr_xwayland_create(g_pCompositor->m_sWLDisplay, g_pCompositor->m_sWLRCompositor, 1);
if (!m_sWLRXWayland) {
Debug::log(ERR, "Couldn't start up the XWaylandManager because wlr_xwayland_create returned a nullptr!");
return;
}
addWLSignal(&m_sWLRXWayland->events.ready, &Events::listen_readyXWayland, m_sWLRXWayland, "XWayland Manager");
addWLSignal(&m_sWLRXWayland->events.new_surface, &Events::listen_surfaceXWayland, m_sWLRXWayland, "XWayland Manager");
setenv("DISPLAY", m_sWLRXWayland->display_name, 1);
Debug::log(LOG, "CHyprXWaylandManager started on display %s", m_sWLRXWayland->display_name);
} else {
unsetenv("DISPLAY"); // unset DISPLAY so that X11 apps do not try to start on a different/invalid DISPLAY
if (!m_sWLRXWayland) {
Debug::log(ERR, "Couldn't start up the XWaylandManager because wlr_xwayland_create returned a nullptr!");
return;
}
addWLSignal(&m_sWLRXWayland->events.ready, &Events::listen_readyXWayland, m_sWLRXWayland, "XWayland Manager");
addWLSignal(&m_sWLRXWayland->events.new_surface, &Events::listen_surfaceXWayland, m_sWLRXWayland, "XWayland Manager");
setenv("DISPLAY", m_sWLRXWayland->display_name, 1);
Debug::log(LOG, "CHyprXWaylandManager started on display %s", m_sWLRXWayland->display_name);
#else
unsetenv("DISPLAY"); // unset DISPLAY so that X11 apps do not try to start on a different/invalid DISPLAY
#endif
}
CHyprXWaylandManager::~CHyprXWaylandManager() {
@@ -53,17 +53,21 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
if (pWindow->m_bIsX11) {
if (pWindow->m_uSurface.xwayland->minimized)
wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false);
if (activate) {
wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false);
wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, NULL, XCB_STACK_MODE_ABOVE);
}
wlr_xwayland_surface_activate(pWindow->m_uSurface.xwayland, activate);
wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, NULL, XCB_STACK_MODE_ABOVE);
}
else
wlr_xdg_toplevel_set_activated(pWindow->m_uSurface.xdg->toplevel, activate);
g_pCompositor->m_pLastFocus = getWindowSurface(pWindow);
g_pCompositor->m_pLastWindow = pWindow;
if (activate) {
g_pCompositor->m_pLastFocus = getWindowSurface(pWindow);
g_pCompositor->m_pLastWindow = pWindow;
}
if (!pWindow->m_bPinned)
g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_pLastFocusedWindow = pWindow;

View File

@@ -39,7 +39,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
m_pFoundLSToFocus = nullptr;
m_pFoundWindowToFocus = nullptr;
if (!g_pCompositor->m_bReadyToProcess)
if (!g_pCompositor->m_bReadyToProcess || g_pCompositor->m_bIsShuttingDown)
return;
if (!g_pCompositor->m_sSeat.mouse) {
@@ -157,26 +157,22 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
return;
}
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
surfacePos = pFoundWindow->m_vRealPosition.vec();
// only check floating because tiled cant be over fullscreen
for (auto w = g_pCompositor->m_vWindows.rbegin(); w != g_pCompositor->m_vWindows.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 || (*w)->m_bPinned)) || ((*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->isHidden()) {
pFoundWindow = (*w).get();
if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
surfacePos = Vector2D(-1337, -1337);
} else {
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
surfacePos = pFoundWindow->m_vRealPosition.vec();
}
break;
}
}
if (!pFoundWindow->m_bIsX11) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
surfacePos = Vector2D(-1337, -1337);
} else {
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
surfacePos = pFoundWindow->m_vRealPosition.vec();
}
}
// then windows
@@ -311,7 +307,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
} else {
if (pFoundLayerSurface && pFoundLayerSurface->layerSurface->current.keyboard_interactive && *PFOLLOWMOUSE != 3 && allowKeyboardRefocus) {
g_pCompositor->focusSurface(foundSurface);
g_pCompositor->m_pLastWindow = nullptr; // reset last window as we have a full focus on a LS
}
if (pFoundLayerSurface)
@@ -684,6 +679,8 @@ void CInputManager::newMouse(wlr_input_device* mouse, bool virt) {
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, mouse);
PMOUSE->connected = true;
g_pCompositor->m_sSeat.mouse = PMOUSE;
m_tmrLastCursorMovement.reset();
@@ -700,6 +697,17 @@ void CInputManager::setPointerConfigs() {
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(devname);
if (HASCONFIG) {
const auto ENABLED = g_pConfigManager->getDeviceInt(devname, "enabled");
if (ENABLED && !m.connected) {
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, m.mouse);
m.connected = true;
} else if (!ENABLED && m.connected) {
wlr_cursor_detach_input_device(g_pCompositor->m_sWLRCursor, m.mouse);
m.connected = false;
}
}
if (wlr_input_device_is_libinput(m.mouse)) {
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.mouse);

View File

@@ -301,7 +301,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
Debug::log(ERR, "Enabling TextInput on no IME!");
Debug::log(WARN, "Enabling TextInput on no IME!");
return;
}
@@ -317,12 +317,12 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
Debug::log(ERR, "Committing TextInput on no IME!");
Debug::log(WARN, "Committing TextInput on no IME!");
return;
}
if (!PINPUT->pWlrInput->current_enabled) {
Debug::log(ERR, "Disabled TextInput commit?");
Debug::log(WARN, "Disabled TextInput commit?");
return;
}
@@ -335,7 +335,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
Debug::log(ERR, "Disabling TextInput on no IME!");
Debug::log(WARN, "Disabling TextInput on no IME!");
return;
}
@@ -352,7 +352,7 @@ void CInputMethodRelay::createNewTextInput(wlr_text_input_v3* pInput) {
const auto PINPUT = (STextInput*)owner;
if (!g_pInputManager->m_sIMERelay.m_pWLRIME) {
Debug::log(ERR, "Disabling TextInput on no IME!");
Debug::log(WARN, "Disabling TextInput on no IME!");
return;
}

View File

@@ -4,6 +4,7 @@
void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
static auto *const PSWIPE = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe")->intValue;
static auto *const PSWIPEFINGERS = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_fingers")->intValue;
static auto *const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue;
if (e->fingers != *PSWIPEFINGERS || *PSWIPE == 0)
return;
@@ -15,7 +16,7 @@ void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
}
}
if (onMonitor < 2)
if (onMonitor < 2 && !*PSWIPENEW)
return; // disallow swiping when there's 1 workspace on a monitor
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
@@ -42,6 +43,7 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
static auto *const PSWIPEPERC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio")->floatValue;
static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
static auto *const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue;
static auto *const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue;
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert";
// commit
@@ -49,7 +51,11 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
if ((workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID || workspaceIDRight == workspaceIDLeft) && *PSWIPENEW) {
workspaceIDRight = m_sActiveSwipe.pWorkspaceBegin->m_iID > 0 ? m_sActiveSwipe.pWorkspaceBegin->m_iID + 1 : 1;
}
auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec();
@@ -60,7 +66,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
// revert
if (abs(m_sActiveSwipe.delta) < 2) {
PWORKSPACEL->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
PWORKSPACER->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
if (PWORKSPACER)
PWORKSPACER->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
} else {
if (m_sActiveSwipe.delta < 0) {
@@ -69,7 +76,7 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
PWORKSPACEL->m_vRenderOffset = Vector2D({0, -m_sActiveSwipe.pMonitor->vecSize.y});
else
PWORKSPACEL->m_vRenderOffset = Vector2D({-m_sActiveSwipe.pMonitor->vecSize.x, 0});
} else {
} else if (PWORKSPACER) {
// to right
if (VERTANIMS)
PWORKSPACER->m_vRenderOffset = Vector2D({0, m_sActiveSwipe.pMonitor->vecSize.y});
@@ -104,9 +111,15 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
pSwitchedTo = PWORKSPACEL;
} else {
// switch to right
const auto RENDEROFFSET = PWORKSPACER->m_vRenderOffset.vec();
const auto RENDEROFFSET = PWORKSPACER ? PWORKSPACER->m_vRenderOffset.vec() : Vector2D();
g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDRight));
if (PWORKSPACER)
g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDRight));
else
g_pKeybindManager->m_mDispatchers["workspace"](std::to_string(workspaceIDRight)); // so that the ID is created properly
if (!PWORKSPACER)
PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed on PSWIPENEW
PWORKSPACER->m_vRenderOffset.setValue(RENDEROFFSET);
PWORKSPACER->m_fAlpha.setValueAndWarp(255.f);
@@ -128,7 +141,8 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
PWORKSPACEL->m_bForceRendering = false;
PWORKSPACER->m_bForceRendering = false;
if (PWORKSPACER)
PWORKSPACER->m_bForceRendering = false;
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = false;
m_sActiveSwipe.pWorkspaceBegin = nullptr;
@@ -137,7 +151,7 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
// apply alpha
for (auto& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
ls->alpha = pSwitchedTo->m_bHasFullscreenWindow ? 0.f : 255.f;
ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FULLSCREEN_FULL ? 0.f : 255.f;
}
}
@@ -147,6 +161,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
static auto *const PSWIPEINVR = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_invert")->intValue;
static auto *const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue;
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert";
@@ -159,7 +174,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
if (workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) {
if ((workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !*PSWIPENEW) {
m_sActiveSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe
return;
}
@@ -168,8 +183,13 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
m_sActiveSwipe.delta = std::clamp(m_sActiveSwipe.delta, (double)-*PSWIPEDIST, (double)*PSWIPEDIST);
if (((m_sActiveSwipe.pWorkspaceBegin->m_iID == workspaceIDLeft || m_sActiveSwipe.pWorkspaceBegin->m_iID == workspaceIDRight) && *PSWIPENEW && (m_sActiveSwipe.delta < 0)) || (m_sActiveSwipe.delta > 0 && g_pCompositor->getWindowsOnWorkspace(m_sActiveSwipe.pWorkspaceBegin->m_iID) == 0 && workspaceIDRight <= m_sActiveSwipe.pWorkspaceBegin->m_iID)) {
m_sActiveSwipe.delta = 0;
return;
}
if (m_sActiveSwipe.delta < 0) {
if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID){
if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID && !*PSWIPENEW){
m_sActiveSwipe.delta = 0;
return;
}
@@ -196,7 +216,18 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft);
} else {
if (workspaceIDRight < m_sActiveSwipe.pWorkspaceBegin->m_iID){
if (workspaceIDRight < m_sActiveSwipe.pWorkspaceBegin->m_iID) {
if (*PSWIPENEW) {
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
if (VERTANIMS)
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y));
else
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID);
return;
}
m_sActiveSwipe.delta = 0;
return;
}

View File

@@ -11,7 +11,7 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
PMONITOR = PMONITOR ? PMONITOR : g_pCompositor->m_pLastMonitor;
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
refocus();

View File

@@ -18,7 +18,7 @@ executable('Hyprland', src,
xcb_dep,
dependency('pixman-1'),
dependency('GL'),
dependency('GL', 'opengl'),
dependency('threads')
],
install : true

View File

@@ -74,6 +74,7 @@ void CFramebuffer::release() {
m_cTex.m_iTexID = 0;
m_iFb = -1;
m_Size = Vector2D();
}
CFramebuffer::~CFramebuffer() {

View File

@@ -329,7 +329,12 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
glUseProgram(m_RenderData.pCurrentMonData->m_shQUAD.program);
#ifndef GLES2
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shQUAD.proj, 1, GL_FALSE, glMatrix);
#endif
glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
wlr_box transformedBox;
@@ -438,7 +443,12 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
glUseProgram(shader->program);
#ifndef GLES2
glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix);
#endif
glUniform1i(shader->tex, 0);
glUniform1f(shader->alpha, alpha / 255.f);
glUniform1i(shader->discardOpaque, (int)discardOpaque);
@@ -562,7 +572,12 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
glUseProgram(pShader->program);
// prep two shaders
#ifndef GLES2
glUniformMatrix3fv(pShader->proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
#endif
glUniform1f(pShader->radius, *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1)
glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
@@ -799,7 +814,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
if (!pixman_region32_not_empty(m_RenderData.pDamage))
if (!pixman_region32_not_empty(m_RenderData.pDamage) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder))
return;
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
@@ -843,7 +858,12 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
glUseProgram(m_RenderData.pCurrentMonData->m_shBORDER1.program);
#ifndef GLES2
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
#endif
glUniform4f(m_RenderData.pCurrentMonData->m_shBORDER1.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
const auto TOPLEFT = Vector2D(round, round);
@@ -975,9 +995,14 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
const auto BLURLSSTATUS = pLayer->forceBlur;
pLayer->forceBlur = false;
// draw the layer
g_pHyprRenderer->renderLayer(pLayer, PMONITOR, &now);
pLayer->forceBlur = BLURLSSTATUS;
// TODO: WARN:
// revise if any stencil-requiring rendering is done to the layers.
@@ -1098,7 +1123,12 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
glUseProgram(m_RenderData.pCurrentMonData->m_shSHADOW.program);
#ifndef GLES2
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
#endif
glUniform4f(m_RenderData.pCurrentMonData->m_shSHADOW.color, col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
const auto TOPLEFT = Vector2D(range + round, range + round);

View File

@@ -760,9 +760,15 @@ void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) {
PMONITOR->vecReservedTopLeft = Vector2D(usableArea.x, usableArea.y) - PMONITOR->vecPosition;
PMONITOR->vecReservedBottomRight = PMONITOR->vecSize - Vector2D(usableArea.width, usableArea.height) - PMONITOR->vecReservedTopLeft;
const auto ENTRY = g_pConfigManager->m_mAdditionalReservedAreas[PMONITOR->szName];
PMONITOR->vecReservedTopLeft = PMONITOR->vecReservedTopLeft + Vector2D(ENTRY.left, ENTRY.top);
PMONITOR->vecReservedBottomRight = PMONITOR->vecReservedBottomRight + Vector2D(ENTRY.right, ENTRY.bottom);
auto ADDITIONALRESERVED = g_pConfigManager->m_mAdditionalReservedAreas.find(PMONITOR->szName);
if (ADDITIONALRESERVED == g_pConfigManager->m_mAdditionalReservedAreas.end()) {
ADDITIONALRESERVED = g_pConfigManager->m_mAdditionalReservedAreas.find(""); // glob wildcard
}
if (ADDITIONALRESERVED != g_pConfigManager->m_mAdditionalReservedAreas.end()) {
PMONITOR->vecReservedTopLeft = PMONITOR->vecReservedTopLeft + Vector2D(ADDITIONALRESERVED->second.left, ADDITIONALRESERVED->second.top);
PMONITOR->vecReservedBottomRight = PMONITOR->vecReservedBottomRight + Vector2D(ADDITIONALRESERVED->second.right, ADDITIONALRESERVED->second.bottom);
}
// damage the monitor if can
if (PMONITOR->damage)
@@ -944,7 +950,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
&& DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1)
&& pMonitor->scale == pMonitorRule->scale
&& ((DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) || pMonitorRule->offset == Vector2D(-1, -1))
&& pMonitor->transform == pMonitorRule->transform) {
&& pMonitor->transform == pMonitorRule->transform
&& pMonitorRule->enable10bit == pMonitor->enabled10bit) {
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
return true;
@@ -1147,18 +1154,36 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
}
pMonitor->vrrActive = pMonitor->output->pending.adaptive_sync_enabled; // disabled here, will be tested in CConfigManager::ensureVRR()
wlr_output_set_transform(pMonitor->output, pMonitorRule->transform);
pMonitor->transform = pMonitorRule->transform;
pMonitor->vecPixelSize = pMonitor->vecSize;
// Adaptive sync (VRR)
wlr_output_enable_adaptive_sync(pMonitor->output, 1);
if (pMonitorRule->enable10bit) {
// try 10b RGB
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XRGB2101010);
pMonitor->enabled10bit = true;
if (!wlr_output_test(pMonitor->output)) {
Debug::log(LOG, "Pending output %s does not accept VRR.", pMonitor->output->name);
wlr_output_enable_adaptive_sync(pMonitor->output, 0);
if (!wlr_output_test(pMonitor->output)) {
Debug::log(ERR, "Output %s -> 10 bit enabled, but failed format DRM_FORMAT_XRGB2101010. Trying BGR.", pMonitor->output->name);
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XBGR2101010);
if (!wlr_output_test(pMonitor->output)) {
Debug::log(ERR, "Output %s -> 10 bit enabled, but failed format DRM_FORMAT_XBGR2101010. Falling back to 8 bit.", pMonitor->output->name);
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XRGB8888);
} else {
Debug::log(LOG, "10bit format DRM_FORMAT_XBGR2101010 succeeded for output %s", pMonitor->output->name);
}
} else {
Debug::log(LOG, "10bit format DRM_FORMAT_XRGB2101010 succeeded for output %s", pMonitor->output->name);
}
} else {
wlr_output_set_render_format(pMonitor->output, DRM_FORMAT_XRGB8888);
pMonitor->enabled10bit = false;
}
if (!wlr_output_commit(pMonitor->output)) {
@@ -1189,15 +1214,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
pMonitor->vecPosition = pMonitorRule->offset;
}
if (!pMonitor->isMirror())
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
wlr_output_enable(pMonitor->output, true);
// update renderer (here because it will call rollback, so we cannot do this before committing)
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
// updato wlroots
wlr_output_layout_add(g_pCompositor->m_sWLROutputLayout, pMonitor->output, (int)pMonitor->vecPosition.x, (int)pMonitor->vecPosition.y);
Events::listener_change(nullptr, nullptr);
// updato us

View File

@@ -59,6 +59,9 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
if (!m_pWindow->m_sSpecialRenderData.decorate)
return;
if (m_pWindow->m_sAdditionalConfigData.forceNoShadow)
return;
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;