aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--LICENSE24
-rw-r--r--README.md50
-rw-r--r--docs/xkcd1172.136
-rw-r--r--pyproject.toml6
-rw-r--r--requirements.txt7
-rw-r--r--setup.cfg29
-rw-r--r--src/xkcd1172/__init__.py1
-rw-r--r--src/xkcd1172/main.py166
9 files changed, 322 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..abf156d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.egg-info
+dist
+*venv*
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6215aaa
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+BSD 2-Clause License
+
+Copyright (c) 2022, Dawid Potocki
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..00a73e7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,50 @@
+# xkcd1172
+
+Rapidly increases CPU temperature when holding down the spacebar.
+
+***https://xkcd.com/1172***
+
+![xkcd 1172: Workflow](https://imgs.xkcd.com/comics/workflow.png)
+
+## Installation
+
+```sh
+$ pip3 install xkcd1172
+```
+
+### Requirements
+
+- Xorg (Wayland works if you are focused on an Xwayland window)
+- Spacebar
+- CPU
+
+## Building
+
+```sh
+$ git clone https://git.dawidpotocki.com/dawid/xkcd1172
+$ cd xkcd1172
+
+$ python3 -m build
+$ pip3 install dist/xkcd1172-<version>-py3-none-any.whl
+```
+
+## Running standalone
+
+```sh
+$ xkcd1172
+```
+
+### Autostart
+
+```sh
+$ xkcd1172 -a # Add to XDG autostart
+$ xkcd1172 -r # Remove from XDG autostart
+```
+
+## Running as a library
+
+```py
+import xkcd1172
+
+xkcd1172.start_daemon_thread()
+```
diff --git a/docs/xkcd1172.1 b/docs/xkcd1172.1
new file mode 100644
index 0000000..8a2a4ca
--- /dev/null
+++ b/docs/xkcd1172.1
@@ -0,0 +1,36 @@
+.Dd $Mdocdate$
+.Dt XKCD1172 1
+.Os
+.Sh NAME
+.Nm xkcd1172
+.Nd rapidly increase CPU temperature when holding down the spacebar
+.Sh SYNOPSIS
+.Nm
+.Op OPTIONS...
+.Sh DESCRIPTION
+.Nm
+is a program that brings back spacebar heating to your system. You can use it
+standalone or as a Python library to include it in your program.
+.Sh OPTIONS
+.Bl -tag -width Ds -compact
+.It Fl a, Fl -add-autostart
+Adds
+.Nm
+to XDG autostart.
+.Pp
+.It Fl r, Fl -rm-autostart
+Removes
+.Nm
+from XDG autostart.
+.Sh EXAMPLES
+.Pp
+Using as a Python library:
+.Bd -literal
+import xkcd1172
+xkcd1172.start_daemon_thread()
+.Sh AUTHORS
+.An Dawid Potocki
+-
+.Lk https://dawidpotocki.com
+.Sh BUGS
+You mean features?
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..374b58c
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,6 @@
+[build-system]
+requires = [
+ "setuptools>=42",
+ "wheel"
+]
+build-backend = "setuptools.build_meta"
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..e0710ab
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,7 @@
+build==0.7.0
+packaging==21.3
+pep517==0.12.0
+pyparsing==3.0.9
+python-xlib==0.31
+six==1.16.0
+tomli==2.0.1
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..3e97198
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,29 @@
+[metadata]
+name = xkcd1172
+version = 0.1.0
+author = Dawid Potocki
+author_email = pypi@dawidpotocki.com
+description = Rapidly increases CPU temperature when holding down the spacebar
+long_description = file: README.md
+long_description_content_type = text/markdown
+url = https://git.dawidpotocki.com/dawid/xkcd1172
+classifiers =
+ Programming Language :: Python :: 3
+ License :: OSI Approved :: BSD License
+ Operating System :: POSIX
+ Environment :: X11 Applications
+
+[options]
+package_dir =
+ = src
+packages = find:
+python_requires = >=3.7
+install_requires =
+ python-xlib>=0.31,<1
+
+[options.packages.find]
+where = src
+
+[options.entry_points]
+console_scripts =
+ xkcd1172 = xkcd1172:main.main
diff --git a/src/xkcd1172/__init__.py b/src/xkcd1172/__init__.py
new file mode 100644
index 0000000..0eedd79
--- /dev/null
+++ b/src/xkcd1172/__init__.py
@@ -0,0 +1 @@
+from xkcd1172.main import start, start_daemon_thread
diff --git a/src/xkcd1172/main.py b/src/xkcd1172/main.py
new file mode 100644
index 0000000..610d791
--- /dev/null
+++ b/src/xkcd1172/main.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python3
+
+import argparse, atexit, multiprocessing, os, sys, threading
+
+from Xlib import X, XK, display
+from Xlib.ext import record
+from Xlib.protocol import rq
+
+
+#
+# Variables
+#
+
+APPNAME = "xkcd1172"
+ACTIVATE_AT_PRESSES = 2
+
+rubbish_launched = False
+presses_before_release = 0
+local_dpy = None
+
+if "XDG_CONFIG_HOME" in os.environ:
+ XDG_CONFIG_HOME = os.environ["XDG_CONFIG_HOME"]
+else:
+ XDG_CONFIG_HOME = "~/.config"
+
+
+#
+# Functions
+#
+
+def main():
+ """Main function."""
+
+ # Don't print traceback on C-c
+ sys.excepthook = excepthook
+
+ # Argument parsing
+ parser = argparse.ArgumentParser(description="Rapidly increase CPU temperature when holding down the spacebar.")
+ parser.add_argument("-a", "--add-autostart", action="store_true", help=f"add itself to XDG autostart")
+ parser.add_argument("-r", "--rm-autostart", action="store_true", help=f"remove itself from XDG autostart")
+ args = parser.parse_args()
+
+ if args.add_autostart:
+ add_autostart()
+
+ elif args.rm_autostart:
+ rm_autostart()
+
+ else:
+ start()
+
+
+def start():
+ """Setup heating on spacebar holding."""
+ global local_dpy
+
+ if "WAYLAND_DISPLAY" in os.environ:
+ print(
+ "\033[1;33mWARN:\033[0m This utility depends on Xlib, which means it only works with Xorg.\n"
+ " Because you are using Wayland, it will only work when you are focused on an Xwayland window.\n"
+ " How dare these nasty Wayland people break my workflow!\n"
+ )
+ try:
+ local_dpy = display.Display()
+ except Xlib.error.DisplayNameError:
+ print("\033[1;31mCRIT:\033[0m Couldn't find X. Exiting.")
+ exit(1)
+
+ ctx = local_dpy.record_create_context(
+ 0,
+ [record.AllClients],
+ [{
+ 'core_requests': (0, 0),
+ 'core_replies': (0, 0),
+ 'ext_requests': (0, 0, 0, 0),
+ 'ext_replies': (0, 0, 0, 0),
+ 'delivered_events': (0, 0),
+ 'device_events': (X.KeyPress, X.KeyRelease),
+ 'errors': (0, 0),
+ 'client_started': False,
+ 'client_died': False,
+ }]
+ )
+
+ atexit.register(exit_handler, ctx)
+ local_dpy.record_enable_context(ctx, space_handler)
+
+
+def start_daemon_thread():
+ threading.Thread(target=start, daemon=True).start()
+
+
+def space_handler(reply):
+ """Run do_nothing() when space is held."""
+
+ global presses_before_release, rubbish_launched
+
+ data = reply.data
+
+ while len(data):
+ event, data = rq.EventField(None).parse_binary_value(data, local_dpy.display, None, None)
+
+ if presses_before_release > ACTIVATE_AT_PRESSES and rubbish_launched == False:
+ for i in range(multiprocessing.cpu_count()):
+ multiprocessing.Process(target=do_nothing).start()
+ rubbish_launched = True
+
+ if event.type in [X.KeyPress, X.KeyRelease]:
+ # For some reason it's giving numeric keysyms
+ if local_dpy.keycode_to_keysym(event.detail, 0) == 32: # 32 == XK_space
+ if event.type == X.KeyPress:
+ presses_before_release += 1
+ else:
+ for child in multiprocessing.active_children():
+ multiprocessing.Process.kill(child)
+ presses_before_release = 0
+ rubbish_launched = False
+
+
+def do_nothing():
+ """Do nothing."""
+
+ while True:
+ pass
+
+
+def add_autostart():
+ """Add itself to XDG autostart."""
+
+ file_path = f"{XDG_CONFIG_HOME}/autostart/{APPNAME}.desktop"
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
+ with open(file_path, "w") as file:
+ file.write(f"""[Desktop Entry]
+Type=Application
+Name={APPNAME}
+Comment=Rapidly increase CPU temperature when holding down the spacebar
+Exec={APPNAME}
+""")
+
+
+def rm_autostart():
+ """Remove itself from XDG autostart."""
+
+ try:
+ os.remove(f"{XDG_CONFIG_HOME}/autostart/{APPNAME}.desktop")
+ except FileNotFoundError:
+ print(f"\033[1;33mWARN:\033[0m {APPNAME} wasn't in the autostart")
+
+
+def excepthook(type, value, traceback):
+ """Custom exception hook to not print traceback when doing C-c."""
+
+ if type is KeyboardInterrupt:
+ return
+ else:
+ sys.__excepthook__(type, value, traceback)
+
+
+def exit_handler(ctx):
+ """Free context on exit."""
+
+ local_dpy.record_free_context(ctx)
+
+
+if __name__ == "__main__":
+ main()