ahkohd / tauri-toolkit

A workspace of libraries and plugins for @tauri-apps
Apache License 2.0
24 stars 2 forks source link

lib:border - del_border + does not work with “acceptFirstMouse”: true #141

Open doroved opened 1 month ago

doroved commented 1 month ago

Hi Victor, can you tell me how to delete a border? The current solution doesn't work

        if data.is_pinned {
            window.add_border(Some(BorderConfig {
                line_width: 3.0,
                line_color: Color(36, 211, 238, 255),
                inset: 0.0,
                corner_radius: 12.0,
            }));
            window.border().unwrap().set_auto_resizing();
        } else {
            window.add_border(None);
        }

And it seems set_auto_resizing doesn't work, even if you specify it manually, border overlaps content if you specify for example line_width: 10.0.

Found another problem, "acceptFirstMouse": true stops working after setting add_border. Looks like use tauri::Color; is not the correct use, use tauri::window::Color;.

ahkohd commented 1 month ago

I added two new functions, BorderView.remove() & BorderView.set_accepts_first_mouse(value: bool).

See the PR: https://github.com/ahkohd/tauri-toolkit/pull/149

usage:

let border = window.border().expect("window has no border");

// to accept the first mouse click
border.set_accepts_first_mouse(true);

// to remove the border from the parent view
border.remove();

I have renamed the tauri::Color type to tauri::window::Color in the documentation.

ahkohd commented 1 month ago

Let me know if this resolves your issue. Thank you.

doroved commented 1 month ago

Let me know if this resolves your issue. Thank you.

I tried different options but couldn't get this to work inside window.listen, if you use window_clone you get this error

thread 'tokio-runtime-worker' panicked at src/main.rs:507:44:
window has no border

If you set the border inside window.listen, it works incorrectly and at each triggering event parameters of color, thickness, etc. are not set, set_accepts_first_mouse triggers only the first time, then stops, apparently because of the repeated setting there is a conflict.

