Compare commits
9 commits
437f8af8cf
...
3431309511
Author | SHA1 | Date | |
---|---|---|---|
chayleaf | 3431309511 | ||
chayleaf | 4b560281bd | ||
chayleaf | 63eab7c843 | ||
chayleaf | 03332873d2 | ||
chayleaf | d7a732d78a | ||
chayleaf | 0b7fdd43cb | ||
chayleaf | b0b136b6d7 | ||
chayleaf | 8b6a6035c6 | ||
chayleaf | 5ef36a7b93 |
52
flake.lock
52
flake.lock
|
@ -143,6 +143,27 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"crane_2": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"unbound-rust-mod",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1722960479,
|
||||||
|
"narHash": "sha256-NhCkJJQhD5GUib8zN9JrmYGMwt4lCRp6ZVNzIiYCl0Y=",
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"rev": "4c6c77920b8d44cd6660c1621dea6b3fc4b4c4f4",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"disko": {
|
"disko": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
@ -324,16 +345,15 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1714645000,
|
"lastModified": 1723599998,
|
||||||
"narHash": "sha256-RelIgcYWJnUdE96Hjh8gR6wmsNgLc1LHDZY5VtdR6Eo=",
|
"narHash": "sha256-9a/Dq7WUhP35WrpqXUpDBsnKoKASsYB8FQjIeVlghm4=",
|
||||||
"owner": "chayleaf",
|
"owner": "chayleaf",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "2a477b78f5e95a0b8ed741786524ca0fbfe0c230",
|
"rev": "c29f1c444bbfe3cfa22e347923fe04245030bcda",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "chayleaf",
|
"owner": "chayleaf",
|
||||||
"ref": "librewolf",
|
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
@ -757,7 +777,8 @@
|
||||||
"notnft": "notnft",
|
"notnft": "notnft",
|
||||||
"nur": "nur",
|
"nur": "nur",
|
||||||
"osu-wine": "osu-wine",
|
"osu-wine": "osu-wine",
|
||||||
"rust-overlay": "rust-overlay"
|
"rust-overlay": "rust-overlay",
|
||||||
|
"unbound-rust-mod": "unbound-rust-mod"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rust-overlay": {
|
"rust-overlay": {
|
||||||
|
@ -908,6 +929,27 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"unbound-rust-mod": {
|
||||||
|
"inputs": {
|
||||||
|
"crane": "crane_2",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1723550937,
|
||||||
|
"narHash": "sha256-5gEXPy9qIrNi0nPk3D1ctVxh5Ndfrhyu+02R6BIcnHQ=",
|
||||||
|
"ref": "refs/heads/master",
|
||||||
|
"rev": "e0f642180056f351fd712f2b4f3149fd9f02367f",
|
||||||
|
"revCount": 24,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.pavluk.org/chayleaf/unbound-rust-mod.git"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.pavluk.org/chayleaf/unbound-rust-mod.git"
|
||||||
|
}
|
||||||
|
},
|
||||||
"utils": {
|
"utils": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems_2"
|
"systems": "systems_2"
|
||||||
|
|
22
flake.nix
22
flake.nix
|
@ -29,7 +29,7 @@
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
home-manager = {
|
home-manager = {
|
||||||
url = "github:chayleaf/home-manager/librewolf";
|
url = "github:chayleaf/home-manager";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
nix-gaming = {
|
nix-gaming = {
|
||||||
|
@ -52,6 +52,10 @@
|
||||||
url = "gitlab:simple-nixos-mailserver/nixos-mailserver";
|
url = "gitlab:simple-nixos-mailserver/nixos-mailserver";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
unbound-rust-mod = {
|
||||||
|
url = "git+https://git.pavluk.org/chayleaf/unbound-rust-mod.git";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
flake-compat = {
|
flake-compat = {
|
||||||
url = "github:edolstra/flake-compat";
|
url = "github:edolstra/flake-compat";
|
||||||
flake = false;
|
flake = false;
|
||||||
|
@ -69,6 +73,7 @@
|
||||||
# nixos-router = true;
|
# nixos-router = true;
|
||||||
# notnft = true;
|
# notnft = true;
|
||||||
# nixpkgs = true;
|
# nixpkgs = true;
|
||||||
|
# unbound-rust-mod = true;
|
||||||
};
|
};
|
||||||
# IRL-related stuff I'd rather not put into git
|
# IRL-related stuff I'd rather not put into git
|
||||||
priv =
|
priv =
|
||||||
|
@ -197,9 +202,11 @@
|
||||||
hardware = inputs.nixos-hardware.nixosModules;
|
hardware = inputs.nixos-hardware.nixosModules;
|
||||||
} // args.specialArgs or { };
|
} // args.specialArgs or { };
|
||||||
modules = [
|
modules = [
|
||||||
{ _module.args = {
|
({ config, ... }: {
|
||||||
pkgs-kernel = import inputs.nixpkgs-kernel { inherit (args) system; overlays = all-overlays; };
|
_module.args = {
|
||||||
}; }
|
pkgs-kernel = import inputs.nixpkgs-kernel { inherit (args) system; overlays = all-overlays ++ config.nixpkgs.overlays; };
|
||||||
|
};
|
||||||
|
})
|
||||||
(getPrivSys hostname)
|
(getPrivSys hostname)
|
||||||
{ networking.hostName = lib.mkDefault hostname;
|
{ networking.hostName = lib.mkDefault hostname;
|
||||||
nixpkgs.overlays = all-overlays; }
|
nixpkgs.overlays = all-overlays; }
|
||||||
|
@ -238,7 +245,11 @@
|
||||||
extraSpecialArgs = { inherit inputs; };
|
extraSpecialArgs = { inherit inputs; };
|
||||||
modules = [
|
modules = [
|
||||||
./home/hosts/remote.nix
|
./home/hosts/remote.nix
|
||||||
({ pkgs, ... }: { home.file.hysteria.source = pkgs.hysteria; })
|
({ pkgs, ... }: {
|
||||||
|
home.file.hysteria.source = pkgs.hysteria;
|
||||||
|
home.file.shadowsocks-libev.source = pkgs.shadowsocks-libev;
|
||||||
|
home.file.shadowsocks-rust.source = pkgs.shadowsocks-rust;
|
||||||
|
})
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -261,7 +272,6 @@
|
||||||
++ [
|
++ [
|
||||||
(getPrivUser hostname user)
|
(getPrivUser hostname user)
|
||||||
({ pkgs, lib, ... }: {
|
({ pkgs, lib, ... }: {
|
||||||
nixpkgs.overlays = all-overlays;
|
|
||||||
nix.package = lib.mkDefault pkgs.nixForNixPlugins;
|
nix.package = lib.mkDefault pkgs.nixForNixPlugins;
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
lalrpop
|
lalrpop
|
||||||
tio
|
tio
|
||||||
tdesktop
|
tdesktop
|
||||||
|
osu-wine
|
||||||
];
|
];
|
||||||
xdg.configFile."looking-glass/client.ini".text = ''
|
xdg.configFile."looking-glass/client.ini".text = ''
|
||||||
[app]
|
[app]
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
{
|
{
|
||||||
imports = [ ./gui.nix ];
|
imports = [ ./gui.nix ];
|
||||||
|
|
||||||
programs.firefox = {
|
programs.librewolf = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.wrapFirefox pkgs.librewolf-unwrapped {
|
package = pkgs.wrapFirefox pkgs.librewolf-unwrapped {
|
||||||
inherit (pkgs.librewolf-unwrapped) extraPrefsFiles extraPoliciesFiles;
|
inherit (pkgs.librewolf-unwrapped) extraPrefsFiles extraPoliciesFiles;
|
||||||
|
@ -15,6 +15,17 @@
|
||||||
libName = "librewolf";
|
libName = "librewolf";
|
||||||
nativeMessagingHosts = with pkgs; [ keepassxc ];
|
nativeMessagingHosts = with pkgs; [ keepassxc ];
|
||||||
};
|
};
|
||||||
|
profiles.other.id = 1;
|
||||||
|
profiles.other.bookmarks = [{
|
||||||
|
name = "bookmarklets";
|
||||||
|
toolbar = true;
|
||||||
|
bookmarks = [
|
||||||
|
{
|
||||||
|
name = "example.com";
|
||||||
|
url = "https://example.com";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}];
|
||||||
profiles.chayleaf = lib.mkMerge [
|
profiles.chayleaf = lib.mkMerge [
|
||||||
{
|
{
|
||||||
extensions = (with config.nur.repos.rycee.firefox-addons; [
|
extensions = (with config.nur.repos.rycee.firefox-addons; [
|
||||||
|
|
|
@ -172,11 +172,11 @@ commonConfig = {
|
||||||
names = [ "Noto Sans Mono" "Symbols Nerd Font Mono" ];
|
names = [ "Noto Sans Mono" "Symbols Nerd Font Mono" ];
|
||||||
size = 16.0;
|
size = 16.0;
|
||||||
};
|
};
|
||||||
gaps = {
|
# gaps = {
|
||||||
smartBorders = "on";
|
# smartBorders = "on";
|
||||||
smartGaps = true;
|
# smartGaps = true;
|
||||||
inner = 10;
|
# inner = 10;
|
||||||
};
|
# };
|
||||||
window.hideEdgeBorders = "smart";
|
window.hideEdgeBorders = "smart";
|
||||||
workspaceAutoBackAndForth = true;
|
workspaceAutoBackAndForth = true;
|
||||||
};
|
};
|
||||||
|
@ -259,15 +259,25 @@ in
|
||||||
'';
|
'';
|
||||||
wayland.windowManager.sway = {
|
wayland.windowManager.sway = {
|
||||||
wrapperFeatures.gtk = true;
|
wrapperFeatures.gtk = true;
|
||||||
package = pkgs.sway-unwrapped.overrideAttrs (old: {
|
package = let
|
||||||
|
cfg = config.wayland.windowManager.sway;
|
||||||
|
in pkgs.sway.override {
|
||||||
|
sway-unwrapped = pkgs.sway-unwrapped.overrideAttrs (old: {
|
||||||
patches = old.patches or [] ++ [
|
patches = old.patches or [] ++ [
|
||||||
./sway.patch
|
../../pkgs/sway/allow-other.patch
|
||||||
/*(pkgs.fetchpatch {
|
/*(pkgs.fetchpatch {
|
||||||
url = "https://patch-diff.githubusercontent.com/raw/swaywm/sway/pull/6920.patch";
|
url = "https://patch-diff.githubusercontent.com/raw/swaywm/sway/pull/6920.patch";
|
||||||
sha256 = "sha256-XgkysduhHbmprE334yeL65txpK0HNXeCmgCZMxpwsgU=";
|
sha256 = "sha256-XgkysduhHbmprE334yeL65txpK0HNXeCmgCZMxpwsgU=";
|
||||||
})*/
|
})*/
|
||||||
];
|
] ++ lib.optionals config.phone.enable
|
||||||
|
(map
|
||||||
|
(x: ../../pkgs/sway/${x})
|
||||||
|
(builtins.filter (lib.hasInfix "-mobile-") (builtins.attrNames (builtins.readDir ../../pkgs/sway))));
|
||||||
});
|
});
|
||||||
|
inherit (cfg) extraSessionCommands extraOptions;
|
||||||
|
withBaseWrapper = cfg.wrapperFeatures.base;
|
||||||
|
withGtkWrapper = cfg.wrapperFeatures.gtk;
|
||||||
|
};
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
title_align center
|
title_align center
|
||||||
'';
|
'';
|
||||||
|
@ -297,6 +307,11 @@ in
|
||||||
app_id = "^org.keepassxc.KeePassXC$";
|
app_id = "^org.keepassxc.KeePassXC$";
|
||||||
title = "^KeePassXC - (?:Browser |ブラウザーの)?(?:Access Request|アクセス要求)$";
|
title = "^KeePassXC - (?:Browser |ブラウザーの)?(?:Access Request|アクセス要求)$";
|
||||||
}; }
|
}; }
|
||||||
|
{ command = "floating on; border normal";
|
||||||
|
criteria = {
|
||||||
|
class = "ghidra-Ghidra";
|
||||||
|
title = "\\[CodeBrowser.*\\]$";
|
||||||
|
}; }
|
||||||
]; };
|
]; };
|
||||||
assigns = {
|
assigns = {
|
||||||
"2" = [
|
"2" = [
|
||||||
|
|
|
@ -19,8 +19,10 @@
|
||||||
sha256 = "sha256-zH4hbQ8+9TYRVW/XYqmAVsi0vsSPn1LPqXxr0gi0j1E=";
|
sha256 = "sha256-zH4hbQ8+9TYRVW/XYqmAVsi0vsSPn1LPqXxr0gi0j1E=";
|
||||||
};
|
};
|
||||||
});*/
|
});*/
|
||||||
settings = lib.toList {
|
settings = let
|
||||||
layer = "top";
|
layer = if config.phone.enable then "overlay" else "top";
|
||||||
|
in lib.toList {
|
||||||
|
inherit layer;
|
||||||
position = "top";
|
position = "top";
|
||||||
ipc = true;
|
ipc = true;
|
||||||
height = 40;
|
height = 40;
|
||||||
|
@ -151,7 +153,7 @@
|
||||||
};
|
};
|
||||||
} ++ lib.optionals config.phone.enable [
|
} ++ lib.optionals config.phone.enable [
|
||||||
{
|
{
|
||||||
layer = "top";
|
inherit layer;
|
||||||
position = "top";
|
position = "top";
|
||||||
ipc = true;
|
ipc = true;
|
||||||
height = 40;
|
height = 40;
|
||||||
|
@ -168,7 +170,7 @@
|
||||||
modules-right = [ "clock" ];
|
modules-right = [ "clock" ];
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
layer = "top";
|
inherit layer;
|
||||||
position = "bottom";
|
position = "bottom";
|
||||||
ipc = true;
|
ipc = true;
|
||||||
height = 80;
|
height = 80;
|
||||||
|
|
|
@ -22,6 +22,8 @@ in
|
||||||
inherit (inputs.osu-wine.packages.${pkgs.system}) osu-wine;
|
inherit (inputs.osu-wine.packages.${pkgs.system}) osu-wine;
|
||||||
matrix-appservice-discord = pkgs.callPackage ./matrix-appservice-discord { inherit (pkgs) matrix-appservice-discord; };
|
matrix-appservice-discord = pkgs.callPackage ./matrix-appservice-discord { inherit (pkgs) matrix-appservice-discord; };
|
||||||
|
|
||||||
|
krita = pkgs.callPackage ./krita { inherit (pkgs) krita; };
|
||||||
|
|
||||||
openssh = pkgs.openssh.overrideAttrs (old: rec {
|
openssh = pkgs.openssh.overrideAttrs (old: rec {
|
||||||
version = "9.8p1";
|
version = "9.8p1";
|
||||||
src = pkgs.fetchurl {
|
src = pkgs.fetchurl {
|
||||||
|
@ -30,6 +32,11 @@ in
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
inherit (inputs.unbound-rust-mod.packages.${pkgs.system}) unbound-mod;
|
||||||
|
unbound-full = pkgs.unbound-full.overrideAttrs (old: {
|
||||||
|
configureFlags = old.configureFlags ++ [ "--with-dynlibmodule" ];
|
||||||
|
});
|
||||||
|
|
||||||
buffyboard = pkgs.callPackage ./buffyboard { };
|
buffyboard = pkgs.callPackage ./buffyboard { };
|
||||||
clang-tools_latest = pkgs.clang-tools_16;
|
clang-tools_latest = pkgs.clang-tools_16;
|
||||||
clang_latest = pkgs.clang_16;
|
clang_latest = pkgs.clang_16;
|
||||||
|
@ -39,8 +46,12 @@ in
|
||||||
gimp = callPackage ./gimp { inherit (pkgs) gimp; };
|
gimp = callPackage ./gimp { inherit (pkgs) gimp; };
|
||||||
home-daemon = callPackage ./home-daemon { };
|
home-daemon = callPackage ./home-daemon { };
|
||||||
# pin version
|
# pin version
|
||||||
looking-glass-client = pkgs.looking-glass-client.overrideAttrs (old: {
|
looking-glass-client = pkgs.looking-glass-client.overrideAttrs (old: rec {
|
||||||
version = "B6";
|
version = "B6";
|
||||||
|
postUnpack = ''
|
||||||
|
echo ${src.rev} > source/VERSION
|
||||||
|
export sourceRoot="source/client"
|
||||||
|
'';
|
||||||
src = pkgs.fetchFromGitHub {
|
src = pkgs.fetchFromGitHub {
|
||||||
owner = "gnif";
|
owner = "gnif";
|
||||||
repo = "LookingGlass";
|
repo = "LookingGlass";
|
||||||
|
@ -50,8 +61,7 @@ in
|
||||||
};
|
};
|
||||||
patches = [ ];
|
patches = [ ];
|
||||||
});
|
});
|
||||||
kvmfrOverlay = kvmfr: kvmfr.overrideAttrs (old: {
|
kvmfrOverlay = kvmfr: (kvmfr.override { inherit (pkgs') looking-glass-client; }).overrideAttrs (old: {
|
||||||
inherit (pkgs'.looking-glass-client) version src;
|
|
||||||
patches = [ ./looking-glass.patch ];
|
patches = [ ./looking-glass.patch ];
|
||||||
});
|
});
|
||||||
mobile-config-firefox = callPackage ./mobile-config-firefox { };
|
mobile-config-firefox = callPackage ./mobile-config-firefox { };
|
||||||
|
|
12
pkgs/krita/default.nix
Normal file
12
pkgs/krita/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{ krita, python3Packages }:
|
||||||
|
|
||||||
|
(krita.override {
|
||||||
|
unwrapped = krita.unwrapped.overrideAttrs (old: { patches = old.patches or [] ++ [
|
||||||
|
./painting-api.patch
|
||||||
|
./fix-painting-api-crashes.patch
|
||||||
|
./painting-api-options.patch
|
||||||
|
./painting-api-pressure.patch
|
||||||
|
]; });
|
||||||
|
}).overrideAttrs (old: {
|
||||||
|
buildInputs = old.buildInputs ++ [ python3Packages.requests ];
|
||||||
|
})
|
145
pkgs/krita/fix-painting-api-crashes.patch
Normal file
145
pkgs/krita/fix-painting-api-crashes.patch
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
diff --git a/libs/libkis/Node.cpp b/libs/libkis/Node.cpp
|
||||||
|
index 84f24d3..0e2370e 100644
|
||||||
|
--- a/libs/libkis/Node.cpp
|
||||||
|
+++ b/libs/libkis/Node.cpp
|
||||||
|
@@ -76,6 +76,8 @@
|
||||||
|
#include "KisAsynchronousStrokeUpdateHelper.h"
|
||||||
|
#include "kis_stroke_strategy.h"
|
||||||
|
#include "PaintingResources.h"
|
||||||
|
+#include "KisMainWindow.h"
|
||||||
|
+#include "kis_canvas2.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct Node::Private {
|
||||||
|
@@ -833,8 +835,48 @@ KisNodeSP Node::node() const
|
||||||
|
return d->node;
|
||||||
|
}
|
||||||
|
|
||||||
|
+QString Node::paintAbility()
|
||||||
|
+{
|
||||||
|
+ // Taken from KisTool:nodePaintAbility().
|
||||||
|
+ KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow();
|
||||||
|
+ KisCanvas2 *canvas = mainWindow->activeView()->canvasBase();
|
||||||
|
+ if (canvas->resourceManager()->resource(KoCanvasResource::CurrentPaintOpPreset).isNull()) {
|
||||||
|
+ return "UNPAINTABLE";
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!d->node) {
|
||||||
|
+ return "UNPAINTABLE";
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (d->node->inherits("KisShapeLayer")) {
|
||||||
|
+ return "VECTOR";
|
||||||
|
+ }
|
||||||
|
+ if (d->node->inherits("KisCloneLayer")) {
|
||||||
|
+ return "CLONE";
|
||||||
|
+ }
|
||||||
|
+ if (d->node->paintDevice()) {
|
||||||
|
+
|
||||||
|
+ KisPaintOpPresetSP currentPaintOpPreset = canvas->resourceManager()->resource(KoCanvasResource::CurrentPaintOpPreset).value<KisPaintOpPresetSP>();
|
||||||
|
+ if (currentPaintOpPreset->paintOp().id() == "mypaintbrush") {
|
||||||
|
+ const KoColorSpace *colorSpace = d->node->paintDevice()->colorSpace();
|
||||||
|
+ if (colorSpace->colorModelId() != RGBAColorModelID) {
|
||||||
|
+ return "MYPAINTBRUSH_UNPAINTABLE";
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return "PAINT";
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return "UNPAINTABLE";
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void Node::paintLine(const QPointF pointOne, const QPointF pointTwo)
|
||||||
|
{
|
||||||
|
+ if (paintAbility() != "PAINT") {
|
||||||
|
+ dbgScript << "Script attempted to use Node::paintLine() on an unpaintable node, ignoring.";
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
KisPaintInformation pointOneInfo;
|
||||||
|
pointOneInfo.setPressure(1.0);
|
||||||
|
pointOneInfo.setPos(pointOne);
|
||||||
|
@@ -850,6 +892,11 @@ void Node::paintLine(const QPointF pointOne, const QPointF pointTwo)
|
||||||
|
|
||||||
|
void Node::paintRectangle(const QRectF &rect)
|
||||||
|
{
|
||||||
|
+ if (paintAbility() != "PAINT") {
|
||||||
|
+ dbgScript << "Script attempted to use Node::paintRectangle() on an unpaintable node, ignoring.";
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// reference class where this stuff is being done. Maybe can use the "facade" like that does for setup?
|
||||||
|
// void KisFigurePaintingToolHelper::paintRect(const QRectF &rect)
|
||||||
|
|
||||||
|
@@ -860,6 +907,11 @@ void Node::paintRectangle(const QRectF &rect)
|
||||||
|
|
||||||
|
void Node::paintPolygon(const QList<QPointF> listPoint)
|
||||||
|
{
|
||||||
|
+ if (paintAbility() != "PAINT") {
|
||||||
|
+ dbgScript << "Script attempted to use Node::paintPolygon() on an unpaintable node, ignoring.";
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// strategy needs points in vPointF format
|
||||||
|
QVector<QPointF> points = points.fromList(listPoint);
|
||||||
|
KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
@@ -869,6 +921,11 @@ void Node::paintPolygon(const QList<QPointF> listPoint)
|
||||||
|
|
||||||
|
void Node::paintEllipse(const QRectF &rect)
|
||||||
|
{
|
||||||
|
+ if (paintAbility() != "PAINT") {
|
||||||
|
+ dbgScript << "Script attempted to use Node::paintEllipse() on an unpaintable node, ignoring.";
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
helper.paintEllipse(rect);
|
||||||
|
}
|
||||||
|
@@ -876,6 +933,11 @@ void Node::paintEllipse(const QRectF &rect)
|
||||||
|
|
||||||
|
void Node::paintPath(const QPainterPath &path)
|
||||||
|
{
|
||||||
|
+ if (paintAbility() != "PAINT") {
|
||||||
|
+ dbgScript << "Script attempted to use Node::paintPath() on an unpaintable node, ignoring.";
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
helper.paintPainterPath(path);
|
||||||
|
}
|
||||||
|
diff --git a/libs/libkis/Node.h b/libs/libkis/Node.h
|
||||||
|
index 10daba4..89a6f40 100644
|
||||||
|
--- a/libs/libkis/Node.h
|
||||||
|
+++ b/libs/libkis/Node.h
|
||||||
|
@@ -601,6 +601,18 @@ public Q_SLOTS:
|
||||||
|
*/
|
||||||
|
void paintPath(const QPainterPath &path);
|
||||||
|
|
||||||
|
+ /**
|
||||||
|
+ * @brief paintAbility can be used to determine whether this node can be painted on with the current brush preset.
|
||||||
|
+ * @return QString, one of the following:
|
||||||
|
+ * <ul>
|
||||||
|
+ * <li>VECTOR - This node is vector-based.</li>
|
||||||
|
+ * <li>CLONE - This node is a Clone Layer.</li>
|
||||||
|
+ * <li>PAINT - This node is paintable by the current brush preset.</li>
|
||||||
|
+ * <li>UNPAINTABLE - This node is not paintable, or a null preset is somehow selected./li>
|
||||||
|
+ * <li>MYPAINTBRUSH_UNPAINTABLE - This node's non-RGBA colorspace cannot be painted on by the currently selected MyPaint brush.</li>
|
||||||
|
+ */
|
||||||
|
+ QString paintAbility();
|
||||||
|
+
|
||||||
|
private:
|
||||||
|
|
||||||
|
friend class Filter;
|
||||||
|
diff --git a/plugins/extensions/pykrita/sip/krita/Node.sip b/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
index cbcef0f..6270bd9 100644
|
||||||
|
--- a/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
+++ b/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
@@ -75,6 +75,7 @@ public Q_SLOTS:
|
||||||
|
void paintPolygon(const QList<QPointF> points);
|
||||||
|
void paintEllipse(const QRectF &rect);
|
||||||
|
void paintPath(const QPainterPath &path);
|
||||||
|
+ QString paintAbility();
|
||||||
|
Q_SIGNALS:
|
||||||
|
private:
|
||||||
|
};
|
332
pkgs/krita/painting-api-options.patch
Normal file
332
pkgs/krita/painting-api-options.patch
Normal file
|
@ -0,0 +1,332 @@
|
||||||
|
diff --git a/libs/libkis/Node.cpp b/libs/libkis/Node.cpp
|
||||||
|
index 0e2370e..3eed4ea 100644
|
||||||
|
--- a/libs/libkis/Node.cpp
|
||||||
|
+++ b/libs/libkis/Node.cpp
|
||||||
|
@@ -870,7 +870,7 @@ QString Node::paintAbility()
|
||||||
|
return "UNPAINTABLE";
|
||||||
|
}
|
||||||
|
|
||||||
|
-void Node::paintLine(const QPointF pointOne, const QPointF pointTwo)
|
||||||
|
+void Node::paintLine(const QPointF pointOne, const QPointF pointTwo, const QString strokeStyle)
|
||||||
|
{
|
||||||
|
if (paintAbility() != "PAINT") {
|
||||||
|
dbgScript << "Script attempted to use Node::paintLine() on an unpaintable node, ignoring.";
|
||||||
|
@@ -885,12 +885,12 @@ void Node::paintLine(const QPointF pointOne, const QPointF pointTwo)
|
||||||
|
pointTwoInfo.setPressure(1.0);
|
||||||
|
pointTwoInfo.setPos(pointTwo);
|
||||||
|
|
||||||
|
- KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
+ KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, strokeStyle);
|
||||||
|
helper.paintLine(pointOneInfo, pointTwoInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-void Node::paintRectangle(const QRectF &rect)
|
||||||
|
+void Node::paintRectangle(const QRectF &rect, const QString strokeStyle, const QString fillStyle)
|
||||||
|
{
|
||||||
|
if (paintAbility() != "PAINT") {
|
||||||
|
dbgScript << "Script attempted to use Node::paintRectangle() on an unpaintable node, ignoring.";
|
||||||
|
@@ -900,12 +900,12 @@ void Node::paintRectangle(const QRectF &rect)
|
||||||
|
// reference class where this stuff is being done. Maybe can use the "facade" like that does for setup?
|
||||||
|
// void KisFigurePaintingToolHelper::paintRect(const QRectF &rect)
|
||||||
|
|
||||||
|
- KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
+ KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, strokeStyle, fillStyle);
|
||||||
|
helper.paintRect(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-void Node::paintPolygon(const QList<QPointF> listPoint)
|
||||||
|
+void Node::paintPolygon(const QList<QPointF> listPoint, const QString strokeStyle, const QString fillStyle)
|
||||||
|
{
|
||||||
|
if (paintAbility() != "PAINT") {
|
||||||
|
dbgScript << "Script attempted to use Node::paintPolygon() on an unpaintable node, ignoring.";
|
||||||
|
@@ -914,30 +914,30 @@ void Node::paintPolygon(const QList<QPointF> listPoint)
|
||||||
|
|
||||||
|
// strategy needs points in vPointF format
|
||||||
|
QVector<QPointF> points = points.fromList(listPoint);
|
||||||
|
- KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
+ KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, strokeStyle, fillStyle);
|
||||||
|
helper.paintPolygon(points);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-void Node::paintEllipse(const QRectF &rect)
|
||||||
|
+void Node::paintEllipse(const QRectF &rect, const QString strokeStyle, const QString fillStyle)
|
||||||
|
{
|
||||||
|
if (paintAbility() != "PAINT") {
|
||||||
|
dbgScript << "Script attempted to use Node::paintEllipse() on an unpaintable node, ignoring.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
+ KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, strokeStyle, fillStyle);
|
||||||
|
helper.paintEllipse(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-void Node::paintPath(const QPainterPath &path)
|
||||||
|
+void Node::paintPath(const QPainterPath &path, const QString strokeStyle, const QString fillStyle)
|
||||||
|
{
|
||||||
|
if (paintAbility() != "PAINT") {
|
||||||
|
dbgScript << "Script attempted to use Node::paintPath() on an unpaintable node, ignoring.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
+ KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, strokeStyle, fillStyle);
|
||||||
|
helper.paintPainterPath(path);
|
||||||
|
}
|
||||||
|
diff --git a/libs/libkis/Node.h b/libs/libkis/Node.h
|
||||||
|
index 89a6f40..ecf9845 100644
|
||||||
|
--- a/libs/libkis/Node.h
|
||||||
|
+++ b/libs/libkis/Node.h
|
||||||
|
@@ -13,6 +13,8 @@
|
||||||
|
#include "kritalibkis_export.h"
|
||||||
|
#include "libkis.h"
|
||||||
|
|
||||||
|
+#include "PaintingResources.h"
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* Node represents a layer or mask in a Krita image's Node hierarchy. Group layers can contain
|
||||||
|
* other layers and masks; layers can contain masks.
|
||||||
|
@@ -574,33 +576,101 @@ public Q_SLOTS:
|
||||||
|
* @brief paint a line on the canvas. Uses current brush preset
|
||||||
|
* @param pointOne starting point
|
||||||
|
* @param pointTwo end point
|
||||||
|
+ * @param strokeStyle appearance of the outline, one of:
|
||||||
|
+ * <ul>
|
||||||
|
+ * <li>None - will use Foreground Color, since line would be invisible otherwise
|
||||||
|
+ * <li>ForegroundColor</li>
|
||||||
|
+ * <li>BackgroundColor</li>
|
||||||
|
+ * </ul>
|
||||||
|
*/
|
||||||
|
- void paintLine(const QPointF pointOne, const QPointF pointTwo);
|
||||||
|
+ void paintLine(const QPointF pointOne, const QPointF pointTwo, const QString strokeStyle = PaintingResources::defaultStrokeStyle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief paint a rectangle on the canvas. Uses current brush preset
|
||||||
|
* @param rect QRect with x, y, width, and height
|
||||||
|
+ * @param strokeStyle appearance of the outline, one of:
|
||||||
|
+ * <ul>
|
||||||
|
+ * <li>None
|
||||||
|
+ * <li>ForegroundColor</li>
|
||||||
|
+ * <li>BackgroundColor</li>
|
||||||
|
+ * </ul>
|
||||||
|
+ * Default is ForegroundColor.
|
||||||
|
+ * @param fillStyle appearance of the fill, one of:
|
||||||
|
+ * <ul>
|
||||||
|
+ * <li>None
|
||||||
|
+ * <li>ForegroundColor</li>
|
||||||
|
+ * <li>BackgroundColor</li>
|
||||||
|
+ * <li>Pattern</li>
|
||||||
|
+ * </ul>
|
||||||
|
+ * Default is None.
|
||||||
|
*/
|
||||||
|
- void paintRectangle(const QRectF &rect);
|
||||||
|
+ void paintRectangle(const QRectF &rect,
|
||||||
|
+ const QString strokeStyle = PaintingResources::defaultStrokeStyle,
|
||||||
|
+ const QString fillStyle = PaintingResources::defaultFillStyle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief paint a polygon on the canvas. Uses current brush preset
|
||||||
|
* @param list of Qpoints
|
||||||
|
+ * <ul>
|
||||||
|
+ * <li>None
|
||||||
|
+ * <li>ForegroundColor</li>
|
||||||
|
+ * <li>BackgroundColor</li>
|
||||||
|
+ * </ul>
|
||||||
|
+ * Default is ForegroundColor.
|
||||||
|
+ * @param fillStyle appearance of the fill, one of:
|
||||||
|
+ * <ul>
|
||||||
|
+ * <li>None
|
||||||
|
+ * <li>ForegroundColor</li>
|
||||||
|
+ * <li>BackgroundColor</li>
|
||||||
|
+ * <li>Pattern</li>
|
||||||
|
+ * </ul>
|
||||||
|
+ * Default is None.
|
||||||
|
*/
|
||||||
|
- void paintPolygon(const QList<QPointF> points);
|
||||||
|
-
|
||||||
|
+ void paintPolygon(const QList<QPointF> points,
|
||||||
|
+ const QString strokeStyle = PaintingResources::defaultStrokeStyle,
|
||||||
|
+ const QString fillStyle = PaintingResources::defaultFillStyle);
|
||||||
|
/**
|
||||||
|
* @brief paint an ellipse on the canvas. Uses current brush preset
|
||||||
|
* @param rect QRect with x, y, width, and height
|
||||||
|
+ * <ul>
|
||||||
|
+ * <li>None
|
||||||
|
+ * <li>ForegroundColor</li>
|
||||||
|
+ * <li>BackgroundColor</li>
|
||||||
|
+ * </ul>
|
||||||
|
+ * Default is ForegroundColor.
|
||||||
|
+ * @param fillStyle appearance of the fill, one of:
|
||||||
|
+ * <ul>
|
||||||
|
+ * <li>None
|
||||||
|
+ * <li>ForegroundColor</li>
|
||||||
|
+ * <li>BackgroundColor</li>
|
||||||
|
+ * <li>Pattern</li>
|
||||||
|
+ * </ul>
|
||||||
|
+ * Default is None.
|
||||||
|
*/
|
||||||
|
- void paintEllipse(const QRectF &rect);
|
||||||
|
-
|
||||||
|
+ void paintEllipse(const QRectF &rect,
|
||||||
|
+ const QString strokeStyle = PaintingResources::defaultStrokeStyle,
|
||||||
|
+ const QString fillStyle = PaintingResources::defaultFillStyle);
|
||||||
|
/**
|
||||||
|
* @brief paint a custom path on the canvas. Uses current brush preset
|
||||||
|
* @param path QPainterPath to determine path
|
||||||
|
+ * <ul>
|
||||||
|
+ * <li>None
|
||||||
|
+ * <li>ForegroundColor</li>
|
||||||
|
+ * <li>BackgroundColor</li>
|
||||||
|
+ * </ul>
|
||||||
|
+ * Default is ForegroundColor.
|
||||||
|
+ * @param fillStyle appearance of the fill, one of:
|
||||||
|
+ * <ul>
|
||||||
|
+ * <li>None
|
||||||
|
+ * <li>ForegroundColor</li>
|
||||||
|
+ * <li>BackgroundColor</li>
|
||||||
|
+ * <li>Pattern</li>
|
||||||
|
+ * </ul>
|
||||||
|
+ * Default is None.
|
||||||
|
*/
|
||||||
|
- void paintPath(const QPainterPath &path);
|
||||||
|
-
|
||||||
|
+ void paintPath(const QPainterPath &path,
|
||||||
|
+ const QString strokeStyle = PaintingResources::defaultStrokeStyle,
|
||||||
|
+ const QString fillStyle = PaintingResources::defaultFillStyle);
|
||||||
|
/**
|
||||||
|
* @brief paintAbility can be used to determine whether this node can be painted on with the current brush preset.
|
||||||
|
* @return QString, one of the following:
|
||||||
|
@@ -610,6 +680,7 @@ public Q_SLOTS:
|
||||||
|
* <li>PAINT - This node is paintable by the current brush preset.</li>
|
||||||
|
* <li>UNPAINTABLE - This node is not paintable, or a null preset is somehow selected./li>
|
||||||
|
* <li>MYPAINTBRUSH_UNPAINTABLE - This node's non-RGBA colorspace cannot be painted on by the currently selected MyPaint brush.</li>
|
||||||
|
+ * </ul>
|
||||||
|
*/
|
||||||
|
QString paintAbility();
|
||||||
|
|
||||||
|
diff --git a/libs/libkis/PaintingResources.cpp b/libs/libkis/PaintingResources.cpp
|
||||||
|
index 62abb26..58d67ae 100644
|
||||||
|
--- a/libs/libkis/PaintingResources.cpp
|
||||||
|
+++ b/libs/libkis/PaintingResources.cpp
|
||||||
|
@@ -53,9 +53,28 @@
|
||||||
|
#include "kis_painting_information_builder.h"
|
||||||
|
#include "KisAsynchronousStrokeUpdateHelper.h"
|
||||||
|
#include "kis_stroke_strategy.h"
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-KisFigurePaintingToolHelper PaintingResources::createHelper(KisImageWSP image)
|
||||||
|
+#include "KisViewManager.h"
|
||||||
|
+#include "KisMainWindow.h"
|
||||||
|
+#include "kis_image.h"
|
||||||
|
+#include "KisToolShapeUtils.h"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+const QStringList StrokeStyle = {
|
||||||
|
+ "None", // 0 = KisToolShapeUtils::StrokeStyle::StrokeStyleNone
|
||||||
|
+ "ForegroundColor", // KisToolShapeUtils::StrokeStyle::StrokeStyleForeground
|
||||||
|
+ "BackgroundColor" // KisToolShapeUtils::StrokeStyle::StrokeStyleBackground
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+const QStringList FillStyle = {
|
||||||
|
+ "None", // 0 = KisToolShapeUtils::FillStyle::FillStyleNone
|
||||||
|
+ "ForegroundColor", // KisToolShapeUtils::FillStyle::FillStyleForegroundColor
|
||||||
|
+ "BackgroundColor", // KisToolShapeUtils::FillStyle::FillStyleBackgroundColor
|
||||||
|
+ "Pattern" // KisToolShapeUtils::FillStyle::FillStylePattern
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+KisFigurePaintingToolHelper PaintingResources::createHelper(KisImageWSP image,
|
||||||
|
+ const QString strokeStyleString,
|
||||||
|
+ const QString fillStyleString)
|
||||||
|
{
|
||||||
|
// need to grab the resource provider
|
||||||
|
KisView *activeView = KisPart::instance()->currentMainwindow()->activeView();
|
||||||
|
@@ -64,13 +83,35 @@ KisFigurePaintingToolHelper PaintingResources::createHelper(KisImageWSP image)
|
||||||
|
// grab the image and current layer
|
||||||
|
KisNodeSP node = activeView->currentNode();
|
||||||
|
|
||||||
|
- const KUndo2MagicString name = kundo2_noi18n("python_stroke");
|
||||||
|
+ int strokeIndex = StrokeStyle.indexOf(strokeStyleString);
|
||||||
|
+ if (strokeIndex == -1) {
|
||||||
|
+ dbgScript << "Script tried to paint with invalid strokeStyle" << strokeStyleString << ", ignoring and using" << defaultStrokeStyle << ".";
|
||||||
|
+ strokeIndex = StrokeStyle.indexOf(defaultStrokeStyle);
|
||||||
|
+ if (strokeIndex == -1) {
|
||||||
|
+ warnScript << "PaintingResources::createHelper(): defaultStrokeStyle" << defaultStrokeStyle << "is invalid!";
|
||||||
|
+ strokeIndex = 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ KisToolShapeUtils::StrokeStyle strokeStyle = (KisToolShapeUtils::StrokeStyle) strokeIndex;
|
||||||
|
+
|
||||||
|
+ int fillIndex = FillStyle.indexOf(fillStyleString);
|
||||||
|
+ if (fillIndex == -1) {
|
||||||
|
+ dbgScript << "Script tried to paint with invalid fillStyle" << fillStyleString << ", ignoring and using" << defaultFillStyle << ".";
|
||||||
|
+ fillIndex = FillStyle.indexOf(defaultFillStyle);
|
||||||
|
+ if (fillIndex == -1) {
|
||||||
|
+ warnScript << "PaintingResources::createHelper(): defaultFillStyle" << defaultFillStyle << " is invalid!";
|
||||||
|
+ fillIndex = 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ KisToolShapeUtils::FillStyle fillStyle = (KisToolShapeUtils::FillStyle) fillIndex;
|
||||||
|
+
|
||||||
|
+ const KUndo2MagicString name = kundo2_i18n("Scripted Brush Stroke");
|
||||||
|
KisFigurePaintingToolHelper helper(
|
||||||
|
name,
|
||||||
|
image,
|
||||||
|
node, resourceManager,
|
||||||
|
- KisToolShapeUtils::StrokeStyle::StrokeStyleForeground,
|
||||||
|
- KisToolShapeUtils::FillStyle::FillStyleNone
|
||||||
|
+ strokeStyle,
|
||||||
|
+ fillStyle
|
||||||
|
);
|
||||||
|
|
||||||
|
return helper;
|
||||||
|
diff --git a/libs/libkis/PaintingResources.h b/libs/libkis/PaintingResources.h
|
||||||
|
index 19bb0d4..174057a 100644
|
||||||
|
--- a/libs/libkis/PaintingResources.h
|
||||||
|
+++ b/libs/libkis/PaintingResources.h
|
||||||
|
@@ -35,12 +35,19 @@
|
||||||
|
/**
|
||||||
|
* @brief The PaintingResources namespace
|
||||||
|
* Sets up information related to making painting strokes.
|
||||||
|
- * Used primarily in the Document class
|
||||||
|
+ * Used primarily in the Node class
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
namespace PaintingResources
|
||||||
|
{
|
||||||
|
- KisFigurePaintingToolHelper createHelper(KisImageWSP image);
|
||||||
|
+ // These are set in Node.sip
|
||||||
|
+ const QString defaultStrokeStyle = "ForegroundColor";
|
||||||
|
+ const QString defaultFillStyle = "None";
|
||||||
|
+
|
||||||
|
+ KisFigurePaintingToolHelper createHelper(KisImageWSP image,
|
||||||
|
+ const QString strokeStyle = defaultStrokeStyle,
|
||||||
|
+ const QString fillStyle = defaultFillStyle);
|
||||||
|
+
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LIBKIS_PAINTINGRESOURCES_H
|
||||||
|
diff --git a/plugins/extensions/pykrita/sip/krita/Node.sip b/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
index 6270bd9..884e615 100644
|
||||||
|
--- a/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
+++ b/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
@@ -70,11 +70,11 @@ public Q_SLOTS:
|
||||||
|
int index() const;
|
||||||
|
QUuid uniqueId() const;
|
||||||
|
|
||||||
|
- void paintLine(const QPoint pointOne, const QPoint pointTwo);
|
||||||
|
- void paintRectangle(const QRectF &rect);
|
||||||
|
- void paintPolygon(const QList<QPointF> points);
|
||||||
|
- void paintEllipse(const QRectF &rect);
|
||||||
|
- void paintPath(const QPainterPath &path);
|
||||||
|
+ void paintLine(const QPoint pointOne, const QPoint pointTwo, const QString strokeStyle = "ForegroundColor");
|
||||||
|
+ void paintRectangle(const QRectF &rect, const QString strokeStyle = "ForegroundColor", const QString fillStyle = "None");
|
||||||
|
+ void paintPolygon(const QList<QPointF> points, const QString strokeStyle = "ForegroundColor", const QString fillStyle = "None");
|
||||||
|
+ void paintEllipse(const QRectF &rect, const QString strokeStyle = "ForegroundColor", const QString fillStyle = "None");
|
||||||
|
+ void paintPath(const QPainterPath &path, const QString strokeStyle = "ForegroundColor", const QString fillStyle = "None");
|
||||||
|
QString paintAbility();
|
||||||
|
Q_SIGNALS:
|
||||||
|
private:
|
66
pkgs/krita/painting-api-pressure.patch
Normal file
66
pkgs/krita/painting-api-pressure.patch
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
diff --git a/libs/libkis/Node.cpp b/libs/libkis/Node.cpp
|
||||||
|
index 7e15b58c2c..a187c18aad 100644
|
||||||
|
--- a/libs/libkis/Node.cpp
|
||||||
|
+++ b/libs/libkis/Node.cpp
|
||||||
|
@@ -863,7 +863,7 @@ QString Node::paintAbility()
|
||||||
|
return "UNPAINTABLE";
|
||||||
|
}
|
||||||
|
|
||||||
|
-void Node::paintLine(const QPointF pointOne, const QPointF pointTwo, const QString strokeStyle)
|
||||||
|
+void Node::paintLine(const QPointF pointOne, const QPointF pointTwo, double pressureOne, double pressureTwo, const QString strokeStyle)
|
||||||
|
{
|
||||||
|
if (paintAbility() != "PAINT") {
|
||||||
|
dbgScript << "Script attempted to use Node::paintLine() on an unpaintable node, ignoring.";
|
||||||
|
@@ -871,11 +871,11 @@ void Node::paintLine(const QPointF pointOne, const QPointF pointTwo, const QStri
|
||||||
|
}
|
||||||
|
|
||||||
|
KisPaintInformation pointOneInfo;
|
||||||
|
- pointOneInfo.setPressure(1.0);
|
||||||
|
+ pointOneInfo.setPressure(pressureOne);
|
||||||
|
pointOneInfo.setPos(pointOne);
|
||||||
|
|
||||||
|
KisPaintInformation pointTwoInfo;
|
||||||
|
- pointTwoInfo.setPressure(1.0);
|
||||||
|
+ pointTwoInfo.setPressure(pressureTwo);
|
||||||
|
pointTwoInfo.setPos(pointTwo);
|
||||||
|
|
||||||
|
KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, strokeStyle);
|
||||||
|
diff --git a/libs/libkis/Node.h b/libs/libkis/Node.h
|
||||||
|
index ecf9845a22..ce63d3f1bc 100644
|
||||||
|
--- a/libs/libkis/Node.h
|
||||||
|
+++ b/libs/libkis/Node.h
|
||||||
|
@@ -576,6 +576,8 @@ public Q_SLOTS:
|
||||||
|
* @brief paint a line on the canvas. Uses current brush preset
|
||||||
|
* @param pointOne starting point
|
||||||
|
* @param pointTwo end point
|
||||||
|
+ * @param pressureOne starting pressure
|
||||||
|
+ * @param pressureTwo end pressure
|
||||||
|
* @param strokeStyle appearance of the outline, one of:
|
||||||
|
* <ul>
|
||||||
|
* <li>None - will use Foreground Color, since line would be invisible otherwise
|
||||||
|
@@ -583,7 +585,11 @@ public Q_SLOTS:
|
||||||
|
* <li>BackgroundColor</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
- void paintLine(const QPointF pointOne, const QPointF pointTwo, const QString strokeStyle = PaintingResources::defaultStrokeStyle);
|
||||||
|
+ void paintLine(const QPointF pointOne,
|
||||||
|
+ const QPointF pointTwo,
|
||||||
|
+ double pressureOne = 1.0,
|
||||||
|
+ double pressureTwo = 1.0,
|
||||||
|
+ const QString strokeStyle = PaintingResources::defaultStrokeStyle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief paint a rectangle on the canvas. Uses current brush preset
|
||||||
|
diff --git a/plugins/extensions/pykrita/sip/krita/Node.sip b/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
index a01a6bce6f..986cc54169 100644
|
||||||
|
--- a/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
+++ b/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
@@ -82,7 +82,7 @@ public Q_SLOTS:
|
||||||
|
int index() const;
|
||||||
|
QUuid uniqueId() const;
|
||||||
|
|
||||||
|
- void paintLine(const QPoint pointOne, const QPoint pointTwo, const QString strokeStyle = "ForegroundColor");
|
||||||
|
+ void paintLine(const QPoint pointOne, const QPoint pointTwo, double pressureOne = 1.0, double pressureTwo = 1.0, const QString strokeStyle = "ForegroundColor");
|
||||||
|
void paintRectangle(const QRectF &rect, const QString strokeStyle = "ForegroundColor", const QString fillStyle = "None");
|
||||||
|
void paintPolygon(const QList<QPointF> points, const QString strokeStyle = "ForegroundColor", const QString fillStyle = "None");
|
||||||
|
void paintEllipse(const QRectF &rect, const QString strokeStyle = "ForegroundColor", const QString fillStyle = "None");
|
309
pkgs/krita/painting-api.patch
Normal file
309
pkgs/krita/painting-api.patch
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
diff --git a/libs/libkis/CMakeLists.txt b/libs/libkis/CMakeLists.txt
|
||||||
|
index a337451..66a5166 100644
|
||||||
|
--- a/libs/libkis/CMakeLists.txt
|
||||||
|
+++ b/libs/libkis/CMakeLists.txt
|
||||||
|
@@ -10,6 +10,7 @@ set(kritalibkis_LIB_SRCS
|
||||||
|
ManagedColor.cpp
|
||||||
|
Node.cpp
|
||||||
|
Notifier.cpp
|
||||||
|
+ PaintingResources.cpp
|
||||||
|
PresetChooser.cpp
|
||||||
|
Preset.cpp
|
||||||
|
Palette.cpp
|
||||||
|
diff --git a/libs/libkis/Document.h b/libs/libkis/Document.h
|
||||||
|
index 998a350..841c319 100644
|
||||||
|
--- a/libs/libkis/Document.h
|
||||||
|
+++ b/libs/libkis/Document.h
|
||||||
|
@@ -6,8 +6,6 @@
|
||||||
|
#ifndef LIBKIS_DOCUMENT_H
|
||||||
|
#define LIBKIS_DOCUMENT_H
|
||||||
|
|
||||||
|
-#include <QObject>
|
||||||
|
-
|
||||||
|
#include "kritalibkis_export.h"
|
||||||
|
#include "libkis.h"
|
||||||
|
|
||||||
|
diff --git a/libs/libkis/Node.cpp b/libs/libkis/Node.cpp
|
||||||
|
index 3fd7b5a..84f24d3 100644
|
||||||
|
--- a/libs/libkis/Node.cpp
|
||||||
|
+++ b/libs/libkis/Node.cpp
|
||||||
|
@@ -67,6 +67,17 @@
|
||||||
|
#include "LibKisUtils.h"
|
||||||
|
#include <kis_layer_utils.h>
|
||||||
|
|
||||||
|
+#include <KoCanvasResourceProvider.h>
|
||||||
|
+#include "strokes/KisFreehandStrokeInfo.h"
|
||||||
|
+#include "kis_resources_snapshot.h"
|
||||||
|
+#include "kis_canvas_resource_provider.h"
|
||||||
|
+#include "strokes/freehand_stroke.h"
|
||||||
|
+#include "kis_painting_information_builder.h"
|
||||||
|
+#include "KisAsynchronousStrokeUpdateHelper.h"
|
||||||
|
+#include "kis_stroke_strategy.h"
|
||||||
|
+#include "PaintingResources.h"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
struct Node::Private {
|
||||||
|
Private() {}
|
||||||
|
KisImageWSP image;
|
||||||
|
@@ -821,3 +832,50 @@ KisNodeSP Node::node() const
|
||||||
|
{
|
||||||
|
return d->node;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+void Node::paintLine(const QPointF pointOne, const QPointF pointTwo)
|
||||||
|
+{
|
||||||
|
+ KisPaintInformation pointOneInfo;
|
||||||
|
+ pointOneInfo.setPressure(1.0);
|
||||||
|
+ pointOneInfo.setPos(pointOne);
|
||||||
|
+
|
||||||
|
+ KisPaintInformation pointTwoInfo;
|
||||||
|
+ pointTwoInfo.setPressure(1.0);
|
||||||
|
+ pointTwoInfo.setPos(pointTwo);
|
||||||
|
+
|
||||||
|
+ KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
+ helper.paintLine(pointOneInfo, pointTwoInfo);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+void Node::paintRectangle(const QRectF &rect)
|
||||||
|
+{
|
||||||
|
+ // reference class where this stuff is being done. Maybe can use the "facade" like that does for setup?
|
||||||
|
+ // void KisFigurePaintingToolHelper::paintRect(const QRectF &rect)
|
||||||
|
+
|
||||||
|
+ KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
+ helper.paintRect(rect);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+void Node::paintPolygon(const QList<QPointF> listPoint)
|
||||||
|
+{
|
||||||
|
+ // strategy needs points in vPointF format
|
||||||
|
+ QVector<QPointF> points = points.fromList(listPoint);
|
||||||
|
+ KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
+ helper.paintPolygon(points);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+void Node::paintEllipse(const QRectF &rect)
|
||||||
|
+{
|
||||||
|
+ KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
+ helper.paintEllipse(rect);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+void Node::paintPath(const QPainterPath &path)
|
||||||
|
+{
|
||||||
|
+ KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image);
|
||||||
|
+ helper.paintPainterPath(path);
|
||||||
|
+}
|
||||||
|
diff --git a/libs/libkis/Node.h b/libs/libkis/Node.h
|
||||||
|
index 1a40372..10daba4 100644
|
||||||
|
--- a/libs/libkis/Node.h
|
||||||
|
+++ b/libs/libkis/Node.h
|
||||||
|
@@ -570,6 +570,36 @@ public Q_SLOTS:
|
||||||
|
*/
|
||||||
|
QUuid uniqueId() const;
|
||||||
|
|
||||||
|
+ /**
|
||||||
|
+ * @brief paint a line on the canvas. Uses current brush preset
|
||||||
|
+ * @param pointOne starting point
|
||||||
|
+ * @param pointTwo end point
|
||||||
|
+ */
|
||||||
|
+ void paintLine(const QPointF pointOne, const QPointF pointTwo);
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * @brief paint a rectangle on the canvas. Uses current brush preset
|
||||||
|
+ * @param rect QRect with x, y, width, and height
|
||||||
|
+ */
|
||||||
|
+ void paintRectangle(const QRectF &rect);
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * @brief paint a polygon on the canvas. Uses current brush preset
|
||||||
|
+ * @param list of Qpoints
|
||||||
|
+ */
|
||||||
|
+ void paintPolygon(const QList<QPointF> points);
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * @brief paint an ellipse on the canvas. Uses current brush preset
|
||||||
|
+ * @param rect QRect with x, y, width, and height
|
||||||
|
+ */
|
||||||
|
+ void paintEllipse(const QRectF &rect);
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * @brief paint a custom path on the canvas. Uses current brush preset
|
||||||
|
+ * @param path QPainterPath to determine path
|
||||||
|
+ */
|
||||||
|
+ void paintPath(const QPainterPath &path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
diff --git a/libs/libkis/PaintingResources.cpp b/libs/libkis/PaintingResources.cpp
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..62abb26
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libs/libkis/PaintingResources.cpp
|
||||||
|
@@ -0,0 +1,77 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2020 Scott Petrovic <scottpetrovic@gmail.com>
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
+ * the Free Software Foundation; either version 2 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU Lesser General Public License
|
||||||
|
+ * along with this program; if not, write to the Free Software
|
||||||
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
+ */
|
||||||
|
+#include "PaintingResources.h"
|
||||||
|
+
|
||||||
|
+#include <kis_types.h>
|
||||||
|
+
|
||||||
|
+#include "KisView.h"
|
||||||
|
+#include "kis_types.h"
|
||||||
|
+
|
||||||
|
+#include "kis_canvas_resource_provider.h"
|
||||||
|
+#include "kis_paintop_preset.h"
|
||||||
|
+
|
||||||
|
+#include "KisViewManager.h"
|
||||||
|
+#include "KisGlobalResourcesInterface.h"
|
||||||
|
+
|
||||||
|
+#include <KoResourcePaths.h>
|
||||||
|
+
|
||||||
|
+#include "Document.h"
|
||||||
|
+
|
||||||
|
+#include <KisPart.h>
|
||||||
|
+#include <KisMainWindow.h>
|
||||||
|
+
|
||||||
|
+#include <kis_types.h>
|
||||||
|
+#include <kis_annotation.h>
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#include "kis_animation_importer.h"
|
||||||
|
+#include <kis_canvas2.h>
|
||||||
|
+#include <KoUpdater.h>
|
||||||
|
+#include <QMessageBox>
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#include "strokes/KisFreehandStrokeInfo.h"
|
||||||
|
+#include "kis_resources_snapshot.h"
|
||||||
|
+#include "kis_canvas_resource_provider.h"
|
||||||
|
+#include "strokes/freehand_stroke.h"
|
||||||
|
+#include "kis_painting_information_builder.h"
|
||||||
|
+#include "KisAsynchronousStrokeUpdateHelper.h"
|
||||||
|
+#include "kis_stroke_strategy.h"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+KisFigurePaintingToolHelper PaintingResources::createHelper(KisImageWSP image)
|
||||||
|
+{
|
||||||
|
+ // need to grab the resource provider
|
||||||
|
+ KisView *activeView = KisPart::instance()->currentMainwindow()->activeView();
|
||||||
|
+ KoCanvasResourceProvider *resourceManager = activeView->viewManager()->canvasResourceProvider()->resourceManager();
|
||||||
|
+
|
||||||
|
+ // grab the image and current layer
|
||||||
|
+ KisNodeSP node = activeView->currentNode();
|
||||||
|
+
|
||||||
|
+ const KUndo2MagicString name = kundo2_noi18n("python_stroke");
|
||||||
|
+ KisFigurePaintingToolHelper helper(
|
||||||
|
+ name,
|
||||||
|
+ image,
|
||||||
|
+ node, resourceManager,
|
||||||
|
+ KisToolShapeUtils::StrokeStyle::StrokeStyleForeground,
|
||||||
|
+ KisToolShapeUtils::FillStyle::FillStyleNone
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ return helper;
|
||||||
|
+}
|
||||||
|
diff --git a/libs/libkis/PaintingResources.h b/libs/libkis/PaintingResources.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..19bb0d4
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libs/libkis/PaintingResources.h
|
||||||
|
@@ -0,0 +1,46 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2020 Scott Petrovic <scottpetrovic@gmail.com>
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
+ * the Free Software Foundation; either version 2 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU Lesser General Public License
|
||||||
|
+ * along with this program; if not, write to the Free Software
|
||||||
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
+ */
|
||||||
|
+#ifndef LIBKIS_PAINTINGRESOURCES_H
|
||||||
|
+#define LIBKIS_PAINTINGRESOURCES_H
|
||||||
|
+
|
||||||
|
+#include <QObject>
|
||||||
|
+#include <QColor>
|
||||||
|
+#include <kis_types.h>
|
||||||
|
+
|
||||||
|
+#include "kritalibkis_export.h"
|
||||||
|
+#include "KoCanvasResourceProvider.h"
|
||||||
|
+#include "kis_stroke_strategy.h"
|
||||||
|
+
|
||||||
|
+#include <kis_figure_painting_tool_helper.h>
|
||||||
|
+
|
||||||
|
+#include "libkis.h"
|
||||||
|
+
|
||||||
|
+#include "View.h"
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief The PaintingResources namespace
|
||||||
|
+ * Sets up information related to making painting strokes.
|
||||||
|
+ * Used primarily in the Document class
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+namespace PaintingResources
|
||||||
|
+{
|
||||||
|
+ KisFigurePaintingToolHelper createHelper(KisImageWSP image);
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#endif // LIBKIS_PAINTINGRESOURCES_H
|
||||||
|
diff --git a/libs/ui/tool/kis_resources_snapshot.cpp b/libs/ui/tool/kis_resources_snapshot.cpp
|
||||||
|
index dca6ba5..0c031e0 100644
|
||||||
|
--- a/libs/ui/tool/kis_resources_snapshot.cpp
|
||||||
|
+++ b/libs/ui/tool/kis_resources_snapshot.cpp
|
||||||
|
@@ -75,8 +75,11 @@ KisResourcesSnapshot::KisResourcesSnapshot(KisImageSP image, KisNodeSP currentNo
|
||||||
|
m_d->currentBgColor = resourceManager->resource(KoCanvasResource::BackgroundColor).value<KoColor>();
|
||||||
|
m_d->currentPattern = resourceManager->resource(KoCanvasResource::CurrentPattern).value<KoPatternSP>();
|
||||||
|
if (resourceManager->resource(KoCanvasResource::CurrentGradient).value<KoAbstractGradientSP>()) {
|
||||||
|
- m_d->currentGradient = resourceManager->resource(KoCanvasResource::CurrentGradient).value<KoAbstractGradientSP>()
|
||||||
|
- ->cloneAndBakeVariableColors(m_d->globalCanvasResourcesInterface);
|
||||||
|
+ m_d->currentGradient = resourceManager->resource(KoCanvasResource::CurrentGradient).value<KoAbstractGradientSP>();
|
||||||
|
+ if(m_d->currentGradient) {
|
||||||
|
+ m_d->currentGradient = resourceManager->resource(KoCanvasResource::CurrentGradient).value<KoAbstractGradientSP>()
|
||||||
|
+ ->cloneAndBakeVariableColors(m_d->globalCanvasResourcesInterface);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
diff --git a/plugins/extensions/pykrita/sip/krita/Node.sip b/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
index 3066bfb..cbcef0f 100644
|
||||||
|
--- a/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
+++ b/plugins/extensions/pykrita/sip/krita/Node.sip
|
||||||
|
@@ -69,6 +69,12 @@ public Q_SLOTS:
|
||||||
|
void setLayerStyleFromAsl(const QString &asl);
|
||||||
|
int index() const;
|
||||||
|
QUuid uniqueId() const;
|
||||||
|
+
|
||||||
|
+ void paintLine(const QPoint pointOne, const QPoint pointTwo);
|
||||||
|
+ void paintRectangle(const QRectF &rect);
|
||||||
|
+ void paintPolygon(const QList<QPointF> points);
|
||||||
|
+ void paintEllipse(const QRectF &rect);
|
||||||
|
+ void paintPath(const QPainterPath &path);
|
||||||
|
Q_SIGNALS:
|
||||||
|
private:
|
||||||
|
};
|
26
pkgs/sway/0001-mobile-reverse-layer-order.patch
Normal file
26
pkgs/sway/0001-mobile-reverse-layer-order.patch
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
From 7fead3cd2158fe913775ede5651291cf5f4ccf4d Mon Sep 17 00:00:00 2001
|
||||||
|
From: chayleaf <chayleaf-git@pavluk.org>
|
||||||
|
Date: Wed, 14 Aug 2024 07:32:11 +0700
|
||||||
|
Subject: [PATCH 1/2] mobile: reverse layer order
|
||||||
|
|
||||||
|
This makes exclusive anchored layers that were added first be first
|
||||||
|
---
|
||||||
|
sway/desktop/layer_shell.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c
|
||||||
|
index 8c6cedfe..41a638ee 100644
|
||||||
|
--- a/sway/desktop/layer_shell.c
|
||||||
|
+++ b/sway/desktop/layer_shell.c
|
||||||
|
@@ -129,7 +129,7 @@ static void arrange_layer(struct sway_output *output, struct wl_list *list,
|
||||||
|
struct wlr_box full_area = { 0 };
|
||||||
|
wlr_output_effective_resolution(output->wlr_output,
|
||||||
|
&full_area.width, &full_area.height);
|
||||||
|
- wl_list_for_each(sway_layer, list, link) {
|
||||||
|
+ wl_list_for_each_reverse(sway_layer, list, link) {
|
||||||
|
struct wlr_layer_surface_v1 *layer = sway_layer->layer_surface;
|
||||||
|
struct wlr_layer_surface_v1_state *state = &layer->current;
|
||||||
|
if (exclusive != (state->exclusive_zone > 0)) {
|
||||||
|
--
|
||||||
|
2.44.1
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
From 466d750b96184b793d276d9d0e30d37af4477fea Mon Sep 17 00:00:00 2001
|
||||||
|
From: chayleaf <chayleaf-git@pavluk.org>
|
||||||
|
Date: Wed, 14 Aug 2024 08:17:44 +0700
|
||||||
|
Subject: [PATCH 2/2] mobile: don't idle_notify for volume keys
|
||||||
|
|
||||||
|
---
|
||||||
|
sway/input/keyboard.c | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
|
||||||
|
index 8927287f..d42f62b0 100644
|
||||||
|
--- a/sway/input/keyboard.c
|
||||||
|
+++ b/sway/input/keyboard.c
|
||||||
|
@@ -404,7 +404,9 @@ static void handle_key_event(struct sway_keyboard *keyboard,
|
||||||
|
keyboard->seat_device->input_device->wlr_device;
|
||||||
|
char *device_identifier = input_device_get_identifier(wlr_device);
|
||||||
|
bool exact_identifier = keyboard->wlr->group != NULL;
|
||||||
|
- seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD);
|
||||||
|
+ if (event->keycode != XKB_KEY_XF86AudioLowerVolume && event->keycode != XKB_KEY_XF86AudioRaiseVolume) {
|
||||||
|
+ seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD);
|
||||||
|
+ }
|
||||||
|
bool input_inhibited = seat->exclusive_client != NULL ||
|
||||||
|
server.session_lock.locked;
|
||||||
|
struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor =
|
||||||
|
--
|
||||||
|
2.44.1
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{ config
|
{ config
|
||||||
|
, lib
|
||||||
, pkgs
|
, pkgs
|
||||||
, router-config
|
, router-config
|
||||||
, hardware
|
, hardware
|
||||||
|
@ -126,14 +127,16 @@ in
|
||||||
options = [ "defaults" "size=2G" "mode=755" ]; };
|
options = [ "defaults" "size=2G" "mode=755" ]; };
|
||||||
"/persist" =
|
"/persist" =
|
||||||
{ device = "UUID=${uuids.bch}"; fsType = "bcachefs"; inherit neededForBoot;
|
{ device = "UUID=${uuids.bch}"; fsType = "bcachefs"; inherit neededForBoot;
|
||||||
# TODO: https://github.com/systemd/systemd/pull/33720/files
|
# TODO: remove the if when systemd >= 257
|
||||||
options = [
|
options = let
|
||||||
|
dep = if lib.versionAtLeast config.boot.initrd.systemd.package.version "257" then "wants" else "requires";
|
||||||
|
in [
|
||||||
"degraded"
|
"degraded"
|
||||||
"errors=ro"
|
"errors=ro"
|
||||||
"x-systemd.device-timeout=0"
|
"x-systemd.device-timeout=0"
|
||||||
"x-systemd.requires=dev-mapper-bch0.device"
|
"x-systemd.${dep}=dev-mapper-bch0.device"
|
||||||
"x-systemd.requires=dev-mapper-bch1.device"
|
"x-systemd.${dep}=dev-mapper-bch1.device"
|
||||||
"x-systemd.requires=dev-mapper-bch2.device"
|
"x-systemd.${dep}=dev-mapper-bch2.device"
|
||||||
]; };
|
]; };
|
||||||
"/boot" = { device = parts.boot; fsType = "vfat"; inherit neededForBoot; };
|
"/boot" = { device = parts.boot; fsType = "vfat"; inherit neededForBoot; };
|
||||||
};
|
};
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
"steam-original"
|
"steam-original"
|
||||||
];
|
];
|
||||||
hardware = {
|
hardware = {
|
||||||
|
opentabletdriver.enable = true;
|
||||||
steam-hardware.enable = true;
|
steam-hardware.enable = true;
|
||||||
opengl.driSupport32Bit = true;
|
opengl.driSupport32Bit = true;
|
||||||
# needed for sway WLR_RENDERER=vulkan
|
# needed for sway WLR_RENDERER=vulkan
|
||||||
|
|
20
system/hosts/router/a.py
Normal file
20
system/hosts/router/a.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import pytricia # type: ignore
|
||||||
|
|
||||||
|
def build_ipset(ips: list[str]) -> pytricia.PyTricia:
|
||||||
|
pyt = pytricia.PyTricia()
|
||||||
|
for ip in ips:
|
||||||
|
try:
|
||||||
|
pyt.insert(ip, None)
|
||||||
|
except:
|
||||||
|
with open("/var/lib/unbound/error.log", "at") as f:
|
||||||
|
f.write(f"Warning: couldn't insert ip {ip}:\n")
|
||||||
|
traceback.print_exc(file=f)
|
||||||
|
return pyt
|
||||||
|
|
||||||
|
s = build_ipset(["10.0.0.0/24"])
|
|
@ -178,12 +178,8 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
import gi
|
import gi
|
||||||
import ipaddress
|
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
|
||||||
import pydbus
|
import pydbus
|
||||||
import pytricia # type: ignore
|
|
||||||
import re
|
import re
|
||||||
import array
|
import array
|
||||||
import threading
|
import threading
|
||||||
|
@ -205,22 +201,6 @@ from typing import TypedDict, Optional, Any
|
||||||
IF_UNSPEC = -1
|
IF_UNSPEC = -1
|
||||||
PROTO_UNSPEC = -1
|
PROTO_UNSPEC = -1
|
||||||
|
|
||||||
|
|
||||||
Domains = dict[str, "Domains | bool"]
|
|
||||||
|
|
||||||
|
|
||||||
class NftQuery(TypedDict):
|
|
||||||
domains: Domains
|
|
||||||
ips4: pytricia.PyTricia
|
|
||||||
ips6: pytricia.PyTricia
|
|
||||||
name4: str
|
|
||||||
name6: str
|
|
||||||
dynamic: bool
|
|
||||||
|
|
||||||
|
|
||||||
NFT_QUERIES: dict[str, NftQuery] = {}
|
|
||||||
# dynamic query update token
|
|
||||||
NFT_TOKEN: str = ""
|
|
||||||
DOMAIN_NAME_OVERRIDES: dict[str, str] = {}
|
DOMAIN_NAME_OVERRIDES: dict[str, str] = {}
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
MDNS_TTL: int
|
MDNS_TTL: int
|
||||||
|
@ -239,22 +219,6 @@ dbus_thread: threading.Thread
|
||||||
dbus_loop: Any
|
dbus_loop: Any
|
||||||
|
|
||||||
|
|
||||||
def is_valid_ip4(x: str) -> bool:
|
|
||||||
try:
|
|
||||||
_ = ipaddress.IPv4Address(x)
|
|
||||||
return True
|
|
||||||
except ipaddress.AddressValueError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def is_valid_ip6(x: str) -> bool:
|
|
||||||
try:
|
|
||||||
_ = ipaddress.IPv6Address(x)
|
|
||||||
return True
|
|
||||||
except ipaddress.AddressValueError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def str2bool(v: str) -> bool:
|
def str2bool(v: str) -> bool:
|
||||||
if v.lower() in ["false", "no", "0", "off", ""]:
|
if v.lower() in ["false", "no", "0", "off", ""]:
|
||||||
return False
|
return False
|
||||||
|
@ -500,150 +464,11 @@ def parse_type_list(lst: str) -> list[RdataType]:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def build_ipset(ips: list[str]) -> pytricia.PyTricia:
|
|
||||||
pyt = pytricia.PyTricia()
|
|
||||||
for ip in ips:
|
|
||||||
try:
|
|
||||||
pyt.insert(ip, None)
|
|
||||||
except:
|
|
||||||
with open("/var/lib/unbound/error.log", "at") as f:
|
|
||||||
f.write(f"Warning: couldn't insert ip {ip}:\n")
|
|
||||||
traceback.print_exc(file=f)
|
|
||||||
return pyt
|
|
||||||
|
|
||||||
|
|
||||||
def add_ips(set: str, ipv6: bool, ips: list[str], flush: bool = False):
|
|
||||||
# with open('/var/lib/unbound/info.log', 'at') as f:
|
|
||||||
# print('set', set, 'ipv6', ipv6, 'ips', ips, file=f)
|
|
||||||
pyt = build_ipset(ips)
|
|
||||||
ruleset: list[dict] = []
|
|
||||||
if flush:
|
|
||||||
ruleset.append(
|
|
||||||
{"flush": {"set": {"family": "inet", "table": "global", "name": set}}}
|
|
||||||
)
|
|
||||||
elems: list[str | dict] = []
|
|
||||||
if ipv6:
|
|
||||||
maxn = 128
|
|
||||||
is_valid: Callable[[str], bool] = is_valid_ip6
|
|
||||||
else:
|
|
||||||
maxn = 32
|
|
||||||
is_valid = is_valid_ip4
|
|
||||||
for ip in pyt.keys():
|
|
||||||
try:
|
|
||||||
if pyt.parent(ip) != None:
|
|
||||||
continue
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if "/" not in ip:
|
|
||||||
n: int = maxn
|
|
||||||
else:
|
|
||||||
ip, n0 = ip.split("/")
|
|
||||||
try:
|
|
||||||
n = int(n0)
|
|
||||||
except:
|
|
||||||
continue
|
|
||||||
if not is_valid(ip):
|
|
||||||
continue
|
|
||||||
if n == maxn:
|
|
||||||
elems.append(ip)
|
|
||||||
else:
|
|
||||||
elems.append({"prefix": {"addr": ip, "len": n}})
|
|
||||||
# with open('/var/lib/unbound/info.log', 'at') as f:
|
|
||||||
# print('elems', elems, file=f)
|
|
||||||
if len(elems) == 0:
|
|
||||||
return
|
|
||||||
ruleset.append(
|
|
||||||
{
|
|
||||||
"add": {
|
|
||||||
"element": {
|
|
||||||
"family": "inet",
|
|
||||||
"table": "global",
|
|
||||||
"name": set,
|
|
||||||
"elem": elems,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
data: bytes = json.dumps({"nftables": ruleset}).encode("utf-8")
|
|
||||||
# with open('/var/lib/unbound/info.log', 'at') as f:
|
|
||||||
# print('data', data, file=f)
|
|
||||||
try:
|
|
||||||
out = subprocess.run(
|
|
||||||
["/run/current-system/sw/bin/nft", "-j", "-f", "/dev/stdin"],
|
|
||||||
capture_output=True,
|
|
||||||
input=data,
|
|
||||||
)
|
|
||||||
# with open('/var/lib/unbound/info.log', 'at') as f:
|
|
||||||
# print('out', out, file=f)
|
|
||||||
if out.returncode != 0:
|
|
||||||
with open("/var/lib/unbound/nftables.log", "wb") as f:
|
|
||||||
f.write(b"Error running nftables ruleset. Ruleset:\n")
|
|
||||||
f.write(data)
|
|
||||||
f.write(b"\n")
|
|
||||||
f.write(b"stdout:\n")
|
|
||||||
f.write(out.stdout)
|
|
||||||
f.write(b"\nstderr:\n")
|
|
||||||
f.write(out.stderr)
|
|
||||||
f.write(b"\n")
|
|
||||||
except:
|
|
||||||
with open("/var/lib/unbound/error.log", "at") as f:
|
|
||||||
f.write(f"While adding ips for set {set}:\n")
|
|
||||||
traceback.print_exc(file=f)
|
|
||||||
|
|
||||||
|
|
||||||
def add_split_domain(domains: Domains, split_domain: list[str]):
|
|
||||||
if not split_domain:
|
|
||||||
return
|
|
||||||
split_domain = split_domain[:]
|
|
||||||
if split_domain and split_domain[-1] == '*':
|
|
||||||
split_domain.pop()
|
|
||||||
if not split_domain:
|
|
||||||
return
|
|
||||||
while len(split_domain) > 1:
|
|
||||||
key = split_domain[-1]
|
|
||||||
if key in domains.keys():
|
|
||||||
domains1 = domains[key]
|
|
||||||
if isinstance(domains1, bool):
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
domains1 = {}
|
|
||||||
domains[key] = domains1
|
|
||||||
domains = domains1
|
|
||||||
split_domain.pop()
|
|
||||||
domains[split_domain[-1]] = True
|
|
||||||
|
|
||||||
|
|
||||||
def build_domains(domains: list[str]) -> Domains:
|
|
||||||
ret: Domains = {}
|
|
||||||
for domain in domains:
|
|
||||||
add_split_domain(ret, domain.split("."))
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def lookup_domain(domains: Domains, domain: str) -> bool:
|
|
||||||
split_domain: list[str] = domain.split(".")
|
|
||||||
while len(split_domain):
|
|
||||||
key: str = split_domain[-1]
|
|
||||||
split_domain = split_domain[:-1]
|
|
||||||
domains1 = domains.get(key, False)
|
|
||||||
if isinstance(domains1, bool):
|
|
||||||
return domains1
|
|
||||||
domains = domains1
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class DpiInfo(TypedDict):
|
|
||||||
domains: list[str]
|
|
||||||
name: str
|
|
||||||
restriction: dict
|
|
||||||
|
|
||||||
|
|
||||||
def init(*args: Any, **kwargs: Any):
|
def init(*args: Any, **kwargs: Any):
|
||||||
global dbus_thread, DEBUG
|
global dbus_thread, DEBUG
|
||||||
global MDNS_TTL, MDNS_GETONE, MDNS_TIMEOUT
|
global MDNS_TTL, MDNS_GETONE, MDNS_TIMEOUT
|
||||||
global MDNS_REJECT_TYPES, MDNS_ACCEPT_TYPES
|
global MDNS_REJECT_TYPES, MDNS_ACCEPT_TYPES
|
||||||
global MDNS_REJECT_NAMES, MDNS_ACCEPT_NAMES
|
global MDNS_REJECT_NAMES, MDNS_ACCEPT_NAMES
|
||||||
global NFT_QUERIES, NFT_TOKEN, DOMAIN_NAME_OVERRIDES
|
|
||||||
|
|
||||||
domain_name_overrides: str = os.environ.get("DOMAIN_NAME_OVERRIDES", "")
|
domain_name_overrides: str = os.environ.get("DOMAIN_NAME_OVERRIDES", "")
|
||||||
if domain_name_overrides:
|
if domain_name_overrides:
|
||||||
|
@ -652,92 +477,6 @@ def init(*args: Any, **kwargs: Any):
|
||||||
DOMAIN_NAME_OVERRIDES[k1] = v1
|
DOMAIN_NAME_OVERRIDES[k1] = v1
|
||||||
DOMAIN_NAME_OVERRIDES[k1 + "."] = v1 + "."
|
DOMAIN_NAME_OVERRIDES[k1 + "."] = v1 + "."
|
||||||
|
|
||||||
NFT_TOKEN = os.environ.get("NFT_TOKEN", "")
|
|
||||||
nft_queries: str = os.environ.get("NFT_QUERIES", "")
|
|
||||||
if nft_queries:
|
|
||||||
for query in nft_queries.split(";"):
|
|
||||||
name, sets = query.split(":")
|
|
||||||
dynamic = False
|
|
||||||
if name.endswith("!"):
|
|
||||||
name = name.rstrip("!")
|
|
||||||
dynamic = True
|
|
||||||
set4, set6 = sets.split(",")
|
|
||||||
NFT_QUERIES[name] = {
|
|
||||||
"domains": {},
|
|
||||||
"ips4": [],
|
|
||||||
"ips6": [],
|
|
||||||
"name4": set4,
|
|
||||||
"name6": set6,
|
|
||||||
"dynamic": dynamic,
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v in NFT_QUERIES.items():
|
|
||||||
all_domains: list[str] = []
|
|
||||||
for base in ["/etc/unbound", "/var/lib/unbound"]:
|
|
||||||
try:
|
|
||||||
with open(f"{base}/{k}_domains.json", "rt", encoding="utf-8") as f:
|
|
||||||
domains: list[str] = json.load(f)
|
|
||||||
all_domains.extend(domains)
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
except:
|
|
||||||
with open("/var/lib/unbound/error.log", "at") as f:
|
|
||||||
traceback.print_exc(file=f)
|
|
||||||
try:
|
|
||||||
with open(f"{base}/{k}_dpi.json", "rt", encoding="utf-8") as f:
|
|
||||||
dpi: list[DpiInfo] = json.load(f)
|
|
||||||
for dpi_info in dpi:
|
|
||||||
all_domains.extend(dpi_info["domains"])
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
except:
|
|
||||||
with open("/var/lib/unbound/error.log", "at") as f:
|
|
||||||
traceback.print_exc(file=f)
|
|
||||||
try:
|
|
||||||
with open(f"{base}/{k}_ips.json", "rt", encoding="utf-8") as f:
|
|
||||||
ips: list[str] = json.load(f)
|
|
||||||
v["ips4"].extend(filter(lambda x: "." in x, ips))
|
|
||||||
v["ips6"].extend(filter(lambda x: ":" in x, ips))
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
except:
|
|
||||||
with open("/var/lib/unbound/error.log", "at") as f:
|
|
||||||
traceback.print_exc(file=f)
|
|
||||||
v["domains"] = build_domains(all_domains)
|
|
||||||
|
|
||||||
# cached resolved domains
|
|
||||||
try:
|
|
||||||
os.makedirs("/var/lib/unbound/domains4/", exist_ok=True)
|
|
||||||
for x in os.listdir("/var/lib/unbound/domains4/"):
|
|
||||||
with open(f"/var/lib/unbound/domains4/{x}", "rt") as f:
|
|
||||||
data = f.read().split("\n")
|
|
||||||
for k, v in NFT_QUERIES.items():
|
|
||||||
if lookup_domain(v["domains"], x):
|
|
||||||
v["ips4"].extend(data)
|
|
||||||
except:
|
|
||||||
with open("/var/lib/unbound/error.log", "at") as f:
|
|
||||||
traceback.print_exc(file=f)
|
|
||||||
try:
|
|
||||||
os.makedirs("/var/lib/unbound/domains6/", exist_ok=True)
|
|
||||||
for x in os.listdir("/var/lib/unbound/domains6/"):
|
|
||||||
with open(f"/var/lib/unbound/domains6/{x}", "rt") as f:
|
|
||||||
data = f.read().split("\n")
|
|
||||||
for k, v in NFT_QUERIES.items():
|
|
||||||
if lookup_domain(v["domains"], x):
|
|
||||||
v["ips6"].extend(data)
|
|
||||||
except:
|
|
||||||
with open("/var/lib/unbound/error.log", "at") as f:
|
|
||||||
traceback.print_exc(file=f)
|
|
||||||
|
|
||||||
# finally, add the ips to nftables
|
|
||||||
for k, v in NFT_QUERIES.items():
|
|
||||||
if v["ips4"] and v["name4"]:
|
|
||||||
add_ips(v["name4"], False, v["ips4"], flush=True)
|
|
||||||
if v["ips6"] and v["name6"]:
|
|
||||||
add_ips(v["name6"], True, v["ips6"], flush=True)
|
|
||||||
v["ips4"] = build_ipset(v["ips4"])
|
|
||||||
v["ips6"] = build_ipset(v["ips6"])
|
|
||||||
|
|
||||||
DEBUG = str2bool(os.environ.get("DEBUG", str(False)))
|
DEBUG = str2bool(os.environ.get("DEBUG", str(False)))
|
||||||
|
|
||||||
MDNS_TTL = int(os.environ.get("MDNS_TTL", 120))
|
MDNS_TTL = int(os.environ.get("MDNS_TTL", 120))
|
||||||
|
@ -751,20 +490,20 @@ def init(*args: Any, **kwargs: Any):
|
||||||
if MDNS_ACCEPT_TYPES:
|
if MDNS_ACCEPT_TYPES:
|
||||||
dbg(f"ONLY resolving the following types via Avahi: {MDNS_ACCEPT_TYPES}")
|
dbg(f"ONLY resolving the following types via Avahi: {MDNS_ACCEPT_TYPES}")
|
||||||
|
|
||||||
v2 = os.environ.get("MDNS_REJECT_NAMES", None)
|
v = os.environ.get("MDNS_REJECT_NAMES", None)
|
||||||
MDNS_REJECT_NAMES = re.compile(v2, flags=re.I | re.S) if v2 is not None else None
|
MDNS_REJECT_NAMES = re.compile(v, flags=re.I | re.S) if v is not None else None
|
||||||
if MDNS_REJECT_NAMES is not None:
|
if MDNS_REJECT_NAMES is not None:
|
||||||
dbg(f"Names NOT resolved via Avahi: {MDNS_REJECT_NAMES.pattern}")
|
dbg(f"Names NOT resolved via Avahi: {MDNS_REJECT_NAMES.pattern}")
|
||||||
|
|
||||||
v2 = os.environ.get("MDNS_ACCEPT_NAMES", None)
|
v = os.environ.get("MDNS_ACCEPT_NAMES", None)
|
||||||
MDNS_ACCEPT_NAMES = re.compile(v2, flags=re.I | re.S) if v2 is not None else None
|
MDNS_ACCEPT_NAMES = re.compile(v, flags=re.I | re.S) if v is not None else None
|
||||||
if MDNS_ACCEPT_NAMES is not None:
|
if MDNS_ACCEPT_NAMES is not None:
|
||||||
dbg(
|
dbg(
|
||||||
f"ONLY resolving the following names via Avahi: {MDNS_ACCEPT_NAMES.pattern}"
|
f"ONLY resolving the following names via Avahi: {MDNS_ACCEPT_NAMES.pattern}"
|
||||||
)
|
)
|
||||||
|
|
||||||
v2 = os.environ.get("MDNS_TIMEOUT", None)
|
v = os.environ.get("MDNS_TIMEOUT", None)
|
||||||
MDNS_TIMEOUT = int(v2) if v2 is not None else None
|
MDNS_TIMEOUT = int(v) if v is not None else None
|
||||||
if MDNS_TIMEOUT is not None:
|
if MDNS_TIMEOUT is not None:
|
||||||
dbg(f"Avahi request timeout: {MDNS_TIMEOUT}")
|
dbg(f"Avahi request timeout: {MDNS_TIMEOUT}")
|
||||||
|
|
||||||
|
@ -824,139 +563,6 @@ def operate(id, event, qstate, qdata) -> bool:
|
||||||
|
|
||||||
n2: str = name.rstrip(".")
|
n2: str = name.rstrip(".")
|
||||||
|
|
||||||
if NFT_TOKEN and n2.endswith(f"{NFT_TOKEN}"):
|
|
||||||
if n2.endswith(f".{NFT_TOKEN}"):
|
|
||||||
n3 = n2.removesuffix(f".{NFT_TOKEN}")
|
|
||||||
for k, v in NFT_QUERIES.items():
|
|
||||||
if v["dynamic"] and n3.endswith(f".{k}"):
|
|
||||||
n4 = n3.removesuffix(f".{k}")
|
|
||||||
qdomains = v["domains"]
|
|
||||||
if not lookup_domain(qdomains, n4):
|
|
||||||
add_split_domain(qdomains, n4.split("."))
|
|
||||||
old = []
|
|
||||||
if os.path.exists(f"/var/lib/unbound/{k}_domains.json"):
|
|
||||||
with open(f"/var/lib/unbound/{k}_domains.json", "rt") as f:
|
|
||||||
old = json.load(f)
|
|
||||||
os.rename(
|
|
||||||
f"/var/lib/unbound/{k}_domains.json",
|
|
||||||
f"/var/lib/unbound/{k}_domains.json.bak",
|
|
||||||
)
|
|
||||||
old.append(n4)
|
|
||||||
with open(f"/var/lib/unbound/{k}_domains.json", "wt") as f:
|
|
||||||
json.dump(old, f)
|
|
||||||
elif n2.endswith(f".tmp{NFT_TOKEN}"):
|
|
||||||
n3 = n2.removesuffix(f".tmp{NFT_TOKEN}")
|
|
||||||
for k, v in NFT_QUERIES.items():
|
|
||||||
if v["dynamic"] and n3.endswith(f".{k}"):
|
|
||||||
n4 = n3.removesuffix(f".{k}")
|
|
||||||
qdomains = v["domains"]
|
|
||||||
if not lookup_domain(qdomains, n4):
|
|
||||||
add_split_domain(qdomains, n4.split("."))
|
|
||||||
return True
|
|
||||||
qnames: list[str] = []
|
|
||||||
for k, v in NFT_QUERIES.items():
|
|
||||||
if lookup_domain(v["domains"], n2):
|
|
||||||
qnames.append(k)
|
|
||||||
# THIS IS PAIN
|
|
||||||
if qnames:
|
|
||||||
try:
|
|
||||||
ip4: list[str] = []
|
|
||||||
ip6: list[str] = []
|
|
||||||
if qstate.return_msg and qstate.return_msg.rep:
|
|
||||||
rep = qstate.return_msg.rep
|
|
||||||
for i in range(rep.rrset_count):
|
|
||||||
d = rep.rrsets[i].entry.data
|
|
||||||
rk = rep.rrsets[i].rk
|
|
||||||
for j in range(0, d.count + d.rrsig_count):
|
|
||||||
wire = array.array("B", d.rr_data[j]).tobytes()
|
|
||||||
# IN
|
|
||||||
if rk.rrset_class != 256:
|
|
||||||
continue
|
|
||||||
# A, AAAA
|
|
||||||
if (
|
|
||||||
rk.type == 256
|
|
||||||
and len(wire) == 4 + 2
|
|
||||||
and wire[:2] == b"\x00\x04"
|
|
||||||
):
|
|
||||||
ip4.append(".".join(str(x) for x in wire[2:]))
|
|
||||||
elif (
|
|
||||||
rk.type == 7168
|
|
||||||
and len(wire) == 16 + 2
|
|
||||||
and wire[:2] == b"\x00\x10"
|
|
||||||
):
|
|
||||||
b = list(hex(x)[2:].zfill(2) for x in wire[2:])
|
|
||||||
ip6.append(
|
|
||||||
":".join(
|
|
||||||
"".join(b[x : x + 2]) for x in range(0, len(b), 2)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
changed4 = False
|
|
||||||
changed6 = False
|
|
||||||
if ip4:
|
|
||||||
new_data = "\n".join(sorted(ip4))
|
|
||||||
try:
|
|
||||||
with open("/var/lib/unbound/domains4/" + n2, "rt") as f:
|
|
||||||
old_data = f.read()
|
|
||||||
except:
|
|
||||||
old_data = ""
|
|
||||||
if old_data != new_data:
|
|
||||||
changed4 = True
|
|
||||||
with open("/var/lib/unbound/domains4/" + n2, "wt") as f:
|
|
||||||
f.write(new_data)
|
|
||||||
if ip6:
|
|
||||||
new_data = "\n".join(sorted(ip6))
|
|
||||||
try:
|
|
||||||
with open("/var/lib/unbound/domains6/" + n2, "rt") as f:
|
|
||||||
old_data = f.read()
|
|
||||||
except:
|
|
||||||
old_data = ""
|
|
||||||
if old_data != new_data:
|
|
||||||
changed6 = True
|
|
||||||
with open("/var/lib/unbound/domains6/" + n2, "wt") as f:
|
|
||||||
f.write(new_data)
|
|
||||||
if changed4:
|
|
||||||
for qname in qnames:
|
|
||||||
q = NFT_QUERIES[qname]
|
|
||||||
name4 = q["name4"]
|
|
||||||
ips4 = q["ips4"]
|
|
||||||
if name4:
|
|
||||||
ip2 = []
|
|
||||||
for ip in ip4:
|
|
||||||
exists = False
|
|
||||||
try:
|
|
||||||
if ips4.has_key(ip) or ips4.parent(ip) != None:
|
|
||||||
exists = True
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if not exists:
|
|
||||||
ips4.insert(ip, None)
|
|
||||||
ip2.append(ip)
|
|
||||||
if ip2:
|
|
||||||
add_ips(name4, False, ip2)
|
|
||||||
if changed6:
|
|
||||||
for qname in qnames:
|
|
||||||
q = NFT_QUERIES[qname]
|
|
||||||
name6 = q["name6"]
|
|
||||||
ips6 = q["ips6"]
|
|
||||||
if name6:
|
|
||||||
ip2 = []
|
|
||||||
for ip in ip6:
|
|
||||||
exists = False
|
|
||||||
try:
|
|
||||||
if ips6.has_key(ip) or ips6.parent(ip) != None:
|
|
||||||
exists = True
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if not exists:
|
|
||||||
ips6.insert(ip, None)
|
|
||||||
ip2.append(ip)
|
|
||||||
if ip2:
|
|
||||||
add_ips(name6, True, ip2)
|
|
||||||
except:
|
|
||||||
with open("/var/lib/unbound/error.log", "at") as f:
|
|
||||||
traceback.print_exc(file=f)
|
|
||||||
|
|
||||||
if event == MODULE_EVENT_NEW or event == MODULE_EVENT_PASS:
|
if event == MODULE_EVENT_NEW or event == MODULE_EVENT_PASS:
|
||||||
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
qstate.ext_state[id] = MODULE_WAIT_MODULE
|
||||||
return True
|
return True
|
||||||
|
@ -1031,13 +637,11 @@ def operate(id, event, qstate, qdata) -> bool:
|
||||||
if not m.set_return_msg(qstate):
|
if not m.set_return_msg(qstate):
|
||||||
raise Exception("Error in set_return_msg")
|
raise Exception("Error in set_return_msg")
|
||||||
|
|
||||||
# For some reason this breaks everything! Unbound responds with SERVFAIL instead of using the cache
|
|
||||||
# i.e. the first response is fine, but loading it from cache just doesn't work
|
|
||||||
# Resolution via Avahi works fast anyway so whatever
|
|
||||||
# if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0):
|
|
||||||
# raise Exception("Error in storeQueryInCache")
|
|
||||||
|
|
||||||
qstate.return_msg.rep.security = 2
|
qstate.return_msg.rep.security = 2
|
||||||
|
|
||||||
|
if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0):
|
||||||
|
raise Exception("Error in storeQueryInCache")
|
||||||
|
|
||||||
qstate.return_rcode = Rcode.NOERROR
|
qstate.return_rcode = Rcode.NOERROR
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
, lib
|
, lib
|
||||||
, router-lib
|
, router-lib
|
||||||
, server-config
|
, server-config
|
||||||
, ... }:
|
, ...
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.router-settings;
|
cfg = config.router-settings;
|
||||||
|
@ -473,8 +474,8 @@ in {
|
||||||
gateways = [ netAddresses.lan6 ];
|
gateways = [ netAddresses.lan6 ];
|
||||||
radvdSettings.AdvAutonomous = true;
|
radvdSettings.AdvAutonomous = true;
|
||||||
coreradSettings.autonomous = true;
|
coreradSettings.autonomous = true;
|
||||||
# don't allocate addresses for most devices
|
# # don't allocate addresses for most devices
|
||||||
keaSettings.pools = [ ];
|
# keaSettings.pools = [ ];
|
||||||
# just assign the reservations
|
# just assign the reservations
|
||||||
keaSettings.reservations = map (res:
|
keaSettings.reservations = map (res:
|
||||||
(if res.duid != null then { duid = res.duid; } else { hw-address = res.macAddress; }) // {
|
(if res.duid != null then { duid = res.duid; } else { hw-address = res.macAddress; }) // {
|
||||||
|
@ -597,20 +598,21 @@ in {
|
||||||
[(is.eq ip.saddr "@block4") (log "block4/s ") drop]
|
[(is.eq ip.saddr "@block4") (log "block4/s ") drop]
|
||||||
[(is.eq ip6.saddr "@block6") (log "block6/s ") drop]
|
[(is.eq ip6.saddr "@block6") (log "block6/s ") drop]
|
||||||
# default to no vpn...
|
# default to no vpn...
|
||||||
[(mangle meta.mark wan_table)]
|
# [(mangle meta.mark wan_table)]
|
||||||
# # default to vpn...
|
# default to vpn...
|
||||||
# [(mangle meta.mark vpn_table)]
|
[(mangle meta.mark vpn_table)]
|
||||||
|
[(is.eq meta.mark 0)]
|
||||||
|
# ...but unvpn traffic to/from force_unvpn4/force_unvpn6
|
||||||
|
[(is.eq ip.daddr "@force_unvpn4") (mangle meta.mark wan_table)]
|
||||||
|
[(is.eq ip6.daddr "@force_unvpn6") (mangle meta.mark wan_table)]
|
||||||
|
[(is.eq ip.saddr "@force_unvpn4") (mangle meta.mark wan_table)]
|
||||||
|
[(is.eq ip6.saddr "@force_unvpn6") (mangle meta.mark wan_table)]
|
||||||
# ...force vpn to/from force_vpn4/force_vpn6
|
# ...force vpn to/from force_vpn4/force_vpn6
|
||||||
# (disable this if it breaks some sites)
|
# (disable this if it breaks some sites)
|
||||||
[(is.eq ip.daddr "@force_vpn4") (mangle meta.mark vpn_table)]
|
[(is.eq ip.daddr "@force_vpn4") (mangle meta.mark vpn_table)]
|
||||||
[(is.eq ip6.daddr "@force_vpn6") (mangle meta.mark vpn_table)]
|
[(is.eq ip6.daddr "@force_vpn6") (mangle meta.mark vpn_table)]
|
||||||
[(is.eq ip.saddr "@force_vpn4") (mangle meta.mark vpn_table)]
|
[(is.eq ip.saddr "@force_vpn4") (mangle meta.mark vpn_table)]
|
||||||
[(is.eq ip6.saddr "@force_vpn6") (mangle meta.mark vpn_table)]
|
[(is.eq ip6.saddr "@force_vpn6") (mangle meta.mark vpn_table)]
|
||||||
# ...but unvpn traffic to/from force_unvpn4/force_unvpn6
|
|
||||||
[(is.eq ip.daddr "@force_unvpn4") (mangle meta.mark wan_table)]
|
|
||||||
[(is.eq ip6.daddr "@force_unvpn6") (mangle meta.mark wan_table)]
|
|
||||||
[(is.eq ip.saddr "@force_unvpn4") (mangle meta.mark wan_table)]
|
|
||||||
[(is.eq ip6.saddr "@force_unvpn6") (mangle meta.mark wan_table)]
|
|
||||||
# block requests to port 25 from hosts other than the server so they can't send mail pretending to originate from my domain
|
# block requests to port 25 from hosts other than the server so they can't send mail pretending to originate from my domain
|
||||||
# only do this for lans since traffic from other interfaces isn't forwarded to wan
|
# only do this for lans since traffic from other interfaces isn't forwarded to wan
|
||||||
[(is.eq meta.iifname lanSet) (is.ne ether.saddr cfg.serverMac) (is.eq meta.l4proto (f: f.tcp)) (is.eq tcp.dport 25) (log "smtp ") drop]
|
[(is.eq meta.iifname lanSet) (is.ne ether.saddr cfg.serverMac) (is.eq meta.l4proto (f: f.tcp)) (is.eq tcp.dport 25) (log "smtp ") drop]
|
||||||
|
@ -856,7 +858,7 @@ in {
|
||||||
access-control = [ "${netCidrs.netns4} allow" "${netCidrs.netns6} allow" "${netCidrs.lan4} allow" "${netCidrs.lan6} allow" ];
|
access-control = [ "${netCidrs.netns4} allow" "${netCidrs.netns6} allow" "${netCidrs.lan4} allow" "${netCidrs.lan6} allow" ];
|
||||||
aggressive-nsec = true;
|
aggressive-nsec = true;
|
||||||
do-ip6 = true;
|
do-ip6 = true;
|
||||||
module-config = ''"validator python iterator"'';
|
module-config = ''"validator dynlib python iterator"'';
|
||||||
local-zone = [
|
local-zone = [
|
||||||
# incompatible with avahi resolver
|
# incompatible with avahi resolver
|
||||||
# ''"local." static''
|
# ''"local." static''
|
||||||
|
@ -888,6 +890,7 @@ in {
|
||||||
# normally it would refer to the flake path, but then the service changes on every flake update
|
# normally it would refer to the flake path, but then the service changes on every flake update
|
||||||
# instead, write a new file in nix store
|
# instead, write a new file in nix store
|
||||||
python.python-script = builtins.toFile "avahi-resolver-v2.py" (builtins.readFile ./avahi-resolver-v2.py);
|
python.python-script = builtins.toFile "avahi-resolver-v2.py" (builtins.readFile ./avahi-resolver-v2.py);
|
||||||
|
dynlib.dynlib-file = "${pkgs.unbound-mod}/lib/libunbound_mod.so";
|
||||||
remote-control.control-enable = true;
|
remote-control.control-enable = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -907,7 +910,7 @@ in {
|
||||||
networking.hosts."${serverAddress6}" = hosted-domains;
|
networking.hosts."${serverAddress6}" = hosted-domains;
|
||||||
systemd.services.unbound = lib.mkIf config.services.unbound.enable {
|
systemd.services.unbound = lib.mkIf config.services.unbound.enable {
|
||||||
environment.PYTHONPATH = let
|
environment.PYTHONPATH = let
|
||||||
unbound-python = pkgs.python3.withPackages (ps: with ps; [ pydbus dnspython requests pytricia nftables ]);
|
unbound-python = pkgs.python3.withPackages (ps: with ps; [ pydbus dnspython ]);
|
||||||
in
|
in
|
||||||
"${unbound-python}/${unbound-python.sitePackages}";
|
"${unbound-python}/${unbound-python.sitePackages}";
|
||||||
# see https://github.com/NixOS/nixpkgs/pull/310514
|
# see https://github.com/NixOS/nixpkgs/pull/310514
|
||||||
|
|
|
@ -78,6 +78,8 @@ in {
|
||||||
{ directory = /var/lib/certspotter; user = "certspotter"; group = "certspotter"; mode = "0755"; }
|
{ directory = /var/lib/certspotter; user = "certspotter"; group = "certspotter"; mode = "0755"; }
|
||||||
] ++ lib.optionals (config.services.coop-fd.enable or false) [
|
] ++ lib.optionals (config.services.coop-fd.enable or false) [
|
||||||
{ directory = /var/lib/private/coop-fd; mode = "0750"; defaultPerms.mode = "0700"; }
|
{ directory = /var/lib/private/coop-fd; mode = "0750"; defaultPerms.mode = "0700"; }
|
||||||
|
] ++ lib.optionals config.virtualisation.docker.enable [
|
||||||
|
{ directory = /var/lib/docker; user = "root"; group = "root"; mode = "0710"; }
|
||||||
] ++ lib.optionals config.services.dovecot2.enable [
|
] ++ lib.optionals config.services.dovecot2.enable [
|
||||||
{ directory = /var/lib/dhparams; user = "root"; group = "root"; mode = "0755"; }
|
{ directory = /var/lib/dhparams; user = "root"; group = "root"; mode = "0755"; }
|
||||||
{ directory = /var/lib/dovecot; user = "root"; group = "root"; mode = "0755"; }
|
{ directory = /var/lib/dovecot; user = "root"; group = "root"; mode = "0755"; }
|
||||||
|
|
Loading…
Reference in a new issue