mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-07 20:09:59 +03:00
port changing functionality (#34)
* port changing functionality * add portchange to cli frontend
This commit is contained in:
committed by
GitHub
parent
60a73b3cb0
commit
e88241e816
@@ -1,3 +1,11 @@
|
||||
#delete-button {
|
||||
color: @red_1;
|
||||
}
|
||||
|
||||
#port-edit-cancel {
|
||||
color: @red_1;
|
||||
}
|
||||
|
||||
#port-edit-apply {
|
||||
color: @green_1;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
#delete-button {
|
||||
color: @red_3;
|
||||
}
|
||||
|
||||
#port-edit-cancel {
|
||||
color: @red_3;
|
||||
}
|
||||
|
||||
#port-edit-apply {
|
||||
color: @green_3;
|
||||
}
|
||||
|
||||
@@ -8,114 +8,143 @@
|
||||
<attribute name="action">window.close</attribute>
|
||||
</item>
|
||||
</menu>
|
||||
<template class="LanMouseWindow" parent="GtkApplicationWindow">
|
||||
<template class="LanMouseWindow" parent="AdwApplicationWindow">
|
||||
<property name="width-request">600</property>
|
||||
<property name="title" translatable="yes">Lan Mouse</property>
|
||||
<property name="show-menubar">True</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<child type ="end">
|
||||
<object class="GtkMenuButton">
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
<property name="menu-model">main-menu</property>
|
||||
<property name="content">
|
||||
<object class="AdwToolbarView">
|
||||
<child type="top">
|
||||
<object class="AdwHeaderBar">
|
||||
<child type ="end">
|
||||
<object class="GtkMenuButton">
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
<property name="menu-model">main-menu</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="flat"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwStatusPage">
|
||||
<property name="title" translatable="yes">Lan Mouse</property>
|
||||
<property name="description" translatable="yes">easily use your mouse and keyboard on multiple computers</property>
|
||||
<property name="icon-name">mouse-icon</property>
|
||||
<property name="child">
|
||||
<object class="AdwClamp">
|
||||
<property name="maximum-size">600</property>
|
||||
<property name="tightening-threshold">0</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<property name="content">
|
||||
<object class="AdwToastOverlay" id="toast_overlay">
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">General</property>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">enable</property>
|
||||
<child type="suffix">
|
||||
<object class="GtkSwitch">
|
||||
<property name="valign">center</property>
|
||||
<property name="tooltip-text" translatable="yes">enable</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title">port</property>
|
||||
<object class="AdwStatusPage">
|
||||
<property name="title" translatable="yes">Lan Mouse</property>
|
||||
<property name="description" translatable="yes">easily use your mouse and keyboard on multiple computers</property>
|
||||
<property name="icon-name">mouse-icon</property>
|
||||
<property name="child">
|
||||
<object class="AdwClamp">
|
||||
<property name="maximum-size">600</property>
|
||||
<property name="tightening-threshold">0</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">12</property>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<!-- <property name="title" translatable="yes">port</property> -->
|
||||
<property name="placeholder-text">4242</property>
|
||||
<property name="width-chars">5</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="valign">center</property>
|
||||
<!-- <property name="show-apply-button">True</property> -->
|
||||
<property name="input-purpose">GTK_INPUT_PURPOSE_DIGITS</property>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">General</property>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="yes">enable</property>
|
||||
<child type="suffix">
|
||||
<object class="GtkSwitch">
|
||||
<property name="valign">center</property>
|
||||
<property name="tooltip-text" translatable="yes">enable</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title">port</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="port_entry">
|
||||
<signal name="activate" handler="handle_port_edit_apply" swapped="true"/>
|
||||
<signal name="changed" handler="handle_port_changed" swapped="true"/>
|
||||
<!-- <signal name="delete-text" handler="handle_port_changed" swapped="true"/> -->
|
||||
<!-- <property name="title" translatable="yes">port</property> -->
|
||||
<property name="placeholder-text">4242</property>
|
||||
<property name="width-chars">5</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="valign">center</property>
|
||||
<!-- <property name="show-apply-button">True</property> -->
|
||||
<property name="input-purpose">GTK_INPUT_PURPOSE_DIGITS</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="port_edit_apply">
|
||||
<signal name="clicked" handler="handle_port_edit_apply" swapped="true"/>
|
||||
<property name="icon-name">object-select-symbolic</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="visible">false</property>
|
||||
<property name="name">port-edit-apply</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="port_edit_cancel">
|
||||
<signal name="clicked" handler="handle_port_edit_cancel" swapped="true"/>
|
||||
<property name="icon-name">process-stop-symbolic</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="visible">false</property>
|
||||
<property name="name">port-edit-cancel</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Connections</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="client_list">
|
||||
<property name="selection-mode">none</property>
|
||||
<child type="placeholder">
|
||||
<object class="AdwActionRow" id="client_placeholder">
|
||||
<property name="title">No connections!</property>
|
||||
<property name="subtitle">add a new client via the button below</property>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<property name="title" translatable="yes">Connections</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="client_list">
|
||||
<property name="selection-mode">none</property>
|
||||
<child type="placeholder">
|
||||
<object class="AdwActionRow" id="client_placeholder">
|
||||
<property name="title">No connections!</property>
|
||||
<property name="subtitle">add a new client via the button below</property>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="boxed-list" />
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<style>
|
||||
<class name="boxed-list" />
|
||||
</style>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="GtkButton" id="add_client_button">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="tooltip-text">connect a new computer</property>
|
||||
<property name="child">
|
||||
<object class="AdwButtonContent">
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
<property name="label" translatable="yes">Add</property>
|
||||
<property name="use-underline">True</property>
|
||||
</object>
|
||||
</property>
|
||||
<signal name="clicked" handler="handle_add_client_pressed" swapped="true"/>
|
||||
<style>
|
||||
<class name="pill"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwPreferencesGroup">
|
||||
<child>
|
||||
<object class="GtkButton" id="add_client_button">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="tooltip-text">connect a new computer</property>
|
||||
<property name="child">
|
||||
<object class="AdwButtonContent">
|
||||
<property name="icon-name">list-add-symbolic</property>
|
||||
<property name="label" translatable="yes">Add</property>
|
||||
<property name="use-underline">True</property>
|
||||
</object>
|
||||
</property>
|
||||
<!-- <signal name="clicked" handler="handle_add_client" swapped="true"/> -->
|
||||
<style>
|
||||
<class name="pill"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
|
||||
@@ -453,13 +453,38 @@ impl Server {
|
||||
match event {
|
||||
FrontendEvent::AddClient(hostname, port, pos) => { self.add_client(hostname, HashSet::new(), port, pos).await; },
|
||||
FrontendEvent::ActivateClient(client, active) => self.activate_client(client, active).await,
|
||||
FrontendEvent::ChangePort(port) => {
|
||||
let current_port = self.socket.local_addr().unwrap().port();
|
||||
if current_port == port {
|
||||
if let Err(e) = self.frontend.notify_all(FrontendNotify::NotifyPortChange(port, None)).await {
|
||||
log::warn!("error notifying frontend: {e}");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
let listen_addr = SocketAddr::new("0.0.0.0".parse().unwrap(), port);
|
||||
match UdpSocket::bind(listen_addr).await {
|
||||
Ok(socket) => {
|
||||
self.socket = socket;
|
||||
if let Err(e) = self.frontend.notify_all(FrontendNotify::NotifyPortChange(port, None)).await {
|
||||
log::warn!("error notifying frontend: {e}");
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::warn!("could not change port: {e}");
|
||||
let port = self.socket.local_addr().unwrap().port();
|
||||
if let Err(e) = self.frontend.notify_all(FrontendNotify::NotifyPortChange(port, Some(format!("could not change port: {e}")))).await {
|
||||
log::error!("error notifying frontend: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
FrontendEvent::DelClient(client) => { self.remove_client(client).await; },
|
||||
FrontendEvent::UpdateClient(client, hostname, port, pos) => self.update_client(client, hostname, port, pos).await,
|
||||
FrontendEvent::Enumerate() => self.enumerate().await,
|
||||
FrontendEvent::Shutdown() => {
|
||||
log::info!("terminating gracefully...");
|
||||
return true;
|
||||
},
|
||||
FrontendEvent::UpdateClient(client, hostname, port, pos) => self.update_client(client, hostname, port, pos).await,
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
@@ -33,14 +33,16 @@ pub enum FrontendEvent {
|
||||
AddClient(Option<String>, u16, Position),
|
||||
/// activate/deactivate client
|
||||
ActivateClient(ClientHandle, bool),
|
||||
/// update a client (hostname, port, position)
|
||||
UpdateClient(ClientHandle, Option<String>, u16, Position),
|
||||
/// change the listen port (recreate udp listener)
|
||||
ChangePort(u16),
|
||||
/// remove a client
|
||||
DelClient(ClientHandle),
|
||||
/// request an enumertaion of all clients
|
||||
Enumerate(),
|
||||
/// service shutdown
|
||||
Shutdown(),
|
||||
/// update a client (hostname, port, position)
|
||||
UpdateClient(ClientHandle, Option<String>, u16, Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -48,6 +50,8 @@ pub enum FrontendNotify {
|
||||
NotifyClientCreate(ClientHandle, Option<String>, u16, Position),
|
||||
NotifyClientUpdate(ClientHandle, Option<String>, u16, Position),
|
||||
NotifyClientDelete(ClientHandle),
|
||||
/// new port, reason of failure (if failed)
|
||||
NotifyPortChange(u16, Option<String>),
|
||||
Enumerate(Vec<(Client, bool)>),
|
||||
NotifyError(String),
|
||||
}
|
||||
|
||||
@@ -115,6 +115,12 @@ pub fn start() -> Result<(JoinHandle<()>, JoinHandle<()>)> {
|
||||
.join(", ")
|
||||
);
|
||||
}
|
||||
},
|
||||
FrontendNotify::NotifyPortChange(port, msg) => {
|
||||
match msg {
|
||||
Some(msg) => log::info!("could not change port: {msg}"),
|
||||
None => log::info!("port changed: {port}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
prompt();
|
||||
@@ -142,6 +148,7 @@ fn parse_cmd(s: String, len: usize) -> Option<Vec<FrontendEvent>> {
|
||||
log::info!("activate <client> activate a client");
|
||||
log::info!("deactivate <client> deactivate a client");
|
||||
log::info!("exit exit lan-mouse");
|
||||
log::info!("setport <port> change port");
|
||||
None
|
||||
}
|
||||
"exit" => return Some(vec![FrontendEvent::Shutdown()]),
|
||||
@@ -150,13 +157,14 @@ fn parse_cmd(s: String, len: usize) -> Option<Vec<FrontendEvent>> {
|
||||
"disconnect" => Some(parse_disconnect(l)),
|
||||
"activate" => Some(parse_activate(l)),
|
||||
"deactivate" => Some(parse_deactivate(l)),
|
||||
"setport" => Some(parse_port(l)),
|
||||
_ => {
|
||||
log::error!("unknown command: {s}");
|
||||
None
|
||||
}
|
||||
};
|
||||
match res {
|
||||
Some(Ok(e)) => Some(vec![e, FrontendEvent::Enumerate()]),
|
||||
Some(Ok(e)) => Some(e),
|
||||
Some(Err(e)) => {
|
||||
log::warn!("{e}");
|
||||
None
|
||||
@@ -165,7 +173,7 @@ fn parse_cmd(s: String, len: usize) -> Option<Vec<FrontendEvent>> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_connect(mut l: SplitWhitespace) -> Result<FrontendEvent> {
|
||||
fn parse_connect(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
|
||||
let usage = "usage: connect <host> left|right|top|bottom [port]";
|
||||
let host = l.next().context(usage)?.to_owned();
|
||||
let pos = match l.next().context(usage)? {
|
||||
@@ -179,19 +187,25 @@ fn parse_connect(mut l: SplitWhitespace) -> Result<FrontendEvent> {
|
||||
} else {
|
||||
DEFAULT_PORT
|
||||
};
|
||||
Ok(FrontendEvent::AddClient(Some(host), port, pos))
|
||||
Ok(vec![FrontendEvent::AddClient(Some(host), port, pos), FrontendEvent::Enumerate()])
|
||||
}
|
||||
|
||||
fn parse_disconnect(mut l: SplitWhitespace) -> Result<FrontendEvent> {
|
||||
fn parse_disconnect(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
|
||||
let client = l.next().context("usage: disconnect <client_id>")?.parse()?;
|
||||
Ok(FrontendEvent::DelClient(client))
|
||||
Ok(vec![FrontendEvent::DelClient(client), FrontendEvent::Enumerate()])
|
||||
}
|
||||
|
||||
fn parse_activate(mut l: SplitWhitespace) -> Result<FrontendEvent> {
|
||||
fn parse_activate(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
|
||||
let client = l.next().context("usage: activate <client_id>")?.parse()?;
|
||||
Ok(FrontendEvent::ActivateClient(client, true))
|
||||
Ok(vec![FrontendEvent::ActivateClient(client, true), FrontendEvent::Enumerate()])
|
||||
}
|
||||
fn parse_deactivate(mut l: SplitWhitespace) -> Result<FrontendEvent> {
|
||||
|
||||
fn parse_deactivate(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
|
||||
let client = l.next().context("usage: deactivate <client_id>")?.parse()?;
|
||||
Ok(FrontendEvent::ActivateClient(client, false))
|
||||
Ok(vec![FrontendEvent::ActivateClient(client, false), FrontendEvent::Enumerate()])
|
||||
}
|
||||
|
||||
fn parse_port(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
|
||||
let port = l.next().context("usage: setport <port>")?.parse()?;
|
||||
Ok(vec![FrontendEvent::ChangePort(port)])
|
||||
}
|
||||
|
||||
@@ -145,6 +145,13 @@ fn build_ui(app: &Application) {
|
||||
);
|
||||
}
|
||||
},
|
||||
FrontendNotify::NotifyPortChange(port, msg) => {
|
||||
match msg {
|
||||
None => window.show_toast(format!("port changed: {port}").as_str()),
|
||||
Some(msg) => window.show_toast(msg.as_str()),
|
||||
}
|
||||
window.imp().set_port(port);
|
||||
}
|
||||
}
|
||||
glib::ControlFlow::Continue
|
||||
}
|
||||
|
||||
@@ -100,9 +100,19 @@ impl Window {
|
||||
|
||||
pub fn request_client_create(&self) {
|
||||
let event = FrontendEvent::AddClient(None, DEFAULT_PORT, Position::default());
|
||||
self.imp().set_port(DEFAULT_PORT);
|
||||
self.request(event);
|
||||
}
|
||||
|
||||
pub fn request_port_change(&self) {
|
||||
let port = self.imp().port_entry.get().text().to_string();
|
||||
if let Ok(port) = u16::from_str_radix(port.as_str(), 10) {
|
||||
self.request(FrontendEvent::ChangePort(port));
|
||||
} else {
|
||||
self.request(FrontendEvent::ChangePort(DEFAULT_PORT));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn request_client_update(&self, client: &ClientObject) {
|
||||
let data = client.get_data();
|
||||
let position = match data.position.as_str() {
|
||||
@@ -150,11 +160,9 @@ impl Window {
|
||||
};
|
||||
}
|
||||
|
||||
fn setup_callbacks(&self) {
|
||||
self.imp()
|
||||
.add_client_button
|
||||
.connect_clicked(clone!(@weak self as window => move |_| {
|
||||
window.request_client_create();
|
||||
}));
|
||||
pub fn show_toast(&self, msg: &str) {
|
||||
let toast = adw::Toast::new(msg);
|
||||
let toast_overlay = &self.imp().toast_overlay;
|
||||
toast_overlay.add_toast(toast);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,32 @@
|
||||
use std::{cell::{Cell, RefCell}, os::unix::net::UnixStream};
|
||||
|
||||
use glib::subclass::InitializingObject;
|
||||
use adw::{prelude::*, ActionRow};
|
||||
use adw::{ActionRow, ToastOverlay, prelude::{WidgetExt, EditableExt}};
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::{glib, Button, CompositeTemplate, ListBox, gio};
|
||||
use gtk::{glib, Button, CompositeTemplate, ListBox, gio, Entry};
|
||||
|
||||
use crate::config::DEFAULT_PORT;
|
||||
|
||||
#[derive(CompositeTemplate, Default)]
|
||||
#[template(resource = "/de/feschber/LanMouse/window.ui")]
|
||||
pub struct Window {
|
||||
pub number: Cell<i32>,
|
||||
#[template_child]
|
||||
pub port_edit_apply: TemplateChild<Button>,
|
||||
#[template_child]
|
||||
pub port_edit_cancel: TemplateChild<Button>,
|
||||
#[template_child]
|
||||
pub add_client_button: TemplateChild<Button>,
|
||||
#[template_child]
|
||||
pub client_list: TemplateChild<ListBox>,
|
||||
#[template_child]
|
||||
pub client_placeholder: TemplateChild<ActionRow>,
|
||||
#[template_child]
|
||||
pub port_entry: TemplateChild<Entry>,
|
||||
#[template_child]
|
||||
pub toast_overlay: TemplateChild<ToastOverlay>,
|
||||
pub clients: RefCell<Option<gio::ListStore>>,
|
||||
pub stream: RefCell<Option<UnixStream>>,
|
||||
pub port: Cell<u16>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
@@ -24,7 +34,7 @@ impl ObjectSubclass for Window {
|
||||
// `NAME` needs to match `class` attribute of template
|
||||
const NAME: &'static str = "LanMouseWindow";
|
||||
type Type = super::Window;
|
||||
type ParentType = gtk::ApplicationWindow;
|
||||
type ParentType = adw::ApplicationWindow;
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.bind_template();
|
||||
@@ -39,10 +49,38 @@ impl ObjectSubclass for Window {
|
||||
#[gtk::template_callbacks]
|
||||
impl Window {
|
||||
#[template_callback]
|
||||
fn handle_button_clicked(&self, button: &Button) {
|
||||
let number_increased = self.number.get() + 1;
|
||||
self.number.set(number_increased);
|
||||
button.set_label(&number_increased.to_string())
|
||||
fn handle_add_client_pressed(&self, _button: &Button) {
|
||||
self.obj().request_client_create();
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn handle_port_changed(&self, _entry: &Entry) {
|
||||
self.port_edit_apply.set_visible(true);
|
||||
self.port_edit_cancel.set_visible(true);
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn handle_port_edit_apply(&self) {
|
||||
self.obj().request_port_change();
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn handle_port_edit_cancel(&self) {
|
||||
log::debug!("cancel port edit");
|
||||
self.port_entry.set_text(self.port.get().to_string().as_str());
|
||||
self.port_edit_apply.set_visible(false);
|
||||
self.port_edit_cancel.set_visible(false);
|
||||
}
|
||||
|
||||
pub fn set_port(&self, port: u16) {
|
||||
self.port.set(port);
|
||||
if port == DEFAULT_PORT {
|
||||
self.port_entry.set_text("");
|
||||
} else {
|
||||
self.port_entry.set_text(format!("{port}").as_str());
|
||||
}
|
||||
self.port_edit_apply.set_visible(false);
|
||||
self.port_edit_cancel.set_visible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,13 +88,14 @@ impl Window {
|
||||
impl ObjectImpl for Window {
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
self.set_port(DEFAULT_PORT);
|
||||
let obj = self.obj();
|
||||
obj.setup_icon();
|
||||
obj.setup_clients();
|
||||
obj.setup_callbacks();
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetImpl for Window {}
|
||||
impl WindowImpl for Window {}
|
||||
impl ApplicationWindowImpl for Window {}
|
||||
impl AdwApplicationWindowImpl for Window {}
|
||||
|
||||
Reference in New Issue
Block a user