@bobfrankston/msger 0.1.149 → 0.1.151

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -32,13 +32,33 @@ use windows::core::PCWSTR;
32
32
  #[cfg(windows)]
33
33
  use std::sync::atomic::{AtomicBool, Ordering};
34
34
 
35
- // Custom menu ID for About item (must be < 0xF000 to avoid conflicts with system commands)
35
+ // Custom menu IDs (must be < 0xF000 to avoid conflicts with system commands)
36
36
  #[cfg(windows)]
37
37
  const IDM_ABOUT: u32 = 0x1000;
38
+ #[cfg(windows)]
39
+ const IDM_ZOOM_IN: u32 = 0x1001;
40
+ #[cfg(windows)]
41
+ const IDM_ZOOM_OUT: u32 = 0x1002;
42
+ #[cfg(windows)]
43
+ const IDM_ZOOM_RESET: u32 = 0x1003;
44
+ #[cfg(windows)]
45
+ const IDM_ZOOM_50: u32 = 0x1010;
46
+ #[cfg(windows)]
47
+ const IDM_ZOOM_75: u32 = 0x1011;
48
+ #[cfg(windows)]
49
+ const IDM_ZOOM_100: u32 = 0x1012;
50
+ #[cfg(windows)]
51
+ const IDM_ZOOM_125: u32 = 0x1013;
52
+ #[cfg(windows)]
53
+ const IDM_ZOOM_150: u32 = 0x1014;
54
+ #[cfg(windows)]
55
+ const IDM_ZOOM_200: u32 = 0x1015;
38
56
 
39
- // Global flag to signal About menu was clicked
57
+ // Global flags
40
58
  #[cfg(windows)]
41
59
  static ABOUT_CLICKED: AtomicBool = AtomicBool::new(false);
60
+ #[cfg(windows)]
61
+ static ZOOM_ACTION: std::sync::atomic::AtomicI32 = std::sync::atomic::AtomicI32::new(0);
42
62
 
43
63
  // Window subclass procedure to intercept WM_SYSCOMMAND
44
64
  #[cfg(windows)]
