mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-14 11:35:46 -07:00
Compare commits
40 Commits
v0.19.0bet
...
v0.19.2bet
Author | SHA1 | Date | |
---|---|---|---|
|
111d209bff | ||
|
b45a213413 | ||
|
1a9ee959dd | ||
|
46891b12cf | ||
|
0c1bec023f | ||
|
80f58bc93f | ||
|
06e6c6021e | ||
|
e8b99ae13a | ||
|
bb99f151da | ||
|
f97289a3c0 | ||
|
6381b6474f | ||
|
c3f1dc3f52 | ||
|
62f4503f07 | ||
|
bf78dcecf0 | ||
|
d5352a5d12 | ||
|
fd43d2bea7 | ||
|
b9812f8bc0 | ||
|
fba03540d5 | ||
|
11a1a6c271 | ||
|
ff12a41c40 | ||
|
629cca4816 | ||
|
9fc143cf3d | ||
|
726732244a | ||
|
be6e1a33b1 | ||
|
6e3bd440ba | ||
|
cba10ba5b7 | ||
|
050693be2e | ||
|
0803febac5 | ||
|
6259202c01 | ||
|
e1d7a13333 | ||
|
bf5844d607 | ||
|
5b7fec481b | ||
|
73b3bbe49b | ||
|
d8dcf670da | ||
|
87b9313034 | ||
|
993c382e74 | ||
|
3c9a7811b8 | ||
|
6c8d993477 | ||
|
dfa9277867 | ||
|
50e37419e9 |
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
|
||||
- name: Create tarball with submodules
|
||||
id: tar
|
||||
run: mkdir hyprland-source; mv ./* ./hyprland-source; tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
|
||||
run: mkdir hyprland-source; mv ./* ./hyprland-source || tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
|
||||
|
||||
- id: whatrelease
|
||||
name: Get latest release
|
||||
|
@@ -22,7 +22,7 @@ execute_process(
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
execute_process(
|
||||
COMMAND sh -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -s 's/#|\"//g'"
|
||||
COMMAND sh -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g'"
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
@@ -89,6 +89,16 @@ message(STATUS "Setting link libraries")
|
||||
|
||||
target_link_libraries(Hyprland PkgConfig::deps)
|
||||
|
||||
IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Setting debug flags")
|
||||
|
||||
target_link_libraries(Hyprland asan)
|
||||
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg -no-pie -fno-builtin -fsanitize=address")
|
||||
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)
|
||||
|
||||
target_link_libraries(Hyprland
|
||||
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 # wlroots is provided by us
|
||||
pixman-1
|
||||
@@ -97,13 +107,6 @@ target_link_libraries(Hyprland
|
||||
pthread
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${CMAKE_SOURCE_DIR}/ext-workspace-unstable-v1-protocol.o
|
||||
${CMAKE_SOURCE_DIR}/wlr-foreign-toplevel-management-unstable-v1-protocol.o
|
||||
${CMAKE_SOURCE_DIR}/hyprland-toplevel-export-v1-protocol.o
|
||||
)
|
||||
|
||||
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)
|
||||
|
12
Makefile
12
Makefile
@@ -111,6 +111,16 @@ linux-dmabuf-unstable-v1-protocol.c:
|
||||
|
||||
linux-dmabuf-unstable-v1-protocol.o: linux-dmabuf-unstable-v1-protocol.h
|
||||
|
||||
wlr-foreign-toplevel-management-unstable-v1-protocol.h:
|
||||
$(WAYLAND_SCANNER) server-header \
|
||||
protocols/wlr-foreign-toplevel-management-unstable-v1.xml $@
|
||||
|
||||
wlr-foreign-toplevel-management-unstable-v1-protocol.c:
|
||||
$(WAYLAND_SCANNER) private-code \
|
||||
protocols/wlr-foreign-toplevel-management-unstable-v1.xml $@
|
||||
|
||||
wlr-foreign-toplevel-management-unstable-v1-protocol.o: wlr-foreign-toplevel-management-unstable-v1-protocol.h
|
||||
|
||||
legacyrenderer:
|
||||
mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:STRING=true -H./ -B./build -G Ninja
|
||||
cmake --build ./build --config Release --target all -j$(shell nproc)
|
||||
@@ -189,7 +199,7 @@ uninstall:
|
||||
rm -f ${PREFIX}/share/man/man1/Hyprland.1
|
||||
rm -f ${PREFIX}/share/man/man1/hyprctl.1
|
||||
|
||||
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o
|
||||
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o wlr-output-power-management-unstable-v1-protocol.o linux-dmabuf-unstable-v1-protocol.o hyprland-toplevel-export-v1-protocol.o wlr-foreign-toplevel-management-unstable-v1-protocol.o
|
||||
|
||||
fixwlr:
|
||||
sed -i -E 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build
|
||||
|
12
flake.lock
generated
12
flake.lock
generated
@@ -3,11 +3,11 @@
|
||||
"hyprland-protocols": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1670258048,
|
||||
"narHash": "sha256-Lm2sXnDVZNE+taHqsqVibvPmSdu65VHvXI507KVX4lg=",
|
||||
"lastModified": 1670703428,
|
||||
"narHash": "sha256-4KUW5SKR0Y9uaYGcYwy53YJ3B/sgiprCL4fRGO+mpOA=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprland-protocols",
|
||||
"rev": "0dcff94fc10df2bbb66d3e1b5a1d6cfd3ada5515",
|
||||
"rev": "d0d6db8cb5bef6d93ca3ad8fb2124964173396da",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -82,11 +82,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1670202338,
|
||||
"narHash": "sha256-StTfshdAoSxO+t0wRbq1I3YESLFIQWFjGJse5ICV8rk=",
|
||||
"lastModified": 1670797151,
|
||||
"narHash": "sha256-ZFzJHqSXhGCjSeMgqTyJG1KJ2Nlwa+NEN9K4oGhWcjg=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "af840a9e0947a79a37a95a9f62062653721e43fa",
|
||||
"rev": "36ffb6892e14b9c5be6e321b3c47fe286ac256e6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -77,6 +77,10 @@
|
||||
waybar-hyprland = prev.waybar.overrideAttrs (oldAttrs: {
|
||||
mesonFlags = oldAttrs.mesonFlags ++ ["-Dexperimental=true"];
|
||||
});
|
||||
|
||||
xdg-desktop-portal-hyprland = inputs.xdph.packages.${prev.system}.default.override {
|
||||
hyprland-share-picker = inputs.xdph.packages.${prev.system}.hyprland-share-picker.override {inherit hyprland;};
|
||||
};
|
||||
};
|
||||
|
||||
packages = genSystems (system:
|
||||
|
@@ -7,6 +7,11 @@ inputs: {
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.programs.hyprland;
|
||||
|
||||
defaultHyprlandPackage = inputs.self.packages.${pkgs.system}.default.override {
|
||||
enableXWayland = cfg.xwayland.enable;
|
||||
hidpiXWayland = cfg.xwayland.hidpi;
|
||||
};
|
||||
in {
|
||||
imports = [
|
||||
(mkRemovedOptionModule ["programs" "hyprland" "extraPackages"] "extraPackages has been removed. Use environment.systemPackages instead.")
|
||||
@@ -23,7 +28,7 @@ in {
|
||||
|
||||
package = mkOption {
|
||||
type = types.nullOr types.package;
|
||||
default = inputs.self.packages.${pkgs.system}.default;
|
||||
default = defaultHyprlandPackage;
|
||||
defaultText = literalExpression "<Hyprland flake>.packages.<system>.default";
|
||||
example = literalExpression "<Hyprland flake>.packages.<system>.default.override { }";
|
||||
description = ''
|
||||
@@ -31,6 +36,23 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
xwayland = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Enable XWayland.
|
||||
'';
|
||||
};
|
||||
hidpi = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Enable HiDPI XWayland.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
recommendedEnvironment = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
@@ -44,7 +66,7 @@ in {
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment = {
|
||||
systemPackages = lib.optional (cfg.package != null) cfg.package;
|
||||
systemPackages = lib.optional (cfg.package != null) defaultHyprlandPackage;
|
||||
|
||||
sessionVariables = mkIf cfg.recommendedEnvironment {
|
||||
NIXOS_OZONE_WL = "1";
|
||||
@@ -57,11 +79,17 @@ in {
|
||||
xwayland.enable = mkDefault true;
|
||||
};
|
||||
security.polkit.enable = true;
|
||||
services.xserver.displayManager.sessionPackages = lib.optional (cfg.package != null) cfg.package;
|
||||
services.xserver.displayManager.sessionPackages = lib.optional (cfg.package != null) defaultHyprlandPackage;
|
||||
xdg.portal = {
|
||||
enable = mkDefault true;
|
||||
# xdg-desktop-portal-hyprland
|
||||
extraPortals = [inputs.xdph.packages.${pkgs.system}.default];
|
||||
extraPortals = lib.mkIf (cfg.package != null) [
|
||||
(inputs.xdph.packages.${pkgs.system}.xdg-desktop-portal-hyprland.override {
|
||||
hyprland-share-picker = inputs.xdph.packages.${pkgs.system}.hyprland-share-picker.override {
|
||||
hyprland = defaultHyprlandPackage;
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ wayland_scanner = find_program(
|
||||
protocols = [
|
||||
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
|
||||
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
|
||||
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
||||
['wlr-layer-shell-unstable-v1.xml'],
|
||||
['wlr-output-power-management-unstable-v1.xml'],
|
||||
['ext-workspace-unstable-v1.xml'],
|
||||
|
270
protocols/wlr-foreign-toplevel-management-unstable-v1.xml
Normal file
270
protocols/wlr-foreign-toplevel-management-unstable-v1.xml
Normal file
@@ -0,0 +1,270 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="wlr_foreign_toplevel_management_unstable_v1">
|
||||
<copyright>
|
||||
Copyright © 2018 Ilia Bozhinov
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in
|
||||
all copies and that both that copyright notice and this permission
|
||||
notice appear in supporting documentation, and that the name of
|
||||
the copyright holders not be used in advertising or publicity
|
||||
pertaining to distribution of the software without specific,
|
||||
written prior permission. The copyright holders make no
|
||||
representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied
|
||||
warranty.
|
||||
|
||||
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zwlr_foreign_toplevel_manager_v1" version="3">
|
||||
<description summary="list and control opened apps">
|
||||
The purpose of this protocol is to enable the creation of taskbars
|
||||
and docks by providing them with a list of opened applications and
|
||||
letting them request certain actions on them, like maximizing, etc.
|
||||
|
||||
After a client binds the zwlr_foreign_toplevel_manager_v1, each opened
|
||||
toplevel window will be sent via the toplevel event
|
||||
</description>
|
||||
|
||||
<event name="toplevel">
|
||||
<description summary="a toplevel has been created">
|
||||
This event is emitted whenever a new toplevel window is created. It
|
||||
is emitted for all toplevels, regardless of the app that has created
|
||||
them.
|
||||
|
||||
All initial details of the toplevel(title, app_id, states, etc.) will
|
||||
be sent immediately after this event via the corresponding events in
|
||||
zwlr_foreign_toplevel_handle_v1.
|
||||
</description>
|
||||
<arg name="toplevel" type="new_id" interface="zwlr_foreign_toplevel_handle_v1"/>
|
||||
</event>
|
||||
|
||||
<request name="stop">
|
||||
<description summary="stop sending events">
|
||||
Indicates the client no longer wishes to receive events for new toplevels.
|
||||
However the compositor may emit further toplevel_created events, until
|
||||
the finished event is emitted.
|
||||
|
||||
The client must not send any more requests after this one.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="finished" type="destructor">
|
||||
<description summary="the compositor has finished with the toplevel manager">
|
||||
This event indicates that the compositor is done sending events to the
|
||||
zwlr_foreign_toplevel_manager_v1. The server will destroy the object
|
||||
immediately after sending this request, so it will become invalid and
|
||||
the client should free any resources associated with it.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_foreign_toplevel_handle_v1" version="3">
|
||||
<description summary="an opened toplevel">
|
||||
A zwlr_foreign_toplevel_handle_v1 object represents an opened toplevel
|
||||
window. Each app may have multiple opened toplevels.
|
||||
|
||||
Each toplevel has a list of outputs it is visible on, conveyed to the
|
||||
client with the output_enter and output_leave events.
|
||||
</description>
|
||||
|
||||
<event name="title">
|
||||
<description summary="title change">
|
||||
This event is emitted whenever the title of the toplevel changes.
|
||||
</description>
|
||||
<arg name="title" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="app_id">
|
||||
<description summary="app-id change">
|
||||
This event is emitted whenever the app-id of the toplevel changes.
|
||||
</description>
|
||||
<arg name="app_id" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="output_enter">
|
||||
<description summary="toplevel entered an output">
|
||||
This event is emitted whenever the toplevel becomes visible on
|
||||
the given output. A toplevel may be visible on multiple outputs.
|
||||
</description>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</event>
|
||||
|
||||
<event name="output_leave">
|
||||
<description summary="toplevel left an output">
|
||||
This event is emitted whenever the toplevel stops being visible on
|
||||
the given output. It is guaranteed that an entered-output event
|
||||
with the same output has been emitted before this event.
|
||||
</description>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
</event>
|
||||
|
||||
<request name="set_maximized">
|
||||
<description summary="requests that the toplevel be maximized">
|
||||
Requests that the toplevel be maximized. If the maximized state actually
|
||||
changes, this will be indicated by the state event.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="unset_maximized">
|
||||
<description summary="requests that the toplevel be unmaximized">
|
||||
Requests that the toplevel be unmaximized. If the maximized state actually
|
||||
changes, this will be indicated by the state event.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_minimized">
|
||||
<description summary="requests that the toplevel be minimized">
|
||||
Requests that the toplevel be minimized. If the minimized state actually
|
||||
changes, this will be indicated by the state event.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="unset_minimized">
|
||||
<description summary="requests that the toplevel be unminimized">
|
||||
Requests that the toplevel be unminimized. If the minimized state actually
|
||||
changes, this will be indicated by the state event.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="activate">
|
||||
<description summary="activate the toplevel">
|
||||
Request that this toplevel be activated on the given seat.
|
||||
There is no guarantee the toplevel will be actually activated.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat"/>
|
||||
</request>
|
||||
|
||||
<enum name="state">
|
||||
<description summary="types of states on the toplevel">
|
||||
The different states that a toplevel can have. These have the same meaning
|
||||
as the states with the same names defined in xdg-toplevel
|
||||
</description>
|
||||
|
||||
<entry name="maximized" value="0" summary="the toplevel is maximized"/>
|
||||
<entry name="minimized" value="1" summary="the toplevel is minimized"/>
|
||||
<entry name="activated" value="2" summary="the toplevel is active"/>
|
||||
<entry name="fullscreen" value="3" summary="the toplevel is fullscreen" since="2"/>
|
||||
</enum>
|
||||
|
||||
<event name="state">
|
||||
<description summary="the toplevel state changed">
|
||||
This event is emitted immediately after the zlw_foreign_toplevel_handle_v1
|
||||
is created and each time the toplevel state changes, either because of a
|
||||
compositor action or because of a request in this protocol.
|
||||
</description>
|
||||
|
||||
<arg name="state" type="array"/>
|
||||
</event>
|
||||
|
||||
<event name="done">
|
||||
<description summary="all information about the toplevel has been sent">
|
||||
This event is sent after all changes in the toplevel state have been
|
||||
sent.
|
||||
|
||||
This allows changes to the zwlr_foreign_toplevel_handle_v1 properties
|
||||
to be seen as atomic, even if they happen via multiple events.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="close">
|
||||
<description summary="request that the toplevel be closed">
|
||||
Send a request to the toplevel to close itself. The compositor would
|
||||
typically use a shell-specific method to carry out this request, for
|
||||
example by sending the xdg_toplevel.close event. However, this gives
|
||||
no guarantees the toplevel will actually be destroyed. If and when
|
||||
this happens, the zwlr_foreign_toplevel_handle_v1.closed event will
|
||||
be emitted.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_rectangle">
|
||||
<description summary="the rectangle which represents the toplevel">
|
||||
The rectangle of the surface specified in this request corresponds to
|
||||
the place where the app using this protocol represents the given toplevel.
|
||||
It can be used by the compositor as a hint for some operations, e.g
|
||||
minimizing. The client is however not required to set this, in which
|
||||
case the compositor is free to decide some default value.
|
||||
|
||||
If the client specifies more than one rectangle, only the last one is
|
||||
considered.
|
||||
|
||||
The dimensions are given in surface-local coordinates.
|
||||
Setting width=height=0 removes the already-set rectangle.
|
||||
</description>
|
||||
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="invalid_rectangle" value="0"
|
||||
summary="the provided rectangle is invalid"/>
|
||||
</enum>
|
||||
|
||||
<event name="closed">
|
||||
<description summary="this toplevel has been destroyed">
|
||||
This event means the toplevel has been destroyed. It is guaranteed there
|
||||
won't be any more events for this zwlr_foreign_toplevel_handle_v1. The
|
||||
toplevel itself becomes inert so any requests will be ignored except the
|
||||
destroy request.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the zwlr_foreign_toplevel_handle_v1 object">
|
||||
Destroys the zwlr_foreign_toplevel_handle_v1 object.
|
||||
|
||||
This request should be called either when the client does not want to
|
||||
use the toplevel anymore or after the closed event to finalize the
|
||||
destruction of the object.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<request name="set_fullscreen" since="2">
|
||||
<description summary="request that the toplevel be fullscreened">
|
||||
Requests that the toplevel be fullscreened on the given output. If the
|
||||
fullscreen state and/or the outputs the toplevel is visible on actually
|
||||
change, this will be indicated by the state and output_enter/leave
|
||||
events.
|
||||
|
||||
The output parameter is only a hint to the compositor. Also, if output
|
||||
is NULL, the compositor should decide which output the toplevel will be
|
||||
fullscreened on, if at all.
|
||||
</description>
|
||||
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<request name="unset_fullscreen" since="2">
|
||||
<description summary="request that the toplevel be unfullscreened">
|
||||
Requests that the toplevel be unfullscreened. If the fullscreen state
|
||||
actually changes, this will be indicated by the state event.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<!-- Version 3 additions -->
|
||||
|
||||
<event name="parent" since="3">
|
||||
<description summary="parent change">
|
||||
This event is emitted whenever the parent of the toplevel changes.
|
||||
|
||||
No event is emitted when the parent handle is destroyed by the client.
|
||||
</description>
|
||||
<arg name="parent" type="object" interface="zwlr_foreign_toplevel_handle_v1" allow-null="true"/>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
@@ -366,7 +366,7 @@ void CCompositor::startCompositor() {
|
||||
if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */ && fork() == 0)
|
||||
execl("/bin/sh", "/bin/sh", "-c", "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE", nullptr);
|
||||
|
||||
Debug::log(LOG, "Running on WAYLAND_DISPLAY: %s", m_szWLDisplaySocket);
|
||||
Debug::log(LOG, "Running on WAYLAND_DISPLAY: %s", m_szWLDisplaySocket.c_str());
|
||||
|
||||
if (!wlr_backend_start(m_sWLRBackend)) {
|
||||
Debug::log(CRIT, "Backend did not start!");
|
||||
@@ -438,7 +438,7 @@ CMonitor* CCompositor::getMonitorFromVector(const Vector2D& point) {
|
||||
void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
|
||||
if (windowExists(pWindow) && !pWindow->m_bFadingOut){
|
||||
if (pWindow->m_bIsX11 && pWindow->m_iX11Type == 2) {
|
||||
m_dUnmanagedX11Windows.erase(std::remove_if(m_dUnmanagedX11Windows.begin(), m_dUnmanagedX11Windows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; }));
|
||||
std::erase_if(m_dUnmanagedX11Windows, [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; });
|
||||
}
|
||||
|
||||
// if X11, also check its children
|
||||
@@ -449,16 +449,16 @@ void CCompositor::removeWindowFromVectorSafe(CWindow* pWindow) {
|
||||
continue;
|
||||
|
||||
if (w->m_pX11Parent == pWindow)
|
||||
m_vWindows.erase(std::remove_if(m_vWindows.begin(), m_vWindows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == w.get(); }));
|
||||
std::erase_if(m_vWindows, [&](std::unique_ptr<CWindow>& el) { return el.get() == w.get(); });
|
||||
}
|
||||
|
||||
for (auto& w : m_dUnmanagedX11Windows) {
|
||||
if (w->m_pX11Parent == pWindow)
|
||||
m_dUnmanagedX11Windows.erase(std::remove_if(m_dUnmanagedX11Windows.begin(), m_dUnmanagedX11Windows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == w.get(); }));
|
||||
std::erase_if(m_dUnmanagedX11Windows, [&](std::unique_ptr<CWindow>& el) { return el.get() == w.get(); });
|
||||
}
|
||||
}
|
||||
|
||||
m_vWindows.erase(std::remove_if(m_vWindows.begin(), m_vWindows.end(), [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; }));
|
||||
std::erase_if(m_vWindows, [&](std::unique_ptr<CWindow>& el) { return el.get() == pWindow; });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -911,6 +911,9 @@ wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<
|
||||
|
||||
CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->m_bFadingOut || !w->m_bMappedX11)
|
||||
continue;
|
||||
|
||||
if (g_pXWaylandManager->getWindowSurface(w.get()) == pSurface)
|
||||
return w.get();
|
||||
}
|
||||
@@ -928,6 +931,23 @@ CWindow* CCompositor::getWindowFromHandle(uint32_t handle) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::getWindowFromZWLRHandle(wl_resource* handle) {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->isHidden() || !w->m_phForeignToplevel)
|
||||
continue;
|
||||
|
||||
wl_resource* current;
|
||||
|
||||
wl_list_for_each(current, &w->m_phForeignToplevel->resources, link) {
|
||||
if (current == handle) {
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::getFullscreenWindowOnWorkspace(const int& ID) {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w->m_iWorkspaceID == ID && w->m_bIsFullscreen)
|
||||
@@ -1068,8 +1088,9 @@ void CCompositor::cleanupFadingOut(const int& monid) {
|
||||
|
||||
g_pHyprOpenGL->m_mWindowFramebuffers[w].release();
|
||||
g_pHyprOpenGL->m_mWindowFramebuffers.erase(w);
|
||||
w->m_bFadingOut = false;
|
||||
removeWindowFromVectorSafe(w);
|
||||
m_vWindowsFadingOut.erase(std::remove(m_vWindowsFadingOut.begin(), m_vWindowsFadingOut.end(), w));
|
||||
std::erase(m_vWindowsFadingOut, w);
|
||||
|
||||
Debug::log(LOG, "Cleanup: destroyed a window");
|
||||
|
||||
@@ -1454,22 +1475,14 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
|
||||
|
||||
// opacity
|
||||
if (pWindow->m_bIsFullscreen) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
|
||||
pWindow->m_fActiveInactiveAlpha = *PFULLSCREENALPHA;
|
||||
else {
|
||||
if (pWindow == m_pLastWindow)
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alpha * *PACTIVEALPHA;
|
||||
else
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive != -1 ? pWindow->m_sSpecialRenderData.alphaInactive * *PINACTIVEALPHA : *PINACTIVEALPHA;
|
||||
}
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
if (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) {
|
||||
pWindow->m_fActiveInactiveAlpha = *PFULLSCREENALPHA;
|
||||
} else {
|
||||
if (pWindow == m_pLastWindow)
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alpha * *PACTIVEALPHA;
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaOverride ? pWindow->m_sSpecialRenderData.alpha : pWindow->m_sSpecialRenderData.alpha * *PACTIVEALPHA;
|
||||
else
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive != -1 ? pWindow->m_sSpecialRenderData.alphaInactive * *PINACTIVEALPHA : *PINACTIVEALPHA;
|
||||
pWindow->m_fActiveInactiveAlpha = pWindow->m_sSpecialRenderData.alphaInactive != -1 ? (pWindow->m_sSpecialRenderData.alphaInactiveOverride ? pWindow->m_sSpecialRenderData.alphaInactive : pWindow->m_sSpecialRenderData.alphaInactive * *PINACTIVEALPHA) : *PINACTIVEALPHA;
|
||||
}
|
||||
|
||||
// dim
|
||||
@@ -1580,7 +1593,8 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int offsetLeft = std::stoi(OFFSET) % m_vMonitors.size(); // no need to cycle more
|
||||
int offsetLeft = std::stoi(OFFSET);
|
||||
offsetLeft = offsetLeft < 0 ? -((-offsetLeft) % m_vMonitors.size()) : offsetLeft % m_vMonitors.size();
|
||||
|
||||
int currentPlace = 0;
|
||||
for (int i = 0; i < (int)m_vMonitors.size(); i++) {
|
||||
|
@@ -128,6 +128,7 @@ public:
|
||||
CWindow* getWindowForPopup(wlr_xdg_popup*);
|
||||
CWindow* getWindowFromSurface(wlr_surface*);
|
||||
CWindow* getWindowFromHandle(uint32_t);
|
||||
CWindow* getWindowFromZWLRHandle(wl_resource*);
|
||||
bool isWorkspaceVisible(const int&);
|
||||
CWorkspace* getWorkspaceByID(const int&);
|
||||
CWorkspace* getWorkspaceByName(const std::string&);
|
||||
|
@@ -328,14 +328,23 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
}
|
||||
} else if (r.szRule.find("opacity") == 0) {
|
||||
try {
|
||||
std::string alphaPart = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
CVarList vars(r.szRule, 0, ' ');
|
||||
|
||||
if (alphaPart.contains(' ')) {
|
||||
// we have a space, 2 values
|
||||
m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' ')));
|
||||
m_sSpecialRenderData.alphaInactive = std::stof(alphaPart.substr(alphaPart.find_first_of(' ') + 1));
|
||||
} else {
|
||||
m_sSpecialRenderData.alpha = std::stof(alphaPart);
|
||||
for (size_t i = 1 /* first item is "opacity" */; i < vars.size(); ++i) {
|
||||
if (i == 1) {
|
||||
// first arg, alpha
|
||||
m_sSpecialRenderData.alpha = std::stof(vars[i]);
|
||||
} else {
|
||||
if (vars[i] == "override") {
|
||||
if (i == 2) {
|
||||
m_sSpecialRenderData.alphaOverride = true;
|
||||
} else {
|
||||
m_sSpecialRenderData.alphaInactiveOverride = true;
|
||||
}
|
||||
} else {
|
||||
m_sSpecialRenderData.alphaInactive = std::stof(vars[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(std::exception& e) {
|
||||
Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what());
|
||||
|
@@ -16,7 +16,9 @@ enum eIdleInhibitMode {
|
||||
};
|
||||
|
||||
struct SWindowSpecialRenderData {
|
||||
bool alphaOverride = false;
|
||||
float alpha = 1.f;
|
||||
bool alphaInactiveOverride = false;
|
||||
float alphaInactive = -1.f; // -1 means unset
|
||||
|
||||
int64_t activeBorderColor = -1; // -1 means unset
|
||||
@@ -39,6 +41,7 @@ struct SWindowAdditionalConfigData {
|
||||
bool forceNoBorder = false;
|
||||
bool forceNoShadow = false;
|
||||
bool windowDanceCompat = false;
|
||||
bool noMaxSize = false;
|
||||
};
|
||||
|
||||
struct SWindowRule {
|
||||
|
@@ -109,6 +109,8 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["master:new_is_master"].intValue = 1;
|
||||
configValues["master:new_on_top"].intValue = 0;
|
||||
configValues["master:no_gaps_when_only"].intValue = 0;
|
||||
configValues["master:orientation"].strValue = "left";
|
||||
configValues["master:inherit_fullscreen"].intValue = 1;
|
||||
|
||||
configValues["animations:enabled"].intValue = 1;
|
||||
configValues["animations:speed"].floatValue = 7.f;
|
||||
@@ -749,6 +751,7 @@ bool windowRuleValid(const std::string& RULE) {
|
||||
&& RULE != "forceinput"
|
||||
&& RULE != "fullscreen"
|
||||
&& RULE != "nofullscreenrequest"
|
||||
&& RULE != "nomaxsize"
|
||||
&& RULE != "pin"
|
||||
&& RULE != "noanim"
|
||||
&& RULE != "windowdance"
|
||||
@@ -1687,6 +1690,18 @@ CMonitor* CConfigManager::getBoundMonitorForWS(std::string wsname) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string CConfigManager::getBoundMonitorStringForWS(std::string wsname) {
|
||||
for (auto& [ws, mon] : boundWorkspaces) {
|
||||
const auto WSNAME = ws.find("name:") == 0 ? ws.substr(5) : ws;
|
||||
|
||||
if (WSNAME == wsname) {
|
||||
return mon;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void CConfigManager::addExecRule(SExecRequestedRule rule) {
|
||||
execRequestedRules.push_back(rule);
|
||||
}
|
||||
|
@@ -95,7 +95,7 @@ public:
|
||||
|
||||
~CVarList() = default;
|
||||
|
||||
int size() const {
|
||||
size_t size() const {
|
||||
return m_vArgs.size();
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ public:
|
||||
SMonitorRule getMonitorRuleFor(std::string, std::string displayName = "");
|
||||
|
||||
CMonitor* getBoundMonitorForWS(std::string);
|
||||
std::string getBoundMonitorStringForWS(std::string);
|
||||
|
||||
std::vector<SWindowRule> getMatchingRules(CWindow*);
|
||||
|
||||
|
@@ -18,10 +18,10 @@
|
||||
#define ISDEBUG false
|
||||
#endif
|
||||
|
||||
#define LISTENER(name) void listener_##name(wl_listener*, void*); inline wl_listener listen_##name = { .notify = listener_##name };
|
||||
#define DYNLISTENFUNC(name) void listener_##name(void*, void*);
|
||||
#define DYNLISTENER(name) CHyprWLListener hyprListener_##name;
|
||||
#define DYNMULTILISTENER(name) wl_listener listen_##name;
|
||||
#define LISTENER(name) void listener_##name(wl_listener*, void*); inline wl_listener listen_##name = { .notify = listener_##name }
|
||||
#define DYNLISTENFUNC(name) void listener_##name(void*, void*)
|
||||
#define DYNLISTENER(name) CHyprWLListener hyprListener_##name
|
||||
#define DYNMULTILISTENER(name) wl_listener listen_##name
|
||||
|
||||
#define VECINRECT(vec, x1, y1, x2, y2) (vec.x >= (x1) && vec.x <= (x2) && vec.y >= (y1) && vec.y <= (y2))
|
||||
|
||||
|
@@ -110,6 +110,11 @@ void Events::listener_newConstraint(wl_listener* listener, void* data) {
|
||||
|
||||
if (g_pCompositor->m_pLastFocus == PCONSTRAINT->surface) {
|
||||
g_pInputManager->constrainMouse(CONSTRAINT->pMouse, PCONSTRAINT);
|
||||
|
||||
if (!CONSTRAINT->hintSet) {
|
||||
const auto PWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
|
||||
CONSTRAINT->positionHint = g_pInputManager->getMouseCoordsInternal() - PWINDOW->m_vRealPosition.goalv();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,14 +129,14 @@ void Events::listener_destroyConstraint(void* owner, void* data) {
|
||||
if (PWINDOW) {
|
||||
if (PWINDOW->m_bIsX11) {
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
|
||||
PCONSTRAINT->constraint->current.cursor_hint.x + PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y + PCONSTRAINT->constraint->current.cursor_hint.y);
|
||||
PCONSTRAINT->positionHint.x + PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y + PCONSTRAINT->positionHint.y);
|
||||
|
||||
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->constraint->current.cursor_hint.x, PCONSTRAINT->constraint->current.cursor_hint.y);
|
||||
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->positionHint.x, PCONSTRAINT->positionHint.y);
|
||||
} else {
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr,
|
||||
PCONSTRAINT->constraint->current.cursor_hint.x + PWINDOW->m_vRealPosition.vec().x, PCONSTRAINT->constraint->current.cursor_hint.y + PWINDOW->m_vRealPosition.vec().y);
|
||||
PCONSTRAINT->positionHint.x + PWINDOW->m_vRealPosition.vec().x, PCONSTRAINT->positionHint.y + PWINDOW->m_vRealPosition.vec().y);
|
||||
|
||||
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->constraint->current.cursor_hint.x, PCONSTRAINT->constraint->current.cursor_hint.y);
|
||||
wlr_seat_pointer_warp(PCONSTRAINT->constraint->seat, PCONSTRAINT->positionHint.x, PCONSTRAINT->positionHint.y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -20,7 +20,7 @@ void addViewCoords(void* pWindow, int* x, int* y) {
|
||||
*x += PWINDOW->m_vRealPosition.goalv().x;
|
||||
*y += PWINDOW->m_vRealPosition.goalv().y;
|
||||
|
||||
if (!PWINDOW->m_bIsX11) {
|
||||
if (!PWINDOW->m_bIsX11 && PWINDOW->m_bIsMapped) {
|
||||
wlr_box geom;
|
||||
wlr_xdg_surface_get_geometry(PWINDOW->m_uSurface.xdg, &geom);
|
||||
|
||||
@@ -29,18 +29,12 @@ void addViewCoords(void* pWindow, int* x, int* y) {
|
||||
}
|
||||
}
|
||||
|
||||
int setAnimToMove(void* data) {
|
||||
const auto PWINDOW = (CWindow*)data;
|
||||
|
||||
void setAnimToMove(void* data) {
|
||||
auto *const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return 0;
|
||||
CAnimatedVariable* animvar = (CAnimatedVariable*)data;
|
||||
|
||||
PWINDOW->m_vRealPosition.setConfig(PANIMCFG);
|
||||
PWINDOW->m_vRealSize.setConfig(PANIMCFG);
|
||||
|
||||
return 0;
|
||||
animvar->setConfig(PANIMCFG);
|
||||
}
|
||||
|
||||
void Events::listener_mapWindow(void* owner, void* data) {
|
||||
@@ -170,6 +164,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
requestsFullscreen = true;
|
||||
} else if (r.szRule == "windowdance") {
|
||||
PWINDOW->m_sAdditionalConfigData.windowDanceCompat = true;
|
||||
} else if (r.szRule == "nomaxsize") {
|
||||
PWINDOW->m_sAdditionalConfigData.noMaxSize = true;
|
||||
} else if (r.szRule == "forceinput") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceAllowsInput = true;
|
||||
} else if (r.szRule == "pin") {
|
||||
@@ -445,8 +441,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_fAlpha.setValueAndWarp(0.f);
|
||||
PWINDOW->m_fAlpha = 255.f;
|
||||
|
||||
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);
|
||||
PWINDOW->m_vRealPosition.setCallbackOnEnd(setAnimToMove);
|
||||
PWINDOW->m_vRealSize.setCallbackOnEnd(setAnimToMove);
|
||||
|
||||
if (requestsFullscreen && !PWINDOW->m_bNoFullscreenRequest) {
|
||||
// fix fullscreen on requested (basically do a switcheroo)
|
||||
@@ -706,6 +702,11 @@ void Events::listener_destroyWindow(void* owner, void* data) {
|
||||
}
|
||||
|
||||
PWINDOW->m_bReadyToDelete = true;
|
||||
|
||||
if (!PWINDOW->m_bFadingOut) {
|
||||
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
|
||||
Debug::log(LOG, "Unmapped window %x removed instantly", PWINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
void Events::listener_setTitleWindow(void* owner, void* data) {
|
||||
|
@@ -277,51 +277,41 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
|
||||
// result now has +/- what we should move on mon
|
||||
int remains = (int)result;
|
||||
int currentID = g_pCompositor->m_pLastMonitor->activeWorkspace;
|
||||
int searchID = currentID;
|
||||
|
||||
std::vector<int> validWSes;
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (ws->m_bIsSpecialWorkspace || (ws->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID && !onAllMonitors))
|
||||
continue;
|
||||
|
||||
while (remains != 0) {
|
||||
if (remains < 0)
|
||||
searchID--;
|
||||
else
|
||||
searchID++;
|
||||
validWSes.push_back(ws->m_iID);
|
||||
}
|
||||
|
||||
if (g_pCompositor->workspaceIDOutOfBounds(searchID)){
|
||||
// means we need to wrap around
|
||||
int lowestID = 99999;
|
||||
int highestID = -99999;
|
||||
std::sort(validWSes.begin(), validWSes.end());
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (g_pCompositor->isWorkspaceSpecial(w->m_iID))
|
||||
continue;
|
||||
// get the offset
|
||||
remains = remains < 0 ? -((-remains) % validWSes.size()) : remains % validWSes.size();
|
||||
|
||||
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_bIsSpecialWorkspace) {
|
||||
if (onAllMonitors || PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
currentID = PWORKSPACE->m_iID;
|
||||
|
||||
if (remains < 0)
|
||||
remains++;
|
||||
else
|
||||
remains--;
|
||||
}
|
||||
// get the current item
|
||||
int currentItem = -1;
|
||||
for (size_t i = 0; i < validWSes.size(); i++) {
|
||||
if (validWSes[i] == g_pCompositor->m_pLastMonitor->activeWorkspace) {
|
||||
currentItem = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = currentID;
|
||||
outName = g_pCompositor->getWorkspaceByID(currentID)->m_szName;
|
||||
// apply
|
||||
currentItem += remains;
|
||||
|
||||
// sanitize
|
||||
if (currentItem >= (int)validWSes.size()) {
|
||||
currentItem = currentItem % validWSes.size();
|
||||
} else if (currentItem < 0) {
|
||||
currentItem = validWSes.size() + currentItem;
|
||||
}
|
||||
|
||||
result = validWSes[currentItem];
|
||||
outName = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName;
|
||||
|
||||
} else {
|
||||
if (in[0] == '+' || in[0] == '-') {
|
||||
@@ -503,4 +493,4 @@ int64_t configStringToInt(const std::string& VALUE) {
|
||||
return 0;
|
||||
}
|
||||
return stol(VALUE);
|
||||
}
|
||||
}
|
@@ -240,10 +240,24 @@ bool CMonitor::isMirror() {
|
||||
return pMirrorOf != nullptr;
|
||||
}
|
||||
|
||||
int CMonitor::findAvailableDefaultWS() {
|
||||
for (size_t i = 1; i < INT32_MAX; ++i) {
|
||||
if (g_pCompositor->getWorkspaceByID(i))
|
||||
continue;
|
||||
|
||||
if (const auto BOUND = g_pConfigManager->getBoundMonitorStringForWS(std::to_string(i)); !BOUND.empty() && BOUND != szName)
|
||||
continue;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return INT32_MAX; // shouldn't be reachable
|
||||
}
|
||||
|
||||
void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
|
||||
// Workspace
|
||||
std::string newDefaultWorkspaceName = "";
|
||||
int64_t WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
|
||||
int64_t WORKSPACEID = monitorRule.defaultWorkspace == "" ? findAvailableDefaultWS() : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
|
||||
|
||||
if (WORKSPACEID == INT_MAX || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) {
|
||||
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
|
||||
|
@@ -83,4 +83,5 @@ public:
|
||||
|
||||
private:
|
||||
void setupDefaultWS(const SMonitorRule&);
|
||||
int findAvailableDefaultWS();
|
||||
};
|
||||
|
@@ -146,6 +146,9 @@ struct SConstraint {
|
||||
SMouse* pMouse = nullptr;
|
||||
wlr_pointer_constraint_v1* constraint = nullptr;
|
||||
|
||||
bool hintSet = false;
|
||||
Vector2D positionHint; // the position hint, but will be set to the current cursor pos if not set.
|
||||
|
||||
DYNLISTENER(setConstraintRegion);
|
||||
DYNLISTENER(destroyConstraint);
|
||||
|
||||
|
@@ -51,4 +51,4 @@ public:
|
||||
void moveToMonitor(const int&);
|
||||
|
||||
CWindow* getLastFocusedWindow();
|
||||
};
|
||||
};
|
||||
|
@@ -336,6 +336,16 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// last fail-safe to avoid duplicate fullscreens
|
||||
if ((!OPENINGON || OPENINGON->pWindow == pWindow) && getNodesOnWorkspace(PNODE->workspaceID) > 1) {
|
||||
for (auto& node : m_lDwindleNodesData) {
|
||||
if (node.workspaceID == PNODE->workspaceID && node.pWindow != pWindow) {
|
||||
OPENINGON = &node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if it's the first, it's easy. Make it fullscreen.
|
||||
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
|
||||
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
@@ -625,7 +635,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||
|
||||
if (!PNODE) {
|
||||
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0));
|
||||
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0));
|
||||
PWINDOW->updateWindowDecos();
|
||||
return;
|
||||
}
|
||||
|
@@ -21,6 +21,9 @@ void IHyprLayout::onWindowCreated(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
void IHyprLayout::onWindowRemoved(CWindow* pWindow) {
|
||||
if (pWindow->m_bIsFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
|
||||
if (pWindow->m_bIsFloating) {
|
||||
onWindowRemovedFloating(pWindow);
|
||||
} else {
|
||||
@@ -129,16 +132,13 @@ void IHyprLayout::onBeginDragWindow() {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && (!DRAGGINGWINDOW->m_bCreatedOverFullscreen || !DRAGGINGWINDOW->m_bIsFloating)) {
|
||||
Debug::log(LOG, "Rejecting drag on a fullscreen workspace. (window under fullscreen)");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pInputManager->setCursorImageUntilUnset("hand1");
|
||||
|
||||
DRAGGINGWINDOW->m_vRealPosition.setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove"));
|
||||
DRAGGINGWINDOW->m_vRealSize.setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove"));
|
||||
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = false;
|
||||
|
||||
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
||||
@@ -180,11 +180,11 @@ void IHyprLayout::onBeginDragWindow() {
|
||||
void IHyprLayout::onEndDragWindow() {
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||
|
||||
g_pInputManager->unsetCursorImage();
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
|
||||
return;
|
||||
|
||||
g_pInputManager->unsetCursorImage();
|
||||
|
||||
if (DRAGGINGWINDOW->m_bDraggingTiled) {
|
||||
DRAGGINGWINDOW->m_bIsFloating = false;
|
||||
g_pInputManager->refocus();
|
||||
@@ -201,10 +201,13 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
|
||||
// Window invalid or drag begin size 0,0 meaning we rejected it.
|
||||
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
|
||||
onEndDragWindow();
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto SPECIAL = g_pCompositor->isWorkspaceSpecial(DRAGGINGWINDOW->m_iWorkspaceID);
|
||||
|
||||
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
||||
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
||||
|
||||
@@ -271,7 +274,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
// and check its monitor
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
|
||||
|
||||
if (PMONITOR) {
|
||||
if (PMONITOR && !SPECIAL) {
|
||||
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
DRAGGINGWINDOW->moveToWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
@@ -297,6 +300,9 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||
|
||||
const auto TILED = isWindowTiled(pWindow);
|
||||
|
||||
// event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{ "changefloatingmode", getFormat("%x,%d", pWindow, (int)TILED) });
|
||||
|
||||
if (!TILED) {
|
||||
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
|
||||
pWindow->m_iMonitorID = PNEWMON->ID;
|
||||
|
@@ -30,6 +30,28 @@ int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) {
|
||||
return no;
|
||||
}
|
||||
|
||||
SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) {
|
||||
for (auto& n : m_lMasterWorkspacesData) {
|
||||
if (n.workspaceID == ws)
|
||||
return &n;
|
||||
}
|
||||
|
||||
//create on the fly if it doesn't exist yet
|
||||
const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back();
|
||||
PWORKSPACEDATA->workspaceID = ws;
|
||||
const auto orientation = &g_pConfigManager->getConfigValuePtr("master:orientation")->strValue;
|
||||
if (*orientation == "top") {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_TOP;
|
||||
} else if (*orientation == "right") {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_RIGHT;
|
||||
} else if (*orientation == "bottom") {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
|
||||
} else {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
|
||||
}
|
||||
return PWORKSPACEDATA;
|
||||
}
|
||||
|
||||
std::string CHyprMasterLayout::getLayoutName() {
|
||||
return "Master";
|
||||
}
|
||||
@@ -130,11 +152,13 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
}
|
||||
}
|
||||
|
||||
const auto WORKSPACEID = PNODE->workspaceID;
|
||||
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
|
||||
if (getMastersOnWorkspace(PNODE->workspaceID) == getNodesOnWorkspace(PNODE->workspaceID) && MASTERSLEFT > 1) {
|
||||
if (getMastersOnWorkspace(WORKSPACEID) == getNodesOnWorkspace(WORKSPACEID) && MASTERSLEFT > 1) {
|
||||
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
|
||||
if (it->workspaceID == PNODE->workspaceID) {
|
||||
if (it->workspaceID == WORKSPACEID) {
|
||||
it->isMaster = false;
|
||||
break;
|
||||
}
|
||||
@@ -187,6 +211,8 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
if (!PWORKSPACE)
|
||||
return;
|
||||
|
||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(ws);
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
|
||||
const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID);
|
||||
@@ -196,53 +222,119 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
|
||||
const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
||||
//compute placement of master window(s)
|
||||
if (getNodesOnWorkspace(PWORKSPACE->m_iID) < 2) {
|
||||
PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition;
|
||||
PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
|
||||
applyNodeDataToWindow(PMASTERNODE);
|
||||
return;
|
||||
} else {
|
||||
} else if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT || PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) {
|
||||
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
|
||||
int nodesLeft = MASTERS;
|
||||
float nextY = 0;
|
||||
const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster;
|
||||
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) {
|
||||
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY);
|
||||
if (PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) {
|
||||
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMONITOR->vecSize.x - WIDTH, nextY);
|
||||
} else {
|
||||
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY);
|
||||
}
|
||||
float HEIGHT = nodesLeft > 1 ? heightLeft / nodesLeft * n.percSize : heightLeft;
|
||||
if (HEIGHT > heightLeft * 0.9f && nodesLeft > 1)
|
||||
HEIGHT = heightLeft * 0.9f;
|
||||
n.size = Vector2D((PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster, HEIGHT);
|
||||
n.size = Vector2D(WIDTH, HEIGHT);
|
||||
|
||||
nodesLeft--;
|
||||
heightLeft -= HEIGHT;
|
||||
nextY += HEIGHT;
|
||||
|
||||
applyNodeDataToWindow(&n);
|
||||
}
|
||||
}
|
||||
} else if (PWORKSPACEDATA->orientation == ORIENTATION_TOP || PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
|
||||
float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x;
|
||||
int nodesLeft = MASTERS;
|
||||
float nextX = 0;
|
||||
const float HEIGHT = (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y) * PMASTERNODE->percMaster;
|
||||
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) {
|
||||
if (PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
|
||||
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX,PMONITOR->vecSize.y - HEIGHT - PMONITOR->vecReservedBottomRight.y);
|
||||
} else {
|
||||
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, 0);
|
||||
}
|
||||
float WIDTH = nodesLeft > 1 ? widthLeft / nodesLeft * n.percSize : widthLeft;
|
||||
if (WIDTH > widthLeft * 0.9f && nodesLeft > 1)
|
||||
WIDTH = widthLeft * 0.9f;
|
||||
n.size = Vector2D(WIDTH, HEIGHT);
|
||||
|
||||
nodesLeft--;
|
||||
widthLeft -= WIDTH;
|
||||
nextX += WIDTH;
|
||||
|
||||
applyNodeDataToWindow(&n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
|
||||
|
||||
//compute placement of slave window(s)
|
||||
int slavesLeft = getNodesOnWorkspace(PWORKSPACE->m_iID) - MASTERS;
|
||||
float nextY = 0;
|
||||
if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT || PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) {
|
||||
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
|
||||
float nextY = 0;
|
||||
const float WIDTH = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x;
|
||||
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
|
||||
continue;
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
|
||||
continue;
|
||||
|
||||
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMASTERNODE->percMaster * PMONITOR->vecSize.x, nextY);
|
||||
float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft;
|
||||
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
||||
HEIGHT = heightLeft * 0.9f;
|
||||
nd.size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x, HEIGHT);
|
||||
if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT) {
|
||||
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMASTERNODE->percMaster * (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x), nextY);
|
||||
} else {
|
||||
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY);
|
||||
}
|
||||
float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft;
|
||||
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
||||
HEIGHT = heightLeft * 0.9f;
|
||||
nd.size = Vector2D(WIDTH, HEIGHT);
|
||||
|
||||
slavesLeft--;
|
||||
heightLeft -= HEIGHT;
|
||||
nextY += HEIGHT;
|
||||
slavesLeft--;
|
||||
heightLeft -= HEIGHT;
|
||||
nextY += HEIGHT;
|
||||
|
||||
applyNodeDataToWindow(&nd);
|
||||
applyNodeDataToWindow(&nd);
|
||||
}
|
||||
} else if (PWORKSPACEDATA->orientation == ORIENTATION_TOP || PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
|
||||
float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x;
|
||||
float nextX = 0;
|
||||
const float HEIGHT = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y - PMASTERNODE->size.y;
|
||||
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
|
||||
continue;
|
||||
if (PWORKSPACEDATA->orientation == ORIENTATION_TOP) {
|
||||
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, PMASTERNODE->percMaster * (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y));
|
||||
} else {
|
||||
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, 0);
|
||||
}
|
||||
float WIDTH = slavesLeft > 1 ? widthLeft / slavesLeft * nd.percSize : widthLeft;
|
||||
if (WIDTH > widthLeft * 0.9f && slavesLeft > 1)
|
||||
WIDTH = widthLeft * 0.9f;
|
||||
nd.size = Vector2D(WIDTH, HEIGHT);
|
||||
|
||||
slavesLeft--;
|
||||
widthLeft -= WIDTH;
|
||||
nextX += WIDTH;
|
||||
|
||||
applyNodeDataToWindow(&nd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
@@ -490,6 +582,8 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
if (!PNODE2 || !PNODE)
|
||||
return;
|
||||
|
||||
const auto inheritFullscreen = prepareLoseFocus(pWindow);
|
||||
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
|
||||
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
|
||||
@@ -505,6 +599,8 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
|
||||
g_pHyprRenderer->damageWindow(pWindow);
|
||||
g_pHyprRenderer->damageWindow(pWindow2);
|
||||
|
||||
prepareNewFocus(pWindow2, inheritFullscreen);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
|
||||
@@ -559,14 +655,14 @@ CWindow* CHyprMasterLayout::getNextWindow(CWindow* pWindow, bool next) {
|
||||
}
|
||||
} else {
|
||||
if (PNODE->isMaster) {
|
||||
// focus the first non master
|
||||
// focus the last non master
|
||||
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
|
||||
if (it->pWindow != pWindow && it->workspaceID == pWindow->m_iWorkspaceID) {
|
||||
return it->pWindow;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// focus next
|
||||
// focus previous
|
||||
bool reached = false;
|
||||
bool found = false;
|
||||
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
|
||||
@@ -591,6 +687,28 @@ CWindow* CHyprMasterLayout::getNextWindow(CWindow* pWindow, bool next) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CHyprMasterLayout::prepareLoseFocus(CWindow* pWindow) {
|
||||
if (!pWindow)
|
||||
return false;
|
||||
|
||||
//if the current window is fullscreen, make it normal again if we are about to lose focus
|
||||
if (pWindow->m_bIsFullscreen) {
|
||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||
static auto *const INHERIT = &g_pConfigManager->getConfigValuePtr("master:inherit_fullscreen")->intValue;
|
||||
return *INHERIT == 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::prepareNewFocus(CWindow* pWindow, bool inheritFullscreen) {
|
||||
if (!pWindow)
|
||||
return;
|
||||
|
||||
if (inheritFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(pWindow, true, FULLSCREEN_MAXIMIZED);
|
||||
}
|
||||
|
||||
std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
||||
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOWTOCHANGETO))
|
||||
@@ -614,6 +732,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
if (!PMASTER)
|
||||
return 0;
|
||||
|
||||
|
||||
if (PMASTER->pWindow != PWINDOW) {
|
||||
switchWindows(PWINDOW, PMASTER->pWindow);
|
||||
switchToWindow(PWINDOW);
|
||||
@@ -634,17 +753,21 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
if (!PWINDOW)
|
||||
return 0;
|
||||
|
||||
const bool inheritFullscreen = prepareLoseFocus(PWINDOW);
|
||||
|
||||
const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (!PMASTER)
|
||||
return 0;
|
||||
|
||||
if (PMASTER->pWindow != PWINDOW)
|
||||
if (PMASTER->pWindow != PWINDOW) {
|
||||
switchToWindow(PMASTER->pWindow);
|
||||
else {
|
||||
prepareNewFocus(PMASTER->pWindow, inheritFullscreen);
|
||||
} else {
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
|
||||
switchToWindow(n.pWindow);
|
||||
prepareNewFocus(n.pWindow, inheritFullscreen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -657,14 +780,22 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
if (!PWINDOW)
|
||||
return 0;
|
||||
|
||||
switchToWindow(getNextWindow(PWINDOW, true));
|
||||
const bool inheritFullscreen = prepareLoseFocus(PWINDOW);
|
||||
|
||||
const auto PNEXTWINDOW = getNextWindow(PWINDOW, true);
|
||||
switchToWindow(PNEXTWINDOW);
|
||||
prepareNewFocus(PNEXTWINDOW, inheritFullscreen);
|
||||
} else if (message == "cycleprev") {
|
||||
const auto PWINDOW = header.pWindow;
|
||||
|
||||
if (!PWINDOW)
|
||||
return 0;
|
||||
|
||||
switchToWindow(getNextWindow(PWINDOW, false));
|
||||
const bool inheritFullscreen = prepareLoseFocus(PWINDOW);
|
||||
|
||||
const auto PPREVWINDOW = getNextWindow(PWINDOW, true);
|
||||
switchToWindow(PPREVWINDOW);
|
||||
prepareNewFocus(PPREVWINDOW, inheritFullscreen);
|
||||
} else if (message == "swapnext") {
|
||||
if (!g_pCompositor->windowValidMapped(header.pWindow))
|
||||
return 0;
|
||||
@@ -677,6 +808,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true);
|
||||
|
||||
if (PWINDOWTOSWAPWITH) {
|
||||
prepareLoseFocus(header.pWindow);
|
||||
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
|
||||
g_pCompositor->focusWindow(header.pWindow);
|
||||
}
|
||||
@@ -692,6 +824,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false);
|
||||
|
||||
if (PWINDOWTOSWAPWITH) {
|
||||
prepareLoseFocus(header.pWindow);
|
||||
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
|
||||
g_pCompositor->focusWindow(header.pWindow);
|
||||
}
|
||||
@@ -710,6 +843,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
if (MASTERS + 2 > WINDOWS)
|
||||
return 0;
|
||||
|
||||
prepareLoseFocus(header.pWindow);
|
||||
|
||||
if (!PNODE || PNODE->isMaster) {
|
||||
// first non-master node
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
@@ -740,6 +875,8 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
if (WINDOWS < 2 || MASTERS < 2)
|
||||
return 0;
|
||||
|
||||
prepareLoseFocus(header.pWindow);
|
||||
|
||||
if (!PNODE || !PNODE->isMaster) {
|
||||
// first non-master node
|
||||
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
|
||||
@@ -752,6 +889,61 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||
PNODE->isMaster = false;
|
||||
}
|
||||
|
||||
recalculateMonitor(header.pWindow->m_iMonitorID);
|
||||
} else if (message == "orientationleft" || message == "orientationright" || message == "orientationtop" || message == "orientationbottom") {
|
||||
const auto PWINDOW = header.pWindow;
|
||||
|
||||
if (!PWINDOW)
|
||||
return 0;
|
||||
|
||||
prepareLoseFocus(PWINDOW);
|
||||
|
||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (message == "orientationleft")
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
|
||||
else if (message == "orientationright")
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_RIGHT;
|
||||
else if (message == "orientationtop")
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_TOP;
|
||||
else if (message == "orientationbottom")
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
|
||||
|
||||
recalculateMonitor(header.pWindow->m_iMonitorID);
|
||||
|
||||
} else if (message == "orientationnext") {
|
||||
const auto PWINDOW = header.pWindow;
|
||||
|
||||
if (!PWINDOW)
|
||||
return 0;
|
||||
|
||||
prepareLoseFocus(PWINDOW);
|
||||
|
||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
|
||||
} else {
|
||||
PWORKSPACEDATA->orientation = (eOrientation) (PWORKSPACEDATA->orientation + 1);
|
||||
}
|
||||
|
||||
recalculateMonitor(header.pWindow->m_iMonitorID);
|
||||
} else if (message == "orientationprev") {
|
||||
const auto PWINDOW = header.pWindow;
|
||||
|
||||
if (!PWINDOW)
|
||||
return 0;
|
||||
|
||||
prepareLoseFocus(PWINDOW);
|
||||
|
||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT) {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
|
||||
} else {
|
||||
PWORKSPACEDATA->orientation = (eOrientation) (PWORKSPACEDATA->orientation - 1);
|
||||
}
|
||||
|
||||
recalculateMonitor(header.pWindow->m_iMonitorID);
|
||||
}
|
||||
|
||||
|
@@ -1,11 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHyprLayout.hpp"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
|
||||
enum eFullscreenMode : uint8_t;
|
||||
|
||||
//orientation determines which side of the screen the master area resides
|
||||
enum eOrientation : uint8_t {
|
||||
ORIENTATION_LEFT = 0,
|
||||
ORIENTATION_TOP,
|
||||
ORIENTATION_RIGHT,
|
||||
ORIENTATION_BOTTOM
|
||||
};
|
||||
|
||||
struct SMasterNodeData {
|
||||
bool isMaster = false;
|
||||
float percMaster = 0.5f;
|
||||
@@ -24,6 +33,15 @@ struct SMasterNodeData {
|
||||
}
|
||||
};
|
||||
|
||||
struct SMasterWorkspaceData {
|
||||
int workspaceID = -1;
|
||||
eOrientation orientation = ORIENTATION_LEFT;
|
||||
|
||||
bool operator==(const SMasterWorkspaceData& rhs) {
|
||||
return workspaceID == rhs.workspaceID;
|
||||
}
|
||||
};
|
||||
|
||||
class CHyprMasterLayout : public IHyprLayout {
|
||||
public:
|
||||
virtual void onWindowCreatedTiling(CWindow*);
|
||||
@@ -44,7 +62,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
std::list<SMasterNodeData> m_lMasterNodesData;
|
||||
std::list<SMasterNodeData> m_lMasterNodesData;
|
||||
std::vector<SMasterWorkspaceData> m_lMasterWorkspacesData;
|
||||
|
||||
bool m_bForceWarps = false;
|
||||
|
||||
@@ -52,9 +71,13 @@ private:
|
||||
void applyNodeDataToWindow(SMasterNodeData*);
|
||||
SMasterNodeData* getNodeFromWindow(CWindow*);
|
||||
SMasterNodeData* getMasterNodeOnWorkspace(const int&);
|
||||
SMasterWorkspaceData* getMasterWorkspaceData(const int&);
|
||||
void calculateWorkspace(const int&);
|
||||
CWindow* getNextWindow(CWindow*, bool);
|
||||
int getMastersOnWorkspace(const int&);
|
||||
bool prepareLoseFocus(CWindow*);
|
||||
void prepareNewFocus(CWindow*, bool inherit_fullscreen);
|
||||
|
||||
friend struct SMasterNodeData;
|
||||
};
|
||||
friend struct SMasterWorkspaceData;
|
||||
};
|
||||
|
@@ -899,9 +899,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||
|
||||
g_pKeybindManager->changeworkspace(args);
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
if (PWORKSPACE == OLDWORKSPACE) {
|
||||
Debug::log(LOG, "Not moving to workspace because it didn't change.");
|
||||
@@ -909,8 +907,8 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
}
|
||||
|
||||
if (!PWORKSPACE) {
|
||||
Debug::log(ERR, "Workspace null in moveActiveToWorkspace?");
|
||||
return;
|
||||
// create
|
||||
PWORKSPACE = g_pCompositor->createNewWorkspace(WORKSPACEID, OLDWORKSPACE->m_iMonitorID, workspaceName);
|
||||
}
|
||||
|
||||
PWINDOW->moveToWorkspace(PWORKSPACE->m_iID);
|
||||
@@ -932,21 +930,14 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
||||
}
|
||||
|
||||
if (WASFULLSCREEN) {
|
||||
if (WASFULLSCREEN)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, true, OLDWORKSPACE->m_efFullscreenMode);
|
||||
}
|
||||
|
||||
// undo the damage if we are moving to the special workspace
|
||||
if (g_pCompositor->isWorkspaceSpecial(WORKSPACEID)) {
|
||||
changeworkspace("[internal]" + std::to_string(OLDWORKSPACE->m_iID));
|
||||
OLDWORKSPACE->startAnim(true, true, true);
|
||||
toggleSpecialWorkspace(workspaceName.length() > 7 ? workspaceName.substr(8) : workspaceName /* remove special: */);
|
||||
g_pCompositor->getWorkspaceByID(WORKSPACEID)->startAnim(false, false, true);
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
m->specialWorkspaceID = 0;
|
||||
} else {
|
||||
if (!g_pCompositor->isWorkspaceSpecial(WORKSPACEID)) {
|
||||
g_pKeybindManager->changeworkspace(args);
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
} else {
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
|
||||
}
|
||||
|
||||
PWINDOW->updateToplevel();
|
||||
@@ -954,6 +945,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
|
||||
void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
// hacky, but works lol
|
||||
// TODO: this sucks
|
||||
|
||||
CWindow* PWINDOW = nullptr;
|
||||
|
||||
@@ -1024,7 +1016,11 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
// manually post event cuz it got ignored above
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", getFormat("%x,%s", PWINDOW, PWORKSPACE->m_szName.c_str())});
|
||||
|
||||
g_pInputManager->refocus();
|
||||
PWINDOW->m_iWorkspaceID = OLDWORKSPACEIDRETURN;
|
||||
const auto PNEXTCANDIDATE = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(PWINDOW);
|
||||
PWINDOW->m_iWorkspaceID = workspaceToMoveTo;
|
||||
|
||||
g_pCompositor->focusWindow(PNEXTCANDIDATE);
|
||||
}
|
||||
|
||||
void CKeybindManager::moveFocusTo(std::string args) {
|
||||
@@ -1327,6 +1323,8 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
||||
|
||||
void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
|
||||
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
|
||||
std::string workspaceName = "";
|
||||
int workspaceID = getWorkspaceIDFromString("special:" + args, workspaceName);
|
||||
|
||||
@@ -1341,7 +1339,8 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
}
|
||||
|
||||
bool requestedWorkspaceIsAlreadyOpen = false;
|
||||
int specialOpenOnMonitor = g_pCompositor->m_pLastMonitor->specialWorkspaceID;
|
||||
const auto PMONITOR = *PFOLLOWMOUSE == 1 ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->m_pLastMonitor;
|
||||
int specialOpenOnMonitor = PMONITOR->specialWorkspaceID;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->specialWorkspaceID == workspaceID) {
|
||||
@@ -1358,12 +1357,12 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
if (requestedWorkspaceIsAlreadyOpen && specialOpenOnMonitor == workspaceID) {
|
||||
// already open on this monitor
|
||||
|
||||
g_pCompositor->m_pLastMonitor->specialWorkspaceID = 0;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
||||
PMONITOR->specialWorkspaceID = 0;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
||||
|
||||
g_pCompositor->getWorkspaceByID(workspaceID)->startAnim(false, false);
|
||||
|
||||
if (const auto PWINDOW = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace)->getLastFocusedWindow(); PWINDOW)
|
||||
if (const auto PWINDOW = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace)->getLastFocusedWindow(); PWINDOW)
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
else
|
||||
g_pInputManager->refocus();
|
||||
@@ -1371,9 +1370,9 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
// already open on another monitor
|
||||
|
||||
if (specialOpenOnMonitor) {
|
||||
g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->specialWorkspaceID)->startAnim(false, false);
|
||||
g_pCompositor->m_pLastMonitor->specialWorkspaceID = 0;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
||||
g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID)->startAnim(false, false);
|
||||
PMONITOR->specialWorkspaceID = 0;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
// move to current
|
||||
@@ -1382,8 +1381,9 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
|
||||
POLDMON->specialWorkspaceID = 0;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
|
||||
g_pCompositor->m_pLastMonitor->specialWorkspaceID = workspaceID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
||||
PMONITOR->specialWorkspaceID = workspaceID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
||||
PSPECIALWORKSPACE->m_iMonitorID = PMONITOR->ID;
|
||||
|
||||
if (const auto PWINDOW = PSPECIALWORKSPACE->getLastFocusedWindow(); PWINDOW)
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
@@ -1393,23 +1393,23 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
// not open anywhere
|
||||
|
||||
if (specialOpenOnMonitor) {
|
||||
g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->specialWorkspaceID)->startAnim(false, false);
|
||||
g_pCompositor->m_pLastMonitor->specialWorkspaceID = 0;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
||||
g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID)->startAnim(false, false);
|
||||
PMONITOR->specialWorkspaceID = 0;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceID);
|
||||
|
||||
if (!PSPECIALWORKSPACE) {
|
||||
// ??? happens sometimes...?
|
||||
PSPECIALWORKSPACE = g_pCompositor->createNewWorkspace(workspaceID, g_pCompositor->m_pLastMonitor->ID, workspaceName);
|
||||
PSPECIALWORKSPACE = g_pCompositor->createNewWorkspace(workspaceID, PMONITOR->ID, workspaceName);
|
||||
}
|
||||
|
||||
g_pCompositor->m_pLastMonitor->specialWorkspaceID = workspaceID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
||||
PMONITOR->specialWorkspaceID = workspaceID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
||||
|
||||
PSPECIALWORKSPACE->m_iMonitorID = PMONITOR->ID;
|
||||
PSPECIALWORKSPACE->startAnim(true, true);
|
||||
PSPECIALWORKSPACE->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
|
||||
|
||||
if (const auto PWINDOW = PSPECIALWORKSPACE->getLastFocusedWindow(); PWINDOW)
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
|
@@ -263,7 +263,7 @@ Vector2D CHyprXWaylandManager::getMaxSizeForWindow(CWindow* pWindow) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return Vector2D(99999, 99999);
|
||||
|
||||
if ((pWindow->m_bIsX11 && !pWindow->m_uSurface.xwayland->size_hints) || (!pWindow->m_bIsX11 && !pWindow->m_uSurface.xdg->toplevel))
|
||||
if ((pWindow->m_bIsX11 && !pWindow->m_uSurface.xwayland->size_hints) || (!pWindow->m_bIsX11 && !pWindow->m_uSurface.xdg->toplevel) || pWindow->m_sAdditionalConfigData.noMaxSize)
|
||||
return Vector2D(99999, 99999);
|
||||
|
||||
auto MAXSIZE = pWindow->m_bIsX11 ? Vector2D(pWindow->m_uSurface.xwayland->size_hints->max_width, pWindow->m_uSurface.xwayland->size_hints->max_height)
|
||||
|
@@ -73,9 +73,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
// XWayland windows sometimes issue constraints weirdly.
|
||||
// TODO: We probably should search their parent. wlr_xwayland_surface->parent
|
||||
const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
|
||||
const auto PCONSTRAINT = g_pCompositor->m_sSeat.mouse->currentConstraint;
|
||||
const auto PCONSTRAINT = constraintFromWlr(g_pCompositor->m_sSeat.mouse->currentConstraint);
|
||||
|
||||
if (!CONSTRAINTWINDOW) {
|
||||
if (!CONSTRAINTWINDOW || !PCONSTRAINT) {
|
||||
unconstrainMouse();
|
||||
} else {
|
||||
// Native Wayland apps know how 2 constrain themselves.
|
||||
@@ -86,7 +86,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (g_pCompositor->m_sSeat.mouse->currentConstraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) {
|
||||
// we just snap the cursor to where it should be.
|
||||
|
||||
Vector2D hint = { PCONSTRAINT->current.cursor_hint.x, PCONSTRAINT->current.cursor_hint.y };
|
||||
Vector2D hint = { PCONSTRAINT->positionHint.x, PCONSTRAINT->positionHint.y };
|
||||
|
||||
wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, CONSTRAINTPOS.x + hint.x, CONSTRAINTPOS.y + hint.y);
|
||||
|
||||
@@ -94,7 +94,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
// these are usually FPS games. They will use the relative motion.
|
||||
} else {
|
||||
// we restrict the cursor to the confined region
|
||||
if (!pixman_region32_contains_point(&PCONSTRAINT->region, mouseCoords.x - CONSTRAINTPOS.x, mouseCoords.y - CONSTRAINTPOS.y, nullptr)) {
|
||||
if (!pixman_region32_contains_point(&PCONSTRAINT->constraint->region, mouseCoords.x - CONSTRAINTPOS.x, mouseCoords.y - CONSTRAINTPOS.y, nullptr)) {
|
||||
if (g_pCompositor->m_sSeat.mouse->constraintActive) {
|
||||
wlr_cursor_warp_closest(g_pCompositor->m_sWLRCursor, NULL, mouseCoords.x, mouseCoords.y);
|
||||
mouseCoords = getMouseCoordsInternal();
|
||||
@@ -960,6 +960,12 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
|
||||
wlr_seat_pointer_warp(constraint->seat, constraint->current.cursor_hint.x, constraint->current.cursor_hint.y);
|
||||
}
|
||||
}
|
||||
|
||||
const auto PCONSTRAINT = constraintFromWlr(constraint);
|
||||
if (PCONSTRAINT) { // should never be null but who knows
|
||||
PCONSTRAINT->positionHint = Vector2D(constraint->current.cursor_hint.x, constraint->current.cursor_hint.y);
|
||||
PCONSTRAINT->hintSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1005,7 +1011,15 @@ void CInputManager::unconstrainMouse() {
|
||||
}
|
||||
|
||||
void Events::listener_commitConstraint(void* owner, void* data) {
|
||||
//g_pInputManager->recheckConstraint((SMouse*)owner);
|
||||
const auto PMOUSE = (SMouse*)owner;
|
||||
|
||||
if (PMOUSE->currentConstraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
|
||||
const auto PCONSTRAINT = g_pInputManager->constraintFromWlr(PMOUSE->currentConstraint);
|
||||
if (PCONSTRAINT) { // should never be null but who knows
|
||||
PCONSTRAINT->positionHint = Vector2D(PMOUSE->currentConstraint->current.cursor_hint.x, PMOUSE->currentConstraint->current.cursor_hint.y);
|
||||
PCONSTRAINT->hintSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::updateCapabilities() {
|
||||
@@ -1220,3 +1234,12 @@ std::string CInputManager::getNameForNewDevice(std::string internalName) {
|
||||
|
||||
return proposedNewName + (dupeno == 0 ? "" : ("-" + std::to_string(dupeno)));
|
||||
}
|
||||
|
||||
SConstraint* CInputManager::constraintFromWlr(wlr_pointer_constraint_v1* constraint) {
|
||||
for (auto& c : m_lConstraints) {
|
||||
if (c.constraint == constraint)
|
||||
return &c;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@@ -50,6 +50,7 @@ public:
|
||||
void constrainMouse(SMouse*, wlr_pointer_constraint_v1*);
|
||||
void recheckConstraint(SMouse*);
|
||||
void unconstrainMouse();
|
||||
SConstraint* constraintFromWlr(wlr_pointer_constraint_v1*);
|
||||
std::string getActiveLayoutForKeyboard(SKeyboard*);
|
||||
|
||||
Vector2D getMouseCoordsInternal();
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "ToplevelExportWlrFuncs.hpp"
|
||||
|
||||
#define TOPLEVEL_EXPORT_VERSION 1
|
||||
#define TOPLEVEL_EXPORT_VERSION 2
|
||||
|
||||
static void bindManagerInt(wl_client* client, void* data, uint32_t version, uint32_t id) {
|
||||
g_pProtocolManager->m_pToplevelExportProtocolManager->bindManager(client, data, version, id);
|
||||
@@ -41,8 +41,17 @@ CToplevelExportProtocolManager::CToplevelExportProtocolManager() {
|
||||
Debug::log(LOG, "ToplevelExportManager started successfully!");
|
||||
}
|
||||
|
||||
wlr_foreign_toplevel_handle_v1* zwlrHandleFromResource(wl_resource* resource) {
|
||||
// we can't assert here, but it doesnt matter.
|
||||
return (wlr_foreign_toplevel_handle_v1*)wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
void handleCaptureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, uint32_t handle) {
|
||||
g_pProtocolManager->m_pToplevelExportProtocolManager->captureToplevel(client, resource, frame, overlay_cursor, handle);
|
||||
g_pProtocolManager->m_pToplevelExportProtocolManager->captureToplevel(client, resource, frame, overlay_cursor, g_pCompositor->getWindowFromHandle(handle));
|
||||
}
|
||||
|
||||
void handleCaptureToplevelWithWlr(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* handle) {
|
||||
g_pProtocolManager->m_pToplevelExportProtocolManager->captureToplevel(client, resource, frame, overlay_cursor, g_pCompositor->getWindowFromZWLRHandle(handle));
|
||||
}
|
||||
|
||||
void handleDestroy(wl_client* client, wl_resource* resource) {
|
||||
@@ -59,7 +68,8 @@ void handleDestroyFrame(wl_client* client, wl_resource* resource) {
|
||||
|
||||
static const struct hyprland_toplevel_export_manager_v1_interface toplevelExportManagerImpl = {
|
||||
.capture_toplevel = handleCaptureToplevel,
|
||||
.destroy = handleDestroy
|
||||
.destroy = handleDestroy,
|
||||
.capture_toplevel_with_wlr_toplevel_handle = handleCaptureToplevelWithWlr,
|
||||
};
|
||||
|
||||
static const struct hyprland_toplevel_export_frame_v1_interface toplevelFrameImpl = {
|
||||
@@ -92,7 +102,7 @@ void CToplevelExportProtocolManager::removeClient(SToplevelClient* client, bool
|
||||
void handleManagerResourceDestroy(wl_resource* resource) {
|
||||
const auto PCLIENT = clientFromResource(resource);
|
||||
|
||||
g_pProtocolManager->m_pToplevelExportProtocolManager->removeClient(PCLIENT);
|
||||
g_pProtocolManager->m_pToplevelExportProtocolManager->removeClient(PCLIENT, true);
|
||||
}
|
||||
|
||||
void CToplevelExportProtocolManager::bindManager(wl_client* client, void* data, uint32_t version, uint32_t id) {
|
||||
@@ -133,26 +143,24 @@ void CToplevelExportProtocolManager::removeFrame(SToplevelFrame* frame, bool for
|
||||
m_lFrames.remove(*frame);
|
||||
}
|
||||
|
||||
void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, uint32_t handle) {
|
||||
void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, CWindow* pWindow) {
|
||||
const auto PCLIENT = clientFromResource(resource);
|
||||
|
||||
const auto PWINDOW = g_pCompositor->getWindowFromHandle(handle);
|
||||
|
||||
// create a frame
|
||||
const auto PFRAME = &m_lFrames.emplace_back();
|
||||
PFRAME->overlayCursor = !!overlay_cursor;
|
||||
PFRAME->resource = wl_resource_create(client, &hyprland_toplevel_export_frame_v1_interface, wl_resource_get_version(resource), frame);
|
||||
PFRAME->pWindow = PWINDOW;
|
||||
PFRAME->pWindow = pWindow;
|
||||
|
||||
if (!PWINDOW) {
|
||||
Debug::log(ERR, "Client requested sharing of window handle %x which does not exist!", handle);
|
||||
if (!PFRAME->pWindow) {
|
||||
Debug::log(ERR, "Client requested sharing of window handle %x which does not exist!", PFRAME->pWindow);
|
||||
hyprland_toplevel_export_frame_v1_send_failed(PFRAME->resource);
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden()) {
|
||||
Debug::log(ERR, "Client requested sharing of window handle %x which is not shareable!", handle);
|
||||
if (!PFRAME->pWindow->m_bIsMapped || PFRAME->pWindow->isHidden()) {
|
||||
Debug::log(ERR, "Client requested sharing of window handle %x which is not shareable!", PFRAME->pWindow);
|
||||
hyprland_toplevel_export_frame_v1_send_failed(PFRAME->resource);
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
@@ -170,7 +178,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
|
||||
PFRAME->client = PCLIENT;
|
||||
PCLIENT->ref++;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PFRAME->pWindow->m_iMonitorID);
|
||||
|
||||
PFRAME->shmFormat = wlr_output_preferred_read_format(PMONITOR->output);
|
||||
if (PFRAME->shmFormat == DRM_FORMAT_INVALID) {
|
||||
@@ -194,7 +202,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
|
||||
PFRAME->dmabufFormat = DRM_FORMAT_INVALID;
|
||||
}
|
||||
|
||||
PFRAME->box = {0, 0, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y};
|
||||
PFRAME->box = { 0, 0, (int)(PFRAME->pWindow->m_vRealSize.vec().x * PMONITOR->scale), (int)(PFRAME->pWindow->m_vRealSize.vec().y * PMONITOR->scale) };
|
||||
int ow, oh;
|
||||
wlr_output_effective_resolution(PMONITOR->output, &ow, &oh);
|
||||
wlr_box_transform(&PFRAME->box, &PFRAME->box, PMONITOR->transform, ow, oh);
|
||||
@@ -215,22 +223,26 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
|
||||
if (!PFRAME->pWindow->m_bIsMapped || PFRAME->pWindow->isHidden()) {
|
||||
Debug::log(ERR, "Client requested sharing of window handle %x which is not shareable (2)!", PFRAME->pWindow);
|
||||
hyprland_toplevel_export_frame_v1_send_failed(PFRAME->resource);
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PBUFFER = wlr_buffer_from_resource(buffer);
|
||||
if (!PBUFFER) {
|
||||
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PBUFFER->width != PFRAME->box.width || PBUFFER->height != PFRAME->box.height) {
|
||||
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PFRAME->buffer) {
|
||||
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_ALREADY_USED, "frame already used");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -243,6 +255,7 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
|
||||
|
||||
if (dmabufAttrs.format != PFRAME->dmabufFormat) {
|
||||
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
} else if (wlr_buffer_begin_data_ptr_access(PBUFFER, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &wlrBufferAccessData, &wlrBufferAccessFormat, &wlrBufferAccessStride)) {
|
||||
@@ -250,13 +263,16 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
|
||||
|
||||
if (wlrBufferAccessFormat != PFRAME->shmFormat) {
|
||||
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
} else if ((int)wlrBufferAccessStride != PFRAME->shmStride) {
|
||||
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer stride");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer type");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "wlr-foreign-toplevel-management-unstable-v1-protocol.h"
|
||||
#include "hyprland-toplevel-export-v1-protocol.h"
|
||||
|
||||
#include <list>
|
||||
@@ -45,7 +46,7 @@ public:
|
||||
CToplevelExportProtocolManager();
|
||||
|
||||
void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id);
|
||||
void captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, uint32_t handle);
|
||||
void captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, CWindow* handle);
|
||||
void removeClient(SToplevelClient* client, bool force = false);
|
||||
void removeFrame(SToplevelFrame* frame, bool force = false);
|
||||
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage);
|
||||
|
@@ -846,10 +846,10 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
pixman_region32_t inverseOpaque;
|
||||
pixman_region32_init(&inverseOpaque);
|
||||
if (a >= 255.f) {
|
||||
pixman_box32_t surfbox = {0, 0, pSurface->current.width, pSurface->current.height};
|
||||
pixman_box32_t surfbox = {0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale};
|
||||
pixman_region32_copy(&inverseOpaque, &pSurface->current.opaque);
|
||||
pixman_region32_inverse(&inverseOpaque, &inverseOpaque, &surfbox);
|
||||
pixman_region32_intersect_rect(&inverseOpaque, &inverseOpaque, 0, 0, pSurface->current.width, pSurface->current.height);
|
||||
pixman_region32_intersect_rect(&inverseOpaque, &inverseOpaque, 0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale);
|
||||
|
||||
if (!pixman_region32_not_empty(&inverseOpaque)) {
|
||||
pixman_region32_fini(&inverseOpaque);
|
||||
@@ -865,8 +865,16 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
|
||||
CFramebuffer* POUTFB = nullptr;
|
||||
if (!USENEWOPTIMIZE) {
|
||||
if (pSurface->current.scale != 1) {
|
||||
// wlroots prohibits shrinking a region
|
||||
// TODO: just shrink
|
||||
pixman_region32_union_rect(&inverseOpaque, &inverseOpaque, 0, 0, pBox->width, pBox->height);
|
||||
}
|
||||
|
||||
pixman_region32_translate(&inverseOpaque, pBox->x, pBox->y);
|
||||
|
||||
pixman_region32_intersect(&inverseOpaque, &inverseOpaque, &damage);
|
||||
|
||||
POUTFB = blurMainFramebufferWithDamage(a, pBox, &inverseOpaque);
|
||||
} else {
|
||||
POUTFB = &m_RenderData.pCurrentMonData->blurFB;
|
||||
|
@@ -89,7 +89,7 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor) {
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) && pWindow->m_bIsFloating /* tiled windows can't be multi-ws */)
|
||||
return !pWindow->m_bIsFullscreen; // Do not draw fullscreen windows on other monitors
|
||||
|
||||
if (pMonitor->specialWorkspaceID && g_pCompositor->isWorkspaceSpecial(pWindow->m_iWorkspaceID))
|
||||
if (pMonitor->specialWorkspaceID == pWindow->m_iWorkspaceID)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -255,12 +255,6 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
renderdata.fadeAlpha = 255.f;
|
||||
}
|
||||
|
||||
// apply window special data
|
||||
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;
|
||||
|
||||
// apply opaque
|
||||
if (pWindow->m_sAdditionalConfigData.forceOpaque)
|
||||
renderdata.alpha = 1.f;
|
||||
@@ -269,7 +263,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
|
||||
// clip box for animated offsets
|
||||
Vector2D offset;
|
||||
if (!ignorePosition && pWindow->m_bIsFloating) {
|
||||
if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bPinned) {
|
||||
if (PWORKSPACE->m_vRenderOffset.vec().x != 0) {
|
||||
const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.vec().x / PWSMON->vecSize.x;
|
||||
|
Submodule subprojects/hyprland-protocols updated: 0dcff94fc1...301733ae46
Submodule subprojects/wlroots updated: c8eb24d30e...86fc2199f8
Reference in New Issue
Block a user