no more lock!

pull/36063/head
Shane Smiskol 3 days ago
parent 0c6974db12
commit 8c1abd96a2
  1. 25
      system/ui/lib/wifi_manager.py
  2. 75
      system/ui/widgets/network.py

@ -136,10 +136,9 @@ class WifiManager:
self._callback_queue: list[Callable] = [] self._callback_queue: list[Callable] = []
# Callbacks # Callbacks
# TODO: implement a callback queue to avoid blocking UI thread
self._need_auth: Callable[[str], None] | None = None self._need_auth: Callable[[str], None] | None = None
self._activated: Callable[[], None] | None = None self._activated: Callable[[], None] | None = None
self._forgotten: Callable[[str], None] | None = None self._forgotten: Callable[[], None] | None = None
self._networks_updated: Callable[[list[Network]], None] | None = None self._networks_updated: Callable[[list[Network]], None] | None = None
self._disconnected: Callable[[], None] | None = None self._disconnected: Callable[[], None] | None = None
@ -155,7 +154,7 @@ class WifiManager:
def set_callbacks(self, need_auth: Callable[[str], None], def set_callbacks(self, need_auth: Callable[[str], None],
activated: Callable[[], None] | None, activated: Callable[[], None] | None,
forgotten: Callable[[str], None], forgotten: Callable[[], None],
networks_updated: Callable[[list[Network]], None], networks_updated: Callable[[list[Network]], None],
disconnected: Callable[[], None]): disconnected: Callable[[], None]):
self._need_auth = need_auth self._need_auth = need_auth
@ -164,11 +163,14 @@ class WifiManager:
self._networks_updated = networks_updated self._networks_updated = networks_updated
self._disconnected = disconnected self._disconnected = disconnected
def _enqueue_callback(self, cb: Callable, *args):
self._callback_queue.append(lambda: cb(*args))
def process_callbacks(self): def process_callbacks(self):
for cb in self._callback_queue: # Call from UI thread to run any pending callbacks
print('calling wifi cb', cb.__name__) to_run, self._callback_queue = self._callback_queue, []
for cb in to_run:
cb() cb()
self._callback_queue.clear()
def set_active(self, active: bool): def set_active(self, active: bool):
self._active = active self._active = active
@ -213,19 +215,20 @@ class WifiManager:
print('hi') print('hi')
if self._need_auth is not None: if self._need_auth is not None:
print('wifi need auth', self._connecting_to_ssid) print('wifi need auth', self._connecting_to_ssid)
self._callback_queue.append(lambda ssid=self._connecting_to_ssid: self._need_auth(ssid)) # self._callback_queue.append(lambda cb=self._need_auth, ssid=self._connecting_to_ssid: cb(ssid))
self._enqueue_callback(self._need_auth, self._connecting_to_ssid)
self._connecting_to_ssid = "" self._connecting_to_ssid = ""
elif new_state == NMDeviceState.ACTIVATED: elif new_state == NMDeviceState.ACTIVATED:
if self._activated is not None: if self._activated is not None:
self._update_networks() self._update_networks()
self._callback_queue.append(self._activated) self._enqueue_callback(self._activated)
self._connecting_to_ssid = "" self._connecting_to_ssid = ""
elif new_state == NMDeviceState.DISCONNECTED and change_reason != NM_DEVICE_STATE_REASON_NEW_ACTIVATION: elif new_state == NMDeviceState.DISCONNECTED and change_reason != NM_DEVICE_STATE_REASON_NEW_ACTIVATION:
self._connecting_to_ssid = "" self._connecting_to_ssid = ""
if self._disconnected is not None: if self._disconnected is not None:
self._callback_queue.append(self._disconnected) self._enqueue_callback(self._disconnected)
def _network_scanner(self): def _network_scanner(self):
self._wait_for_wifi_device() self._wait_for_wifi_device()
@ -333,7 +336,7 @@ class WifiManager:
if self._forgotten is not None: if self._forgotten is not None:
self._update_networks() self._update_networks()
self._callback_queue.append(lambda: self._forgotten(ssid)) self._enqueue_callback(self._forgotten)
if block: if block:
worker() worker()
@ -409,7 +412,7 @@ class WifiManager:
self._networks = networks self._networks = networks
if self._networks_updated is not None: if self._networks_updated is not None:
self._callback_queue.append(lambda: self._networks_updated(self._networks)) self._enqueue_callback(self._networks_updated, self._networks)
def __del__(self): def __del__(self):
self.stop() self.stop()

