import tkinter as tk import threading import time from flask import Flask from flask import render_template, request app = Flask(__name__) class SharedState(threading.Thread): def __init__(self): self._lock = threading.Lock() self._running = True # When screen is visible, we do not show any window self._screen_visible = True def toggle(self): # this gets called from the Flask thread to record a click with self._lock: # Toggle screen visibility self._screen_visible = not self._screen_visible return self._screen_visible def visible(self): # this gets called from the API thread to 'get' a click return self._screen_visible def stop(self): # called from either side to stop running app.logger.info("stop: setting running to false") with self._lock: self._running = False def running(self): return self._running @app.route('/toggle') def home(): if request.method == 'GET': screen_visibility = app.config['SHARED'].toggle() return render_template('screenserver.html', screen_visibility = screen_visibility) def webserver(shared_state): app.config['SHARED'] = shared_state # It isn't safe to use the reloader in a thread app.run(host='127.0.0.1', debug=True, use_reloader=False) def main(): shared_state = SharedState() api_thread = threading.Thread(target=webserver, args=(shared_state,)) api_thread.start() while shared_state.running(): app.logger.debug("while shared_state.running():") time.sleep(0.1) root = tk.Tk() if not shared_state.visible(): # if state is NOT visible, hide the screen by showing the window screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() ### FIXME: In dev-mode, do not fill the entire screen screen_height, screen_width = "100", "200" root.attributes('-alpha', 0.0) #For icon root.iconify() window = tk.Toplevel(root) window.geometry("%sx%s" % (screen_width, screen_height)) window.configure(background='black', cursor='none') # No border window.overrideredirect(1) # Always on top window.attributes('-topmost', 1) window.mainloop() else: # if state IS visible, show the screen by closing the window print("Destroying root") try: root.destroy() except Exception as e: print(e) pass api_thread.join() if __name__ == '__main__': main()