@@ -52,10 +72,48 @@ unsafe extern "system" fn subclass_proc(
52
72
  ) -> LRESULT {
53
73
  if msg == WM_SYSCOMMAND {
54
74
  let cmd = wparam.0 & 0xFFF0;
55
- if cmd == IDM_ABOUT as usize {
56
- // Set flag that About was clicked
57
- ABOUT_CLICKED.store(true, Ordering::SeqCst);
58
- return LRESULT(0);
75
+ match cmd as u32 {
76
+ IDM_ABOUT => {
77
+ ABOUT_CLICKED.store(true, Ordering::SeqCst);
78
+ return LRESULT(0);
79
+ }
80
+ IDM_ZOOM_IN => {
81
+ ZOOM_ACTION.store(1, Ordering::SeqCst); // Zoom in
82
+ return LRESULT(0);
83
+ }
84
+ IDM_ZOOM_OUT => {
85
+ ZOOM_ACTION.store(2, Ordering::SeqCst); // Zoom out
86
+ return LRESULT(0);
87
+ }
88
+ IDM_ZOOM_RESET => {
89
+ ZOOM_ACTION.store(100, Ordering::SeqCst); // Reset to 100%
90
+ return LRESULT(0);
91
+ }
92
+ IDM_ZOOM_50 => {
93
+ ZOOM_ACTION.store(50, Ordering::SeqCst);
94
+ return LRESULT(0);
95
+ }
96
+ IDM_ZOOM_75 => {
97
+ ZOOM_ACTION.store(75, Ordering::SeqCst);
98
+ return LRESULT(0);
99
+ }
100
+ IDM_ZOOM_100 => {
101
+ ZOOM_ACTION.store(100, Ordering::SeqCst);
102
+ return LRESULT(0);
103
+ }
104
+ IDM_ZOOM_125 => {
105
+ ZOOM_ACTION.store(125, Ordering::SeqCst);
106
+ return LRESULT(0);
107
+ }
108
+ IDM_ZOOM_150 => {
109
+ ZOOM_ACTION.store(150, Ordering::SeqCst);
110
+ return LRESULT(0);
111
+ }
112
+ IDM_ZOOM_200 => {
113
+ ZOOM_ACTION.store(200, Ordering::SeqCst);
114
+ return LRESULT(0);
115
+ }
116
+ _ => {}
59
117
  }
60
118
  }
61
119
  DefSubclassProc(hwnd, msg, wparam, lparam)
@@ -389,8 +447,22 @@ fn main() {
389
447
  let icon = if let Some(ref icon_path) = options.icon {
390
448
  load_icon(icon_path)
391
449
  } else {
392
- // Try default icon.png in current directory
393
- load_icon("icon.png")
450
+ // Try default msger.png next to the binary
451
+ if let Ok(exe_path) = std::env::current_exe() {
452
+ if let Some(exe_dir) = exe_path.parent() {
453
+ let default_icon = exe_dir.join("msger.png");
454
+ if default_icon.exists() {
455
+ load_icon(default_icon.to_str().unwrap_or("msger.png"))
456
+ } else {
457
+ // Fallback to msger.png in current directory
458
+ load_icon("msger.png")
459
+ }
460
+ } else {
461
+ load_icon("msger.png")
462
+ }
463
+ } else {
464
+ load_icon("msger.png")
465
+ }
394
466
  };
395
467
 
396
468
  let mut window_builder = WindowBuilder::new()
@@ -434,9 +506,45 @@ fn main() {
434
506
  if !hmenu.is_invalid() {
435
507
  // Add separator
436
508
  AppendMenuW(hmenu, MF_SEPARATOR, 0, PCWSTR::null()).ok();
509
+
437
510
  // Add About item
438
- let about_text: Vec<u16> = "About (Window Info)\0".encode_utf16().collect();
511
+ let about_text: Vec<u16> = "About msger (Window Info)\0".encode_utf16().collect();
439
512
  AppendMenuW(hmenu, MF_STRING, IDM_ABOUT as usize, PCWSTR(about_text.as_ptr())).ok();
513
+
514
+ // Add another separator
515
+ AppendMenuW(hmenu, MF_SEPARATOR, 0, PCWSTR::null()).ok();
516
+
517
+ // Add Zoom controls
518
+ let zoom_in: Vec<u16> = "Zoom In\tCtrl++\0".encode_utf16().collect();
519
+ AppendMenuW(hmenu, MF_STRING, IDM_ZOOM_IN as usize, PCWSTR(zoom_in.as_ptr())).ok();
520
+
521
+ let zoom_out: Vec<u16> = "Zoom Out\tCtrl+-\0".encode_utf16().collect();
522
+ AppendMenuW(hmenu, MF_STRING, IDM_ZOOM_OUT as usize, PCWSTR(zoom_out.as_ptr())).ok();
523
+
524
+ let zoom_reset: Vec<u16> = "Reset Zoom\tCtrl+0\0".encode_utf16().collect();
525
+ AppendMenuW(hmenu, MF_STRING, IDM_ZOOM_RESET as usize, PCWSTR(zoom_reset.as_ptr())).ok();
526
+
527
+ // Add separator before preset zooms
528
+ AppendMenuW(hmenu, MF_SEPARATOR, 0, PCWSTR::null()).ok();
529
+
530
+ // Add preset zoom levels
531
+ let zoom_50: Vec<u16> = "Zoom 50%\0".encode_utf16().collect();
532
+ AppendMenuW(hmenu, MF_STRING, IDM_ZOOM_50 as usize, PCWSTR(zoom_50.as_ptr())).ok();
533
+
534
+ let zoom_75: Vec<u16> = "Zoom 75%\0".encode_utf16().collect();
535
+ AppendMenuW(hmenu, MF_STRING, IDM_ZOOM_75 as usize, PCWSTR(zoom_75.as_ptr())).ok();
536
+
537
+ let zoom_100: Vec<u16> = "Zoom 100%\0".encode_utf16().collect();
538
+ AppendMenuW(hmenu, MF_STRING, IDM_ZOOM_100 as usize, PCWSTR(zoom_100.as_ptr())).ok();
539
+
540
+ let zoom_125: Vec<u16> = "Zoom 125%\0".encode_utf16().collect();
541
+ AppendMenuW(hmenu, MF_STRING, IDM_ZOOM_125 as usize, PCWSTR(zoom_125.as_ptr())).ok();
542
+
543
+ let zoom_150: Vec<u16> = "Zoom 150%\0".encode_utf16().collect();
544
+ AppendMenuW(hmenu, MF_STRING, IDM_ZOOM_150 as usize, PCWSTR(zoom_150.as_ptr())).ok();
545
+
546
+ let zoom_200: Vec<u16> = "Zoom 200%\0".encode_utf16().collect();
547
+ AppendMenuW(hmenu, MF_STRING, IDM_ZOOM_200 as usize, PCWSTR(zoom_200.as_ptr())).ok();
440
548
  }
441
549
  // Install window subclass to intercept WM_SYSCOMMAND
442
550
  let _ = SetWindowSubclass(hwnd, Some(subclass_proc), 1, 0).ok();
@@ -696,6 +804,13 @@ fn main() {
696
804
  // Check for About menu click
697
805
  #[cfg(windows)]
698
806
  if ABOUT_CLICKED.swap(false, Ordering::SeqCst) {
807
+ // Get current zoom from the page
808
+ let zoom_script = "document.body.style.zoom || '100%'";
809
+ let current_zoom = match webview.evaluate_script(zoom_script) {
810
+ Ok(_) => "100%".to_string(), // Default if can't get it
811
+ Err(_) => "100%".to_string(),
812
+ };
813
+
699
814
  // Get window information
700
815
  let position = window_clone.outer_position().unwrap_or_default();
701
816
  let inner_size = window_clone.inner_size();
@@ -712,27 +827,29 @@ fn main() {
712
827
  let logical_outer_height = (outer_size.height as f64 / scale_factor) as i32;
713
828
 
714
829
  let info = format!(
715
- "Window Information\\n\\n\
716
- Position: x={}, y={}\\n\\n\
830
+ "msger v{}\\n\\n\
831
+ Rust/wry-based message viewer\\n\\n\
832
+ Position: x={}, y={}\\n\
717
833
  Logical Size (API): {}x{} inner\\n\
718
834
  Physical Size (Screen): {}x{} inner\\n\
719
835
  Outer Size (Physical): {}x{}\\n\
720
836
  Outer Size (Logical): {}x{}\\n\\n\
837
+ Current Zoom: {}\\n\
721
838
  Scale Factor: {:.2} ({}% DPI)\\n\
722
839
  Maximized: {}\\n\
723
840
  Fullscreen: {}\\n\
724
- Always On Top: {}\\n\\n\
725
- Version: {}",
841
+ Always On Top: {}",
842
+ get_package_version().unwrap_or_else(|| "unknown".to_string()),
726
843
  position.x, position.y,
727
844
  logical_inner_width, logical_inner_height,
728
845
  inner_size.width, inner_size.height,
729
846
  outer_size.width, outer_size.height,
730
847
  logical_outer_width, logical_outer_height,
848
+ current_zoom,
731
849
  scale_factor, (scale_factor * 100.0) as i32,
732
850
  is_maximized,
733
851
  is_fullscreen,
734
- is_always_on_top,
735
- get_package_version().unwrap_or_else(|| "unknown".to_string())
852
+ is_always_on_top
736
853
  );
737
854
 
738
855
  // Show the info in an alert
@@ -742,6 +859,32 @@ fn main() {
742
859
  }
743
860
  }
744
861
 
862
+ // Check for zoom menu actions
863
+ #[cfg(windows)]
864
+ {
865
+ let zoom_action = ZOOM_ACTION.swap(0, Ordering::SeqCst);
866
+ if zoom_action != 0 {
867
+ let zoom_script = match zoom_action {
868
+ 1 => {
869
+ // Zoom in - get current and increase by 25%
870
+ "var currentZoom = parseFloat(document.body.style.zoom || '100'); document.body.style.zoom = (currentZoom + 25) + '%';"
871
+ }
872
+ 2 => {
873
+ // Zoom out - get current and decrease by 25%
874
+ "var currentZoom = parseFloat(document.body.style.zoom || '100'); document.body.style.zoom = Math.max(25, currentZoom - 25) + '%';"
875
+ }
876
+ percent => {
877
+ // Set specific zoom level
878
+ &format!("document.body.style.zoom = '{}%';", percent)
879
+ }
880
+ };
881
+
882
+ if let Err(e) = webview.evaluate_script(zoom_script) {
883
+ eprintln!("Failed to set zoom: {}", e);
884
+ }
885
+ }
886
+ }
887
+
745
888
  // Check timeout
746
889
  if let Some(deadline) = timeout_instant {
747
890
  if std::time::Instant::now() >= deadline {
package/msger.png ADDED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/msger",
3
- "version": "0.1.149",
3
+ "version": "0.1.151",
4
4
  "description": "Fast, lightweight, cross-platform message box - Rust-powered alternative to msgview",
5
5
  "type": "module",
6
6
  "main": "./index.js",