fn switch_to_panel(app_handle: &AppHandle) {
    let window = app_handle.get_webview_window("main").unwrap();
    let panel = window.to_panel().unwrap();

    let delegate = panel_delegate!(MyPanelDelegate {
        window_did_become_key,
        window_did_resign_key,
    });

    window.add_border(None);
    let border = window.border().expect("window has no border");
    border.set_accepts_first_mouse(true);

    let window_clone = window.clone();

    window.listen("window:pin:toggle", move |event| {
        let border = window_clone.border().expect("window has no border");

        if data.is_pinned {
            border.set_accepts_first_mouse(true);
            border.set_line_width(3.0);
            border.set_line_color(Color(36, 211, 238, 255));
            border.set_inset(0.0);
            border.set_corner_radius(12.0);
        } else {
            border.remove();
        }

    }
....
ahkohd commented 1 month ago

try and send it to the main thread. do all the window appearance stuff on the main thread:

app_handle.run_on_main_thread()
doroved commented 1 month ago

try and send it to the main thread. do all the window appearance stuff on the main thread:

app_handle.run_on_main_thread()

I'm not quite sure where to use it

ahkohd commented 1 month ago

try and send it to the main thread. do all the window appearance stuff on the main thread:

app_handle.run_on_main_thread()

I'm not quite sure where to use it

let handle = app_handle.clone();

 window.listen("window:pin:toggle", move |event| {
let app_handle = handle.clone();

handle.run_on_main_thread(move || {
let window = app_handle.get_webview_window("window name" );

  let border = window.border().expect("window has no border");

        if data.is_pinned {
            border.set_accepts_first_mouse(true);
            border.set_line_width(3.0);
            border.set_line_color(Color(36, 211, 238, 255));
            border.set_inset(0.0);
            border.set_corner_radius(12.0);
        } else {
            border.remove();
        }
});

    }

roughly like that. inside the window:pin:toggle callback, call app_handle.run_on_main_thread() passing the border stuffs as into it's fn arg

doroved commented 1 month ago

try and send it to the main thread. do all the window appearance stuff on the main thread:

app_handle.run_on_main_thread()

I'm not quite sure where to use it

let handle = app_handle.clone();

 window.listen("window:pin:toggle", move |event| {
let app_handle = handle.clone();

handle.run_on_main_thread(move || {
let window = app_handle.get_webview_window("window name" );

  let border = window.border().expect("window has no border");

        if data.is_pinned {
            border.set_accepts_first_mouse(true);
            border.set_line_width(3.0);
            border.set_line_color(Color(36, 211, 238, 255));
            border.set_inset(0.0);
            border.set_corner_radius(12.0);
        } else {
            border.remove();
        }
});

    }

roughly like that. inside the window:pin:toggle callback, call app_handle.run_on_main_thread() passing the border stuffs as into it's fn arg

It works only once, then at each event instead of the set color, the border is layered with gray color, I think there is a conflict because at each event the border is added window.add_border(None);.

ahkohd commented 1 month ago

Since I don't have a clear picture of your code, I can suggest how I think it should work:

  1. Call window.add_border once with Some(config). In this config, set your border size and make the border transparent.
  2. In your window:pin:toggle, get the window's border and set the color to your desired solid color.
  3. Instead of removing the border, simply revert the color back to transparent.
ahkohd commented 1 month ago

Also, keep in mind that the border.remove() function removes the border from the window's content view. However, it still exists, and you can assign it to a new parent.

image image
ahkohd commented 1 month ago

you can always check if border already exits to prevent adding duplicates:

if window.border().is_none() {
   // add your border
    window.add_border(None);
}
ahkohd commented 1 month ago

Reading how it works may help you understand:

image

Let me know how it goes.

doroved commented 1 month ago

you can always check if border already exits to prevent adding duplicates:

if window.border().is_none() {
   // add your border
    window.add_border(None);
}

Yes, this option works, thanks. Only it seems set_auto_resizing doesn't work because the border overlaps the content.

        let app_handle = handle.clone();

        let _ = handle.run_on_main_thread(move || {
            let window = app_handle.get_webview_window("main").unwrap();

            if window.border().is_none() {
                window.add_border(None);
            }

            let border = window.border().expect("window has no border");
            border.set_accepts_first_mouse(true);

            if data.is_pinned {
                border.set_line_width(5.0);
                border.set_line_color(Color(36, 211, 238, 255));
                border.set_inset(0.0);
                border.set_corner_radius(12.0);
                border.set_auto_resizing();
            } else {
                border.remove();
            }
        });
ahkohd commented 1 month ago

you can always check if border already exits to prevent adding duplicates:

if window.border().is_none() {
   // add your border
    window.add_border(None);
}

Yes, this option works, thanks. Only it seems set_auto_resizing doesn't work because the border overlaps the content.

        let app_handle = handle.clone();

        let _ = handle.run_on_main_thread(move || {
            let window = app_handle.get_webview_window("main").unwrap();

            if window.border().is_none() {
                window.add_border(None);
            }

            let border = window.border().expect("window has no border");
            border.set_accepts_first_mouse(true);

            if data.is_pinned {
                border.set_line_width(5.0);
                border.set_line_color(Color(36, 211, 238, 255));
                border.set_inset(0.0);
                border.set_corner_radius(12.0);
                border.set_auto_resizing();
            } else {
                border.remove();
            }
        });

remove the border.remove() line, instead set the color to transparent.

ahkohd commented 1 month ago

Since I don't have a clear picture of your code, I can suggest how I think it should work:

  1. Call window.add_border once with Some(config). In this config, set your border size and make the border transparent.
  2. In your window:pin:toggle, get the window's border and set the color to your desired solid color.
  3. Instead of removing the border, simply revert the color back to transparent.

this.

ahkohd commented 1 month ago

I can implement a border.destroy() method. which will call border.remove() and destroy the border view.

doroved commented 1 month ago

I can implement a border.destroy() method. which will call border.remove() and destroy the border view.

This one will be better.

ahkohd commented 1 month ago

I can implement a border.destroy() method. which will call border.remove() and destroy the border view.

This one will be better.

well, but not really, it's better to reuse objects than to create and destroy them every time.

ahkohd commented 1 month ago

I can implement a border.destroy() method. which will call border.remove() and destroy the border view.

image

Here is the implementation, I haven't tested it.

ahkohd commented 1 month ago

Here is the commit https://github.com/ahkohd/tauri-toolkit/commit/44e3d9ff7670a83d27f9cab29306d1dcc18b335f. Help test it. Let me know how it goes.

run cargo update -p border

doroved commented 1 month ago

this.

If you remove border.remove(); the border stops being set at all, border.set_line_color(Color(36, 211, 238, 0)); solves nothing in this case.

ahkohd commented 1 month ago

this.

If you remove border.remove(); the border stops being set at all, border.set_line_color(Color(36, 211, 238, 0)); solves nothing in this case.

I'm not sure how your setup is. However, I think you should only call window.add_border once!, when you create the window. Configure it's color to transparent at that point. When you pin your panel, change the color to a solid color. When you unpin it, set it back to transparent. I see no need for remove/destroy unless I'm missing something.

doroved commented 1 month ago

this.

If you remove border.remove(); the border stops being set at all, border.set_line_color(Color(36, 211, 238, 0)); solves nothing in this case.

I'm not sure how your setup is. However, I think you should only call window.add_border once!, when you create the window. Configure it's color to transparent at that point. When you pin your panel, change the color to a solid color. When you unpin it, set it back to transparent. I see no need for remove/destroy unless I'm missing something.

The color change just refuses to work. Only the initial border is set.set_line_color(Color(36, 211, 238, 255));


            let window = app_handle.get_webview_window("main").unwrap();
            window.add_border(None);
            let border = window.border().expect("window has no border");
            border.set_accepts_first_mouse(true);
            border.set_line_width(5.0);
            border.set_line_color(Color(36, 211, 238, 255));
            border.set_inset(0.0);
            border.set_corner_radius(12.0);
            border.set_auto_resizing();

            switch_to_panel(app_handle);
            setup_shortcut(app_handle);

            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("unable to run Tauri application");
...
        let app_handle = handle.clone();

        let _ = handle.run_on_main_thread(move || {
            let window = app_handle.get_webview_window("main").unwrap();

            let border = window.border().expect("window has no border");

            if data.is_pinned {
                border.set_line_color(Color(36, 111, 111, 111));
            } else {
               border.set_line_color(Color(56, 67, 145, 123));
            }
        });
ahkohd commented 1 month ago

this.

If you remove border.remove(); the border stops being set at all, border.set_line_color(Color(36, 211, 238, 0)); solves nothing in this case.

I'm not sure how your setup is. However, I think you should only call window.add_border once!, when you create the window. Configure it's color to transparent at that point. When you pin your panel, change the color to a solid color. When you unpin it, set it back to transparent. I see no need for remove/destroy unless I'm missing something.

The color change just refuses to work. Only the initial border is set.set_line_color(Color(36, 211, 238, 255));


            let window = app_handle.get_webview_window("main").unwrap();
            window.add_border(None);
            let border = window.border().expect("window has no border");
            border.set_accepts_first_mouse(true);
            border.set_line_width(5.0);
            border.set_line_color(Color(36, 211, 238, 255));
            border.set_inset(0.0);
            border.set_corner_radius(12.0);
            border.set_auto_resizing();

            switch_to_panel(app_handle);
            setup_shortcut(app_handle);

            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("unable to run Tauri application");
...
        let app_handle = handle.clone();

        let _ = handle.run_on_main_thread(move || {
            let window = app_handle.get_webview_window("main").unwrap();

            let border = window.border().expect("window has no border");

            if data.is_pinned {
                border.set_line_color(Color(36, 111, 111, 111));
            } else {
               border.set_line_color(Color(56, 67, 145, 123));
            }
        });

I'll play around with this to see what's wrong.

ahkohd commented 16 hours ago

I will take a look this weekend!