tauri-apps / tauri

Build smaller, faster, and more secure desktop and mobile applications with a web frontend.
https://tauri.app
Apache License 2.0
84.7k stars 2.55k forks source link

[bug] Cannot set window position correctly between monitors for tray #7139

Open kadiryazici opened 1 year ago

kadiryazici commented 1 year ago

Describe the bug

I have a menubar app, as expected when user clicks on tray icon app places itself correctly but if the user has dual monitor tray click gives correct position but window.set_position cannot place the window correctly for first 1 or 2 clicks.

Sorry for phone recording but couldn't find a way to record multiple monitors.

https://github.com/tauri-apps/tauri/assets/47540799/d2f7a290-51e3-416b-89ba-06c015ed6382

Reproduction

fn handle_system_tray_event(app: &AppHandle, event: SystemTrayEvent) {
    let window = app.get_window("main").unwrap();

    if let SystemTrayEvent::LeftClick { position, .. } = event {
        window.show().unwrap();
        window.set_focus().unwrap();
        window.set_position(position);
    }
}

The code above is used for the video, actual code is in the following link: https://github.com/Gitification-App/gitification/blob/main/src-tauri/src/main.rs#L24-L52

Expected behavior

No response

Platform and versions

Environment
  › OS: Mac OS 13.3.1 X64
  › Node.js: 18.15.0
  › npm: 9.5.0
  › pnpm: 8.6.0
  › yarn: 1.22.18
  › rustup: 1.25.1
  › rustc: 1.67.0
  › cargo: 1.67.0
  › Rust toolchain: stable-aarch64-apple-darwin 

Packages
  › @tauri-apps/cli [NPM]: 1.2.3 (outdated, latest: 1.3.1)

Stack trace

No response

Additional context

No response

tanzim commented 1 year ago

I can confirm that I see exactly the same issue on a multi-monitor setup on macOS 13.4.1, Tauri 1.4 and window-state plug-in v1. Here's the relevant snippet that works fine for showing/hiding on a single monitor setup.

pub fn handle_event(app: &AppHandle, event: SystemTrayEvent) {
    let win = app.get_window("main").unwrap();
    match event {
        SystemTrayEvent::LeftClick { .. } => {
            if win.is_visible().unwrap() {
                win.hide().unwrap();
            } else {
                win.move_window(Position::TrayCenter).unwrap();
                win.show().unwrap();
                win.set_focus().unwrap();
            }
        }
reslear commented 1 year ago

same issue but it doesn't show on the laptop at all, only on the monitor

pronebird commented 7 months ago

On tauri v2 beta the plug-in craps out with panic if I don't initialize it despite what the docs say. Even after initializing it and calling tauri_plugin_positioner::on_tray_event, the call to win.move_window(Position::TrayBottomCenter) puts window into seemingly random position somewhere on the left hand side of screen.

.on_tray_icon_event(move |tray_icon, event| {
  tauri_plugin_positioner::on_tray_event(tray_icon.app_handle(), &event);
  let win = tray_icon.app_handle().get_window("main").unwrap();
  let _ = win.move_window(Position::TrayBottomCenter);
})
dolev146 commented 1 month ago

I solved it with this

// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use tauri::{Manager, PhysicalPosition, PhysicalSize};

fn main() {
  tauri::Builder::default()
  .setup(|app| {
    let win = app.get_window("main").unwrap();

  // Get available monitors
  let available_monitors = win.available_monitors().expect("Failed to get monitors");

      // Check if monitor 2 exists (index 1)
      if available_monitors.len() > 1 {
        // destinationMonitorId = 0 and max_x = available_monitors[destinationMonitorId].x
        // loop over monitors from 1 to len of monitors 
        // compare the x of each monitor with the maxX and 
        // if the new X is bigger than the current maxX then replace it and modify the destination monitor id
        let mut destination_monitor_id = 0;
        let mut max_x = available_monitors[destination_monitor_id].position().x;
        for (index, monitor) in available_monitors.iter().enumerate() {
          if monitor.position().x > max_x {
              max_x = monitor.position().x;
              destination_monitor_id = index;
          }
      }

        let monitor = &available_monitors[destination_monitor_id];
        let monitor_position = monitor.position();
        let monitor_size = monitor.size();

        // Move window to the selected monitor
        win.set_position(PhysicalPosition::new(monitor_position.x, monitor_position.y)).expect("Failed to move window");

        // Optionally resize the window to fit the new monitor
        win.set_size(PhysicalSize::new(monitor_size.width, monitor_size.height)).expect("Failed to resize window");
        win.maximize().expect("Failed to maximize window");
      } else {
        eprintln!("Monitor 2 not found!");
      }

      // Show the window after positioning
      win.show().expect("Failed to show window");

    Ok(())
})
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

and this

    "windows": [
      {
        "fullscreen": false,
        "closable": true,
        "title": "HaGuide",
        "visible": false,
        "url": "index.html",
        "fileDropEnabled": false,
        "maximized": true,
        "alwaysOnTop": true,
        "focus": true
      }
    ]
  }