summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2025-02-17 13:54:37 +0100
committerDavid Lönnhager <david.l@mullvad.net>2025-03-05 23:32:06 +0100
commit7afe2c6ce0bf6cbb3c0e6c8526a1b694fed8acd0 (patch)
tree4e3308256d2ed3d554a54fd1994302389425f801
parent3a5f0a53c2f93f125417f9f1aa1ad9a68cffb05b (diff)
downloadmullvadvpn-7afe2c6ce0bf6cbb3c0e6c8526a1b694fed8acd0.tar.xz
mullvadvpn-7afe2c6ce0bf6cbb3c0e6c8526a1b694fed8acd0.zip
Add arrow to 'stable link' on Windows
-rw-r--r--installer-downloader/src/winapi_impl/delegate.rs15
-rw-r--r--installer-downloader/src/winapi_impl/ui.rs51
2 files changed, 55 insertions, 11 deletions
diff --git a/installer-downloader/src/winapi_impl/delegate.rs b/installer-downloader/src/winapi_impl/delegate.rs
index 69176cf897..da2e5ca317 100644
--- a/installer-downloader/src/winapi_impl/delegate.rs
+++ b/installer-downloader/src/winapi_impl/delegate.rs
@@ -35,7 +35,7 @@ impl AppDelegate for AppWindow {
where
F: Fn() + Send + 'static,
{
- register_label_click_handler(self.window.handle, self.stable_link.handle, callback);
+ register_frame_click_handler(self.stable_message_frame.handle, callback);
}
fn set_status_text(&mut self, text: &str) {
@@ -106,11 +106,11 @@ impl AppDelegate for AppWindow {
}
fn show_stable_text(&mut self) {
- self.stable_link.set_visible(true);
+ self.stable_message_frame.set_visible(true);
}
fn hide_stable_text(&mut self) {
- self.stable_link.set_visible(false);
+ self.stable_message_frame.set_visible(false);
}
fn quit(&mut self) {
@@ -156,6 +156,15 @@ fn register_click_handler_inner(
});
}
+/// Register a window message for clicking anything within a frame.
+fn register_frame_click_handler(frame: nwg::ControlHandle, callback: impl Fn() + 'static) {
+ nwg::bind_event_handler(&frame, &frame, move |evt, _, _handle| {
+ if [Event::OnLabelClick, Event::OnImageFrameClick].contains(&evt) {
+ callback();
+ }
+ });
+}
+
/// Queue sends a window message to the main window containing a [QueueContext], giving us mutable
/// access to the [AppDelegate] on the main UI thread.
///
diff --git a/installer-downloader/src/winapi_impl/ui.rs b/installer-downloader/src/winapi_impl/ui.rs
index f53d00dccd..bd5589beca 100644
--- a/installer-downloader/src/winapi_impl/ui.rs
+++ b/installer-downloader/src/winapi_impl/ui.rs
@@ -33,6 +33,8 @@ pub const SET_LABEL_HANDLER_ID: usize = 0x10000;
pub const QUEUE_MESSAGE_HANDLER_ID: usize = 0x10001;
/// Custom window message used to process requests from other threads.
pub const QUEUE_MESSAGE: u32 = 0x10001;
+/// Unique ID of the handler for the stable link prefix.
+pub const STABLE_LINK_PREFIX_HANDLER_ID: usize = 0x10004;
/// Unique ID of the handler for the stable link.
pub const STABLE_LINK_HANDLER_ID: usize = 0x10003;
/// Unique ID of the handler for the beta link.
@@ -60,6 +62,11 @@ pub struct AppWindow {
pub beta_prefix: nwg::Label,
pub beta_link: nwg::Label,
+
+ pub arrow_font: nwg::Font,
+
+ pub stable_message_frame: nwg::ImageFrame,
+ pub stable_prefix: nwg::Label,
pub stable_link: nwg::Label,
}
@@ -136,14 +143,30 @@ impl AppWindow {
.h_align(nwg::HTextAlign::Left)
.build(&mut self.beta_link)?;
- nwg::Label::builder()
+ nwg::ImageFrame::builder()
.parent(&self.window)
.size((240, 24))
+ .build(&mut self.stable_message_frame)?;
+
+ nwg::Font::builder()
+ // TODO: Ensure font always exists
+ .family("Segoe Fluent Icons")
+ .size(10)
+ .build(&mut self.arrow_font)?;
+ nwg::Label::builder()
+ .parent(&self.stable_message_frame)
+ .size((16, 24))
+ .text("")
+ .font(Some(&self.arrow_font))
+ .h_align(nwg::HTextAlign::Left)
+ .build(&mut self.stable_prefix)?;
+ nwg::Label::builder()
+ .parent(&self.stable_message_frame)
+ .size((240, 24))
.text(STABLE_LINK_TEXT)
.font(Some(&link_font))
.h_align(nwg::HTextAlign::Left)
.build(&mut self.stable_link)?;
- self.stable_link.set_visible(false);
const PROGRESS_BAR_MARGIN: i32 = 48;
nwg::ProgressBar::builder()
@@ -183,11 +206,23 @@ impl AppWindow {
+ LOWER_AREA_YPADDING,
);
- self.stable_link.set_position(
+ self.stable_message_frame.set_position(
24,
- self.window.size().1 as i32 - 24 - self.stable_link.size().1 as i32,
+ self.window.size().1 as i32 - 24 - self.stable_message_frame.size().1 as i32,
);
- handle_link_messages(&self.window, &self.stable_link, STABLE_LINK_HANDLER_ID)?;
+ self.stable_link.set_position(16, 0);
+ self.stable_prefix.set_position(4, 12 - 4);
+ handle_link_messages(
+ &self.stable_message_frame.handle,
+ &self.stable_prefix,
+ STABLE_LINK_PREFIX_HANDLER_ID,
+ )?;
+ handle_link_messages(
+ &self.stable_message_frame.handle,
+ &self.stable_link,
+ STABLE_LINK_HANDLER_ID,
+ )?;
+
self.beta_prefix.set_position(
24,
self.window.size().1 as i32 - 24 - self.beta_prefix.size().1 as i32,
@@ -196,7 +231,7 @@ impl AppWindow {
self.beta_prefix.position().0 + self.beta_prefix.size().0 as i32,
self.beta_prefix.position().1,
);
- handle_link_messages(&self.window, &self.beta_link, BETA_LINK_HANDLER_ID)?;
+ handle_link_messages(&self.window.handle, &self.beta_link, BETA_LINK_HANDLER_ID)?;
self.window.set_visible(true);
@@ -299,12 +334,12 @@ fn handle_banner_label_colors(
/// Register a window message handler for the beta link component
fn handle_link_messages(
- parent: &nwg::Window,
+ parent: &nwg::ControlHandle,
link: &nwg::Label,
handler_id: usize,
) -> Result<nwg::RawEventHandler, nwg::NwgError> {
let link_hwnd = link.handle.hwnd().map(|hwnd| hwnd as isize);
- nwg::bind_raw_event_handler(&parent.handle, handler_id, move |_hwnd, msg, w, p| {
+ nwg::bind_raw_event_handler(&parent, handler_id, move |_hwnd, msg, w, p| {
/// This is the RGB() macro except it takes in a slice representing RGB values
pub fn rgb(color: [u8; 3]) -> COLORREF {
color[0] as COLORREF | ((color[1] as COLORREF) << 8) | ((color[2] as COLORREF) << 16)