Curtains is a GUI application made for Windows to hide specific windows from screen sharing.
Since the pandemic video calls and screen sharing became much more frequent. I noticed that many struggled at least once with keeping private content out of their screen while sharing it. Be it a windows notification, a messenger app, an open browser, alt+tab preview, or simply forgetting to turn screensharing off while returning to usual buisness.
Curtains goal is to solve the problem, keep private screen content private and only share the processes that you want on screen.
There are a few other tools targeting this problem, like Invisiwind, which inspired me to do something similiar, add more functions and a simplistic GUI. To my suprise i found none with those features.
Either download the latest portable executable or download the repository, unpack it into a virtual environment and follow the instructions below.
requirements for source to run:
Python => 3.1
Windows can be hidden by using the Win32 API to change the WindowDisplayAffinity of a window to WDA_EXCLUDEFROMCAPTURE
or WDA_NONE
.
Since those API calls need to originate from the process that owns the windows, curtains uses sane dll-injection using pyinjector (a python wrapper for kubo/injector).
The code for the dll files is copied from Invisiwind.
To find the windows/parent processes and collect other informations about them the windows API is called via ctypes commands, psutil, pywin32 and win32gui (see curtains.py).
Thanks to flet the whole interface could be build in pure python while using Flutter. I am still working on it, codewise and designewise. both will probably change a lot until the first stable production release.
- hide/unhide all windows of a running process from any kind of screencapture (e.g. screensharing)
- new windows of hidden processes will be hidden too
- remembered proccesesses will be hidden/unhidden as soon as they show up, even after closing and restarting the app (lock symbol).
- see all processes with existing windows that belong to the current active user
- search processes by name
- preview a scaled down screenshot to check if windows are really hidden/visible
- interval between screenshots can be configured
- preview can be turned off
- single file executable is fully portable
- right now only all windows of a process can be hidden/unhidden.
- some processes e.g. the main explorer.exe (running taskbar, trays, wallpaper, etc.) have non visible, non clickable windows which will be visible when unhiding the processs windows. Workaround: Either don't hide those processes or keep them hidden until logout.
- some processes cannot be hidden because they are running with higher priviliges/other users. Solution: run Curtains with higher priviliges.
- hibernation might cause the GUI to be empty. Solution: Close and restart Curtains.
- BEWARE GAMERS: if you play computer games with third party anti-cheat software you should never hide any of the game windows. Some anti-cheat software take automatic screenshots and a missing or black screenshot could get your account banned. Use at your own risk.
pip install -r requirements.txt
cd curtains
Either manually download the dll_assets.zip in latest release and extract all .dll files to /curtains/assets/
or run the script to do it.
You can find the sourcecode in src_dll folder if you want to build the dynamic link libraries yourself
python3 ./download_dll.py
cd curtains
pyhon3 ./main.py
The script copies the pyinjector binar to the assets folder and patches pyinjector to check if running as a bundled executable to use the copies binary insides /assets/.
python3 ./pyinjector_patch_for_pyinstaller.py
flet pack -i curtains.ico --add-data "assets;assets" main.py
It is the way how executables frozen with pyinstaller work. Since the executable file is not compiled but a whole python runtime bundled with scripts and ressources together which will be unpacked at startup. This can take up to some few seconds. Of course a compiled executable would be much nicer, but sadly nuitka/cpython don't work well with GUI applications. It is not because python is slower than compiled languages. There is no heavy lifting happening in Curtains.
- I love python!
- i am a beginner still learning other languages and frameworks.
- i lack time lately and python development is kinda fast
- it does the job.
- after playing around with a douzend different GUI frameworks, flet finally looks and feels like what i was looking for. I had to build something with it.
Yes! but it will only work on processes owned by your user, that are running without admin rights.
Curtains is safe software. DLL-Injection is the process of attaching external code to a running process. It is like telling a process to do something it was not intended to do. So it depends on what you tell the process to do. Despite this i cannot rule out AV software flagging Curtains as potentially dangerous because pyinstaller and pyinjector are both known for some false positives.
In case of Curtains, all the injected process do is call the Win32 API with SetDisplayAffinity and changes the value for given windows to WDA_EXCLUDEFROMCAPTURE
or the other way around to WDA_NONE
. The dll files to do this are open-source, can be checked or build by anyone. Curtains will only be able to do this if it has the needed priviliges aka. it will only work on windows run by the user that runs curtains.
- hotkey to un-/hide the active window
- option to run as trayicon
- option to run at startup
- edit window titles / aka custom titles
- windows notifications to alert when new unhidden window appears + prompt option
- upload as pypi package
- dynamic window size (in hope for flet update to call parent/children soon)
- implementing a method to verify and validate the dll files befor injection for safety reasons