diff options
Diffstat (limited to 'src/astal.vala')
-rw-r--r-- | src/astal.vala | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/astal.vala b/src/astal.vala new file mode 100644 index 0000000..e9d1484 --- /dev/null +++ b/src/astal.vala @@ -0,0 +1,171 @@ +namespace Astal { +public class Application : Gtk.Application { + public signal void request (string request); + private List<Gtk.CssProvider> css_providers; + private SocketService service; + private string socket; + + public string instance_name { get; construct set; } + + public List<Gtk.Window> windows { + get { return get_windows(); } + } + + public Gtk.Settings settings { + get { return Gtk.Settings.get_default(); } + } + + public Gdk.Screen screen { + get { return Gdk.Screen.get_default(); } + } + + public string gtk_theme { + owned get { return settings.gtk_theme_name; } + set { settings.gtk_theme_name = value; } + } + + public string icon_theme { + owned get { return settings.gtk_icon_theme_name; } + set { settings.gtk_icon_theme_name = value; } + } + + public string cursor_theme { + owned get { return settings.gtk_cursor_theme_name; } + set { settings.gtk_cursor_theme_name = value; } + } + + public void reset_css() { + foreach(var provider in css_providers) { + Gtk.StyleContext.remove_provider_for_screen(screen, provider); + css_providers.remove_all(provider); + } + } + + public void inspector() { + Gtk.Window.set_interactive_debugging(true); + } + + public Gtk.Window get_window(string name) throws WindowError { + foreach(var win in windows) { + if (win.name == name) + return win; + } + + throw new WindowError.NO_WINDOW_WITH_NAME(name); + } + + public void apply_css(string style, bool reset = false) throws Error { + var provider = new Gtk.CssProvider(); + + if (reset) + reset_css(); + + if (FileUtils.test(style, FileTest.EXISTS)) + provider.load_from_path(style); + else + provider.load_from_data(style); + + Gtk.StyleContext.add_provider_for_screen( + screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_USER); + + css_providers.append(provider); + } + + private async void _socket_request(SocketConnection conn) { + string message = yield read_sock(conn); + request(message.strip()); + response(message.strip(), conn); + } + + public virtual void response(string msg, SocketConnection conn) { + write_sock.begin(conn, "missing response implementation on ".concat(application_id)); + } + + /** + * should be called before `run()` + * the return value indicates if instance is already running + */ + public bool acquire_socket() { + socket = GLib.Environment.get_user_runtime_dir().concat( + "/", + instance_name, + ".sock"); + + if (FileUtils.test(socket, GLib.FileTest.EXISTS)) { + info("socket %s exists", socket); + return false; + } + + try { + SocketAddress _; + service = new SocketService(); + service.add_address( + new UnixSocketAddress(socket), + SocketType.STREAM, + SocketProtocol.DEFAULT, + null, + out _); + + service.incoming.connect((conn) => { + _socket_request.begin(conn); + return false; + }); + + info("socket acquired: %s\n", socket); + return true; + } catch (Error err) { + critical("could not acquire socket %s\n", application_id); + critical(err.message); + return false; + } + } + + construct { + if (instance_name == null) + instance_name = "astal"; + + if (application_id == null) + application_id = "io.Astal.".concat(instance_name); + + shutdown.connect(() => { + if (FileUtils.test(socket, GLib.FileTest.EXISTS)){ + try { + File.new_for_path(socket).delete(null); + } catch (Error err) { + warning(err.message); + } + } + }); + + SourceFunc close = () => { quit(); }; + Unix.signal_add(1, close, Priority.HIGH); + Unix.signal_add(2, close, Priority.HIGH); + Unix.signal_add(15, close, Priority.HIGH); + } +} + +public errordomain WindowError { + NO_WINDOW_WITH_NAME +} + +public async string read_sock(SocketConnection conn) { + try { + var stream = new DataInputStream(conn.input_stream); + size_t size; + return yield stream.read_upto_async("\x04", -1, Priority.DEFAULT, null, out size); + } catch (Error err) { + critical(err.message); + return err.message; + } +} + +public async void write_sock(SocketConnection conn, string response) { + try { + yield conn.output_stream.write_async( + response.concat("\x04").data, + Priority.DEFAULT); + } catch (Error err) { + critical(err.message); + } +} +} |