| 
						
						
						
					 | 
					 | 
					@ -1,9 +1,12 @@ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					from functools import partial | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import time | 
					 | 
					 | 
					 | 
					import time | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					from typing import Literal | 
					 | 
					 | 
					 | 
					from typing import Literal | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import pyray as rl | 
					 | 
					 | 
					 | 
					import pyray as rl | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					from openpilot.system.ui.lib.application import gui_app, FontWeight | 
					 | 
					 | 
					 | 
					from openpilot.system.ui.lib.application import gui_app, FontWeight | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					from openpilot.system.ui.widgets import Widget | 
					 | 
					 | 
					 | 
					from openpilot.system.ui.widgets import Widget | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					from openpilot.system.ui.widgets.button import ButtonStyle, gui_button | 
					 | 
					 | 
					 | 
					from openpilot.system.ui.widgets.button import ButtonStyle, Button | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					from openpilot.system.ui.widgets.inputbox import InputBox | 
					 | 
					 | 
					 | 
					from openpilot.system.ui.widgets.inputbox import InputBox | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					from openpilot.system.ui.widgets.label import gui_label | 
					 | 
					 | 
					 | 
					from openpilot.system.ui.widgets.label import gui_label | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -73,6 +76,9 @@ class Keyboard(Widget): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    self._backspace_press_time: float = 0.0 | 
					 | 
					 | 
					 | 
					    self._backspace_press_time: float = 0.0 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    self._backspace_last_repeat: float = 0.0 | 
					 | 
					 | 
					 | 
					    self._backspace_last_repeat: float = 0.0 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    self._render_return_status = -1 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    self._cancel_button = Button("Cancel", self._cancel_button_callback) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    self._eye_open_texture = gui_app.texture("icons/eye_open.png", 81, 54) | 
					 | 
					 | 
					 | 
					    self._eye_open_texture = gui_app.texture("icons/eye_open.png", 81, 54) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    self._eye_closed_texture = gui_app.texture("icons/eye_closed.png", 81, 54) | 
					 | 
					 | 
					 | 
					    self._eye_closed_texture = gui_app.texture("icons/eye_closed.png", 81, 54) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    self._key_icons = { | 
					 | 
					 | 
					 | 
					    self._key_icons = { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -83,6 +89,18 @@ class Keyboard(Widget): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ENTER_KEY: gui_app.texture("icons/arrow-right.png", 80, 80), | 
					 | 
					 | 
					 | 
					      ENTER_KEY: gui_app.texture("icons/arrow-right.png", 80, 80), | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    self._all_keys = {} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    for l in KEYBOARD_LAYOUTS: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      for _, keys in enumerate(KEYBOARD_LAYOUTS[l]): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        for _, key in enumerate(keys): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          if key in self._key_icons: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            texture = self._key_icons[key] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            self._all_keys[key] = Button("", partial(self._key_callback, key), icon=texture, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                                        button_style=ButtonStyle.PRIMARY if key == ENTER_KEY else ButtonStyle.NORMAL) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          else: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            self._all_keys[key] = Button(key, partial(self._key_callback, key)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    self._all_keys[CAPS_LOCK_KEY] = Button("", partial(self._key_callback, CAPS_LOCK_KEY), icon=self._key_icons[CAPS_LOCK_KEY]) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  @property | 
					 | 
					 | 
					 | 
					  @property | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  def text(self): | 
					 | 
					 | 
					 | 
					  def text(self): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return self._input_box.text | 
					 | 
					 | 
					 | 
					    return self._input_box.text | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -97,13 +115,21 @@ class Keyboard(Widget): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    self._title = title | 
					 | 
					 | 
					 | 
					    self._title = title | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    self._sub_title = sub_title | 
					 | 
					 | 
					 | 
					    self._sub_title = sub_title | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  def _cancel_button_callback(self): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    self.clear() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    self._render_return_status = 0 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  def _key_callback(self, k): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if k == ENTER_KEY: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      self._render_return_status = 1 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    else: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      self.handle_key_press(k) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  def _render(self, rect: rl.Rectangle): | 
					 | 
					 | 
					 | 
					  def _render(self, rect: rl.Rectangle): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    rect = rl.Rectangle(rect.x + CONTENT_MARGIN, rect.y + CONTENT_MARGIN, rect.width - 2 * CONTENT_MARGIN, rect.height - 2 * CONTENT_MARGIN) | 
					 | 
					 | 
					 | 
					    rect = rl.Rectangle(rect.x + CONTENT_MARGIN, rect.y + CONTENT_MARGIN, rect.width - 2 * CONTENT_MARGIN, rect.height - 2 * CONTENT_MARGIN) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    gui_label(rl.Rectangle(rect.x, rect.y, rect.width, 95), self._title, 90, font_weight=FontWeight.BOLD) | 
					 | 
					 | 
					 | 
					    gui_label(rl.Rectangle(rect.x, rect.y, rect.width, 95), self._title, 90, font_weight=FontWeight.BOLD) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    gui_label(rl.Rectangle(rect.x, rect.y + 95, rect.width, 60), self._sub_title, 55, font_weight=FontWeight.NORMAL) | 
					 | 
					 | 
					 | 
					    gui_label(rl.Rectangle(rect.x, rect.y + 95, rect.width, 60), self._sub_title, 55, font_weight=FontWeight.NORMAL) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if gui_button(rl.Rectangle(rect.x + rect.width - 386, rect.y, 386, 125), "Cancel"): | 
					 | 
					 | 
					 | 
					    self._cancel_button.render(rl.Rectangle(rect.x + rect.width - 386, rect.y, 386, 125)) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      self.clear() | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      return 0 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    # Draw input box and password toggle | 
					 | 
					 | 
					 | 
					    # Draw input box and password toggle | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    input_margin = 25 | 
					 | 
					 | 
					 | 
					    input_margin = 25 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -111,7 +137,7 @@ class Keyboard(Widget): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    self._render_input_area(input_box_rect) | 
					 | 
					 | 
					 | 
					    self._render_input_area(input_box_rect) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    # Process backspace key repeat if it's held down | 
					 | 
					 | 
					 | 
					    # Process backspace key repeat if it's held down | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if not rl.is_mouse_button_down(rl.MouseButton.MOUSE_BUTTON_LEFT): | 
					 | 
					 | 
					 | 
					    if not self._all_keys[BACKSPACE_KEY]._is_pressed: | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      self._backspace_pressed = False | 
					 | 
					 | 
					 | 
					      self._backspace_pressed = False | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if self._backspace_pressed: | 
					 | 
					 | 
					 | 
					    if self._backspace_pressed: | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -146,33 +172,22 @@ class Keyboard(Widget): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        start_x += new_width | 
					 | 
					 | 
					 | 
					        start_x += new_width | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        is_enabled = key != ENTER_KEY or len(self._input_box.text) >= self._min_text_size | 
					 | 
					 | 
					 | 
					        is_enabled = key != ENTER_KEY or len(self._input_box.text) >= self._min_text_size | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        result = -1 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        # Check for backspace key press-and-hold | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        mouse_pos = rl.get_mouse_position() | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        mouse_over_key = rl.check_collision_point_rec(mouse_pos, key_rect) | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        if key == BACKSPACE_KEY and mouse_over_key: | 
					 | 
					 | 
					 | 
					        if key == BACKSPACE_KEY and self._all_keys[BACKSPACE_KEY]._is_pressed and not self._backspace_pressed: | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          if rl.is_mouse_button_pressed(rl.MouseButton.MOUSE_BUTTON_LEFT): | 
					 | 
					 | 
					 | 
					          self._backspace_pressed = True | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            self._backspace_pressed = True | 
					 | 
					 | 
					 | 
					          self._backspace_press_time = time.monotonic() | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            self._backspace_press_time = time.monotonic() | 
					 | 
					 | 
					 | 
					          self._backspace_last_repeat = time.monotonic() | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            self._backspace_last_repeat = time.monotonic() | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        if key in self._key_icons: | 
					 | 
					 | 
					 | 
					        if key in self._key_icons: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          if key == SHIFT_ACTIVE_KEY and self._caps_lock: | 
					 | 
					 | 
					 | 
					          if key == SHIFT_ACTIVE_KEY and self._caps_lock: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            key = CAPS_LOCK_KEY | 
					 | 
					 | 
					 | 
					            key = CAPS_LOCK_KEY | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          texture = self._key_icons[key] | 
					 | 
					 | 
					 | 
					          self._all_keys[key].enabled = is_enabled | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          result = gui_button(key_rect, "", icon=texture, button_style=ButtonStyle.PRIMARY if key == ENTER_KEY else ButtonStyle.NORMAL, is_enabled=is_enabled) | 
					 | 
					 | 
					 | 
					          self._all_keys[key].render(key_rect) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        else: | 
					 | 
					 | 
					 | 
					        else: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          result = gui_button(key_rect, key, KEY_FONT_SIZE, is_enabled=is_enabled) | 
					 | 
					 | 
					 | 
					          self._all_keys[key].enabled = is_enabled | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					          self._all_keys[key].render(key_rect) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        if result: | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          if key == ENTER_KEY: | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            return 1 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          else: | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            self.handle_key_press(key) | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return -1 | 
					 | 
					 | 
					 | 
					    return self._render_return_status | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  def _render_input_area(self, input_rect: rl.Rectangle): | 
					 | 
					 | 
					 | 
					  def _render_input_area(self, input_rect: rl.Rectangle): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if self._show_password_toggle: | 
					 | 
					 | 
					 | 
					    if self._show_password_toggle: | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |