├── makefile ├── README.md ├── metadata.desktop └── contents ├── config └── main.xml ├── code └── kwin-desktop-pin.js └── ui └── config.ui /makefile: -------------------------------------------------------------------------------- 1 | install: 2 | plasmapkg2 --type kwinscript -i . 3 | mkdir -p ~/.local/share/kservices5 4 | ln -sf ~/.local/share/kwin/scripts/desktop-pin/metadata.desktop ~/.local/share/kservices5/kwin-script-desktop-pin.desktop 5 | 6 | uninstall: 7 | plasmapkg2 --type kwinscript -r desktop-pin 8 | rm ~/.local/share/kservices5/kwin-script-desktop-pin.desktop 9 | 10 | debug: 11 | QT_LOGGING_RULES="kwin_*.debug=true" kwin --replace && tail -f ~/.xsession-errors -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### desktop pin 2 | 3 | kwin script for making windows inside/outside a specified area pin to all desktops 4 | 5 | i pretty much just use this to make the desktops act like gnome, where only the primary monitor switches 6 | 7 | `make install`: install the plugin 8 | 9 | `make uninstall`: uninstall the plugin 10 | 11 | `make debug`: replace kwin with debug logging enabled and tail the log (you need to re-run kwin --replace from krunner after using this) -------------------------------------------------------------------------------- /metadata.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Desktop Pin 3 | Comment=Pin monitors inside/outside a defined area to all desktops 4 | Icon=preferences-system-windows-script-test 5 | 6 | X-Plasma-API=javascript 7 | X-Plasma-MainScript=code/kwin-desktop-pin.js 8 | 9 | X-KDE-PluginInfo-Name=desktop-pin 10 | X-KDE-PluginInfo-Version=0.0.1 11 | X-KDE-PluginInfo-Author=Leigh Oliver 12 | X-KDE-PluginInfo-Website=github.com/leigholiver/kwin-desktop-pin 13 | X-KDE-PluginInfo-Email=leigholiver@users.noreply.github.com 14 | X-KDE-PluginInfo-Depends= 15 | X-KDE-PluginInfo-License=GPL 16 | X-KDE-ServiceTypes=KWin/Script,KCModule 17 | 18 | X-KDE-Library=kwin/effects/configs/kcm_kwin4_genericscripted 19 | X-KDE-PluginKeyword=desktop-pin 20 | X-KDE-ParentComponents=desktop-pin 21 | 22 | Type=Service 23 | -------------------------------------------------------------------------------- /contents/config/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 0 11 | 12 | 13 | 14 | 0 15 | 16 | 17 | 18 | 1920 19 | 20 | 21 | 22 | 1080 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /contents/code/kwin-desktop-pin.js: -------------------------------------------------------------------------------- 1 | var excludes = readConfig("excludes", ""); 2 | var config = { 3 | // defines the area 4 | x: readConfig("x", 0), 5 | y: readConfig("y", 0), 6 | width: readConfig("width", 1920), 7 | height: readConfig("height", 1080), 8 | 9 | // if false, any windows outside the area will stick 10 | // if true, any windows inside the area will stick 11 | include: readConfig("pinmode", false), 12 | 13 | // list of clients to exclude 14 | excludes: [ 15 | "Desktop — Plasma", 16 | "Latte Shell — Latte Dock", 17 | "Latte Dock" 18 | ].concat((excludes == "" ? [] : ("" + excludes).split("\n"))) 19 | }; 20 | startDesktopPin(); 21 | 22 | function calcPins(client) { 23 | if (clientIsExcluded(client)) return 24 | 25 | var midPointX = client.geometry.x + (client.geometry.width / 2); 26 | var midPointY = client.geometry.y + (client.geometry.height/ 2); 27 | var isInArea = (midPointX >= config.x && midPointX <= config.x + config.width) && (midPointY >= config.y && midPointY <= config.y + config.height); 28 | client.onAllDesktops = (config.include == isInArea); 29 | print(client.caption + " in area?: " + isInArea + " setting on all desktops to: " + client.onAllDesktops); 30 | } 31 | 32 | function startDesktopPin() { 33 | var clients = workspace.clientList(); 34 | for (var i = clients.length; i > 0; i--) { 35 | onClientAdded(clients[i]); 36 | } 37 | workspace.clientAdded.connect(onClientAdded); 38 | workspace.clientRemoved.connect(onClientRemoved); 39 | } 40 | 41 | function onClientMoved(client) { 42 | if (typeof client === 'undefined') { 43 | return; 44 | } 45 | calcPins(client); 46 | } 47 | 48 | function onClientAdded(client) { 49 | if (typeof client === 'undefined') { 50 | return; 51 | } 52 | client.clientFinishUserMovedResized.connect(onClientMoved); 53 | calcPins(client); 54 | } 55 | 56 | function onClientRemoved(client) { 57 | if (typeof client === 'undefined') { 58 | return; 59 | } 60 | client.clientFinishUserMovedResized.disconnect(onClientMoved); 61 | } 62 | 63 | function clientIsExcluded(client) { 64 | for(var i=0; i 2 | 3 | KWin::DesktopPinConfigForm 4 | 5 | 6 | 7 | 0 8 | 0 9 | 263 10 | 285 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Area X Pos 25 | 26 | 27 | 28 | 29 | 30 | 31 | 0 32 | 33 | 34 | 0 35 | 36 | 37 | 9999 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Area Y Pos 49 | 50 | 51 | 52 | 53 | 54 | 55 | 0 56 | 57 | 58 | 0 59 | 60 | 61 | 9999 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | Area Width 73 | 74 | 75 | 76 | 77 | 78 | 79 | 1920 80 | 81 | 82 | 0 83 | 84 | 85 | 9999 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | Area Height 98 | 99 | 100 | 101 | 102 | 103 | 104 | 1080 105 | 106 | 107 | 0 108 | 109 | 110 | 9999 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | Pin Windows 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | Outside 130 | 131 | 132 | 133 | 134 | Inside 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | Window captions to exclude (each caption on a new line, regex supported) 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | --------------------------------------------------------------------------------