@ -1,6 +1,5 @@
from enum import IntEnum from enum import IntEnum
from functools import partial from functools import partial
from threading import Lock
from typing import cast from typing import cast
import pyray as rl import pyray as rl
@ -50,7 +49,6 @@ class WifiManagerUI(Widget):
self._networks: list[Network] = [] self._networks: list[Network] = []
self._networks_buttons: dict[str, Button] = {} self._networks_buttons: dict[str, Button] = {}
self._forget_networks_buttons: dict[str, Button] = {} self._forget_networks_buttons: dict[str, Button] = {}
self._lock = Lock()
self._confirm_dialog = ConfirmDialog("", "Forget", "Cancel") self._confirm_dialog = ConfirmDialog("", "Forget", "Cancel")
self.wifi_manager.set_callbacks(need_auth=self._on_need_auth, self.wifi_manager.set_callbacks(need_auth=self._on_need_auth,
@ -73,21 +71,20 @@ class WifiManagerUI(Widget):
def _render(self, rect: rl.Rectangle): def _render(self, rect: rl.Rectangle):
self.wifi_manager.process_callbacks() self.wifi_manager.process_callbacks()
with self._lock: if not self._networks:
if not self._networks: gui_label(rect, "Scanning Wi-Fi networks...", 72, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER)
gui_label(rect, "Scanning Wi-Fi networks...", 72, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER) return
return
if self.state == UIState.NEEDS_AUTH and self._state_network:
if self.state == UIState.NEEDS_AUTH and self._state_network: self.keyboard.set_title("Wrong password" if self._password_retry else "Enter password", f"for {self._state_network.ssid}")
self.keyboard.set_title("Wrong password" if self._password_retry else "Enter password", f"for {self._state_network.ssid}") self.keyboard.reset()
self.keyboard.reset() gui_app.set_modal_overlay(self.keyboard, lambda result: self._on_password_entered(cast(Network, self._state_network), result))
gui_app.set_modal_overlay(self.keyboard, lambda result: self._on_password_entered(cast(Network, self._state_network), result)) elif self.state == UIState.SHOW_FORGET_CONFIRM and self._state_network:
elif self.state == UIState.SHOW_FORGET_CONFIRM and self._state_network: self._confirm_dialog.set_text(f'Forget Wi-Fi Network "{self._state_network.ssid}"?')
self._confirm_dialog.set_text(f'Forget Wi-Fi Network "{self._state_network.ssid}"?') self._confirm_dialog.reset()
self._confirm_dialog.reset() gui_app.set_modal_overlay(self._confirm_dialog, callback=lambda result: self.on_forgot_confirm_finished(self._state_network, result))
gui_app.set_modal_overlay(self._confirm_dialog, callback=lambda result: self.on_forgot_confirm_finished(self._state_network, result)) else:
else: self._draw_network_list(rect)
self._draw_network_list(rect)
def _on_password_entered(self, network: Network, result: int): def _on_password_entered(self, network: Network, result: int):
if result == 1: if result == 1:
@ -213,37 +210,35 @@ class WifiManagerUI(Widget):
self.wifi_manager.forget_connection(network.ssid) self.wifi_manager.forget_connection(network.ssid)
def _on_network_updated(self, networks: list[Network]): def _on_network_updated(self, networks: list[Network]):
with self._lock: print('networks updated', [n.ssid for n in networks])
self._networks = networks self._networks = networks
for n in self._networks: for n in self._networks:
self._networks_buttons[n.ssid] = Button(n.ssid, partial(self._networks_buttons_callback, n), font_size=55, text_alignment=TextAlignment.LEFT, self._networks_buttons[n.ssid] = Button(n.ssid, partial(self._networks_buttons_callback, n), font_size=55, text_alignment=TextAlignment.LEFT,
button_style=ButtonStyle.NO_EFFECT) button_style=ButtonStyle.NO_EFFECT)
self._forget_networks_buttons[n.ssid] = Button("Forget", partial(self._forget_networks_buttons_callback, n), button_style=ButtonStyle.FORGET_WIFI, self._forget_networks_buttons[n.ssid] = Button("Forget", partial(self._forget_networks_buttons_callback, n), button_style=ButtonStyle.FORGET_WIFI,
font_size=45) font_size=45)
def _on_need_auth(self, ssid): def _on_need_auth(self, ssid):
print('need auth for', ssid) print('need auth for', ssid)
with self._lock: network = next((n for n in self._networks if n.ssid == ssid), None)
network = next((n for n in self._networks if n.ssid == ssid), None) if network:
if network: self.state = UIState.NEEDS_AUTH
self.state = UIState.NEEDS_AUTH self._state_network = network
self._state_network = network self._password_retry = True
self._password_retry = True
def _on_activated(self): def _on_activated(self):
with self._lock: print('_on_activated')
if self.state == UIState.CONNECTING: if self.state == UIState.CONNECTING:
self.state = UIState.IDLE self.state = UIState.IDLE
def _on_forgotten(self, ssid): def _on_forgotten(self):
with self._lock: print('_on_forgotten')
if self.state == UIState.FORGETTING: if self.state == UIState.FORGETTING:
self.state = UIState.IDLE self.state = UIState.IDLE
def _on_disconnected(self): def _on_disconnected(self):
with self._lock: if self.state == UIState.CONNECTING:
if self.state == UIState.CONNECTING: self.state = UIState.IDLE
self.state = UIState.IDLE
def main(): def main():

Loading…
Cancel
Save