@@ -185,6 +185,20 @@ class Manager:
185185 "dest" : "=" ,
186186 "before" : "on_code_autocomplete" ,
187187 },
188+ # Theme change
189+ {
190+ "trigger" : "change_style" ,
191+ "source" : [
192+ "idle" ,
193+ "connected" ,
194+ "paused" ,
195+ "world_ready" ,
196+ "tools_ready" ,
197+ "application_running" ,
198+ ],
199+ "dest" : "=" ,
200+ "before" : "on_change_style" ,
201+ },
188202 ]
189203
190204 def __init__ (self , host : str , port : int ):
@@ -618,6 +632,93 @@ def on_code_autocomplete(self, event):
618632 except Exception as e :
619633 LogManager .logger .info ("Error formating code" + str (e ))
620634
635+ def on_change_style (self , event ):
636+ """
637+ Handle the 'change_style' event.
638+
639+ This method changes the GTK theme and xterm colors without restarting.
640+
641+ Parameters:
642+ event (Event): Has the field 'theme' (dark or light) in data.
643+ """
644+ app_cfg = event .kwargs .get ("data" , {})
645+ theme = app_cfg .get ("theme" , "dark" )
646+ LogManager .logger .info (f"Changing style to { theme } " )
647+
648+ if theme == "dark" :
649+ # Xterm dark theme: background black, foreground white
650+ xterm_cmd = "\033 ]11;black\007 \033 ]10;white\007 "
651+ gtk_theme = "Adwaita-dark"
652+ else :
653+ # Xterm light theme: background white, foreground black
654+ xterm_cmd = "\033 ]11;white\007 \033 ]10;black\007 "
655+ gtk_theme = "Adwaita"
656+
657+ # Apply xterm theme to all active pseudoterminals
658+ try :
659+ self .write_to_tool_terminal (xterm_cmd )
660+ except Exception as e :
661+ LogManager .logger .exception (f"Error changing xterm style: { e } " )
662+
663+ # Update GTK settings for new windows
664+ # Write ~/.gtkrc-2.0
665+ gtkrc_path = os .path .expanduser ("~/.gtkrc-2.0" )
666+ try :
667+ with open (gtkrc_path , "w" ) as f :
668+ f .write (f'gtk-theme-name="{ gtk_theme } "\n ' )
669+ except Exception as e :
670+ LogManager .logger .exception (f"Error writing { gtkrc_path } : { e } " )
671+
672+ # Write ~/.config/gtk-3.0/settings.ini
673+ gtk3_dir = os .path .expanduser ("~/.config/gtk-3.0" )
674+ gtk3_path = os .path .join (gtk3_dir , "settings.ini" )
675+ try :
676+ os .makedirs (gtk3_dir , exist_ok = True )
677+ with open (gtk3_path , "w" ) as f :
678+ f .write ("[Settings]\n " )
679+ f .write (f"gtk-theme-name={ gtk_theme } \n " )
680+ except Exception as e :
681+ LogManager .logger .exception (f"Error writing { gtk3_path } : { e } " )
682+
683+ # Send a signal to force GTK applications to reload their theme
684+ try :
685+ # Also write to lxsession config which is what LXDE actually uses
686+ lxde_conf_dir = os .path .expanduser ("~/.config/lxsession/LXDE" )
687+ lxde_conf_path = os .path .join (lxde_conf_dir , "desktop.conf" )
688+ os .makedirs (lxde_conf_dir , exist_ok = True )
689+
690+ # Read existing or create new
691+ conf_lines = []
692+ if os .path .exists (lxde_conf_path ):
693+ with open (lxde_conf_path , "r" ) as f :
694+ conf_lines = f .readlines ()
695+
696+ # Ensure GTK section exists and update theme name
697+ gtk_section_found = False
698+ for i , line in enumerate (conf_lines ):
699+ if line .strip () == "[GTK]" :
700+ gtk_section_found = True
701+ elif gtk_section_found and line .startswith ("sNet/ThemeName=" ):
702+ conf_lines [i ] = f"sNet/ThemeName={ gtk_theme } \\ n"
703+ break
704+ else :
705+ if not gtk_section_found :
706+ conf_lines .append ("[GTK]\\ n" )
707+ conf_lines .append (f"sNet/ThemeName={ gtk_theme } \\ n" )
708+
709+ with open (lxde_conf_path , "w" ) as f :
710+ f .writelines (conf_lines )
711+
712+ # Reload window manager (Openbox) and LXPanel
713+ subprocess .run (
714+ ["bash" , "-c" , "export DISPLAY=:1; lxpanelctl restart; openbox --reconfigure" ],
715+ stdout = subprocess .DEVNULL ,
716+ stderr = subprocess .DEVNULL
717+ )
718+ except Exception as e :
719+ LogManager .logger .exception (f"Error refreshing GTK applications: { e } " )
720+
721+
621722 def on_run_application (self , event ):
622723 """
623724 Handle the 'run_application' event.
0 commit comments