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.56k stars 2.54k forks source link

[feat] [macOS] Configure `acceptsFirstMouse` for specific elements #4316

Open probablykasper opened 2 years ago

probablykasper commented 2 years ago

Describe the bug

Elements with data-tauri-drag-region can't be dragged while the window isn't in focus, which is not how native windows (or Electron's implementation) works

Note: acceptsFirstMouse doesn't entirely solve this because that would also make everything in the window clickable

Reproduction

No response

Expected behavior

No response

Platform and versions

Environment
  › OS: Mac OS 10.15.7 X64
  › Node.js: 16.15.0
  › npm: 8.12.1
  › pnpm: Not installed!
  › yarn: Not installed!
  › rustup: 1.24.3
  › rustc: 1.61.0
  › cargo: 1.61.0
  › Rust toolchain: stable-x86_64-apple-darwin 

Packages
  › @tauri-apps/cli [NPM]: 1.0.0-rc.12 (outdated, latest: 1.0.0-rc.13)
  › @tauri-apps/api [NPM]: 1.0.0-rc.6
  › tauri [RUST]: git+https://github.com/tauri-apps/tauri?branch=mac-app-hide#ade64c9b1695043c40ffccb3a38b11d1a7f1b6bb (1.0.0-rc.12),
  › tauri-build [RUST]: 1.0.0-rc.10,
  › tao [RUST]: 0.9.1,
  › wry [RUST]: 0.17.0,

App
  › build-type: bundle
  › CSP: default-src 'self'; img-src *
  › distDir: ../build
  › devPath: http://localhost:9000/
  › framework: Svelte

App directory structure
  ├─ node_modules
  ├─ public
  ├─ .github
  ├─ src-tauri
  ├─ build
  ├─ .git
  ├─ assets
  └─ src

Stack trace

No response

Additional context

No response

lhf6623 commented 2 years ago

I have this problem too,And Gaussian blur doesn't work when you lose focus

dceddia commented 2 years ago

I ran into this too. I thought it might have something to do with the acceptsFirstMouse method.

It looks like at least tao is overriding that to be true here so it's probably taken care of at the window level, but I'm wondering if maybe it needs to be overridden for the WKWebView too. It looks like Electron overrides this:

This allows Electron to override acceptsFirstMouse on Mac so that windows can respond to the first mouse click in their window, which is desirable for some kinds of utility windows.

It looks like wry already has a WryWebView that subclasses WKWebView and that might be a good place to put this override. It would be overzealous though, and then filtering of mouse clicks would need to happen somewhere or we'd end up in the reverse situation where the window shouldn't respond to the first mouse click in a lot of situations. I guess ideally it would be up to the application whether it accepts those clicks, but I'm not sure where that would go.

probablykasper commented 2 years ago

Enabling acceptsFirstMouse would technically fix it, but then you get unconventional behavior (although some Electron apps do this)

If we're able to detect the first mouse click position, we would be able to forward it to the frontend to decide if the window should be dragged

dceddia commented 2 years ago

If it were special-cased for only data-tauri-drag-region I think it'd break strategies like this one that make most of the window draggable, which would be a bummer. Maybe it could be made into an option, and do something like...

I think a system like that would still let the developer do their custom startDragging code, and also allow breaking convention for apps where that's desirable. From Apple's acceptsFirstMouse docs it sounds like the convention is to pass firstMouse through for certain types of elements, too. Just as a random example I notice that Chrome passes firstMouse through if you click on a browser tab, but not to elements on the page. It'd be neat to have that level of control in Tauri too.

probablykasper commented 2 years ago

If it were special-cased for only data-tauri-drag-region I think it'd break strategies like this one that make most of the window draggable, which would be a bummer. Maybe it could be made into an option, and do something like...

I think the solution there is to have data-tauri-drag-region="self" that applies only to the element itself, not children

amrbashir commented 2 years ago

/upstream tauri-apps/tao

tauri-apps[bot] commented 2 years ago

Upstream issue at https://github.com/tauri-apps/tao/issues/575 has been closed.

amrbashir commented 2 years ago

/upstream tauri-apps/wry

tauri-apps[bot] commented 2 years ago

Upstream issue at https://github.com/tauri-apps/wry/issues/714 has been closed.

probablykasper commented 2 years ago

Opened #5347 for exposing acceptsFirstMouse

amrbashir commented 2 years ago

/upstream tauri-apps/wry

xyhcode commented 2 months ago

Setting acceptFirstMouse to true will not allow drag on Macs

    decorations: false,
    transparent: true,
GafelSon commented 1 month ago

I'm not entirely sure if this solution will work for everyone, but it successfully resolved the issue in my case. The problem I was encountering involved dragging a window in a Tauri app on macOS, particularly when using the titleBarStyle: Overlay option, where dragging was not functioning as expected. !(Tauri + next.js)

But, through some trial and error (mostly error), I came up with this temporary hack...I mean, solution!

[dependencies]
tauri = { version = "1.7.2", features = ["macos-private-api", "api-all"] }

The macos-private-api and api-all features enable the macOS private APIs needed for handling native behavior more flexibly.

  1. Configure tauri.config.json In your tauri.config.json file, make sure to allow necessary permissions and enable dragging behavior with the startDragging option. Additionally, you can configure window properties, including the titleBarStyle set to Overlay.
{
  "tauri": {
    "allowlist": {
      "all": true,
      "window": {
        "startDragging": true
      }
    },
    "macOSPrivateApi": true,
    "windows": [
      {
        "fullscreen": false,
        "resizable": false,
        "height": 600,
        "width": 410,
        "title": "",
        "titleBarStyle": "Overlay"
      }
    ]
  }
}
  1. Implement TitleBarHandler This is the main logic for setting up the drag region. When the mouse is within the top 50px of the window, the drag region is activated. This allows the window to be draggable, mimicking the behavior of native macOS windows:
"use client";

import { useEffect } from "react";

const TitleBarHandler = () => {
  useEffect(() => {
    const handleMouseMove = (event) => {
      if (event.clientY >= 0 && event.clientY <= 50) {
        document.documentElement.setAttribute("data-tauri-drag-region", "true");
      } else {
        document.documentElement.removeAttribute("data-tauri-drag-region");
      }
    };

    window.addEventListener("mousemove", handleMouseMove);

    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
      document.documentElement.removeAttribute("data-tauri-drag-region"); // Clean up when unmounting
    };
  }, []);

  return null; // No need to render anything for the title bar
};

export default TitleBarHandler;
  1. Handling Title Bar in React In your React component, you can create a custom handler to manage the drag region. For example, I imported a TitleBarHandler component that will handle the mouse move events and set the drag region dynamically based on the mouse position:
import TitleBarHandler from "../components/titleBarHandler";

export default function RootLayout({ children }) {
  return (
    <html lang='en'>
      <body>
        <TitleBarHandler /> {/* Import handler */}
        {children}
      </body>
    </html>
  );
}
.titlebar {
  height: 50px;
  user-select: none;
  display: flex;
  justify-content: flex-end;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}
.titlebar-button {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  width: 30px;
  height: 30px;
}
nyssance commented 1 month ago

我不确定这个解决方案是否适用于所有者,但它成功解决了我的问题。我完全遇到的问题涉及 macOS 上的 Tauri 应用程序中的拖动窗口,特别是在使用该titleBarStyle: Overlay选项时,拖动功能无法按预期运行。!(Tauri + next.js)

但是,通过反复试验(大部分是错误),我想出了这个临时解决办法……我的意思是,解决方案!

[dependencies]
tauri = { version = "1.7.2", features = ["macos-private-api", "api-all"] }

macos-private-api和功能api-all使处理本机所需的 macOS 真空 API 更加灵活。

  1. 配置tauri.config.json 在您的tauri.config.json文件中,确保允许必要的权限并使用startDragging选项启用拖动行为。此外,您可以配置窗口属性,包括设置titleBarStyleOverlay
{
  "tauri": {
    "allowlist": {
      "all": true,
      "window": {
        "startDragging": true
      }
    },
    "macOSPrivateApi": true,
    "windows": [
      {
        "fullscreen": false,
        "resizable": false,
        "height": 600,
        "width": 410,
        "title": "",
        "titleBarStyle": "Overlay"
      }
    ]
  }
}
  1. 这是允许设置拖动区域的主要逻辑。当鼠标位于窗口顶部 50px 内时,拖动区域被激活。这个窗口TitleBarHandler 可拖动,实现复制 macOS 窗口的行为:
"use client";

import { useEffect } from "react";

const TitleBarHandler = () => {
  useEffect(() => {
    const handleMouseMove = (event) => {
      if (event.clientY >= 0 && event.clientY <= 50) {
        document.documentElement.setAttribute("data-tauri-drag-region", "true");
      } else {
        document.documentElement.removeAttribute("data-tauri-drag-region");
      }
    };

    window.addEventListener("mousemove", handleMouseMove);

    return () => {
      window.removeEventListener("mousemove", handleMouseMove);
      document.documentElement.removeAttribute("data-tauri-drag-region"); // Clean up when unmounting
    };
  }, []);

  return null; // No need to render anything for the title bar
};

export default TitleBarHandler;
  1. 在 React 中标题处理栏 在 React 组件中,您可以创建自定义处理程序来管理拖动区域。例如,我导入了一个TitleBarHandler组件,将处理鼠标移动事件并根据鼠标位置动态设置拖动区域:
import TitleBarHandler from "../components/titleBarHandler";

export default function RootLayout({ children }) {
  return (
    <html lang='en'>
      <body>
        <TitleBarHandler /> {/* Import handler */}
        {children}
      </body>
    </html>
  );
}
.titlebar {
  height: 50px;
  user-select: none;
  display: flex;
  justify-content: flex-end;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}
.titlebar-button {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  width: 30px;
  height: 30px;
}

How to work with Tauri 2.0?

ericschmar commented 4 weeks ago

https://github.com/tauri-apps/tauri/issues/4316#issuecomment-2339994215

This configuration isn't compatible with Tauri v2.0 however the issue is persistent. Any ideas?

GafelSon commented 3 weeks ago

#4316 (comment)

This configuration isn't compatible with Tauri v2.0 however the issue is persistent. Any ideas?

Yeah, the config won’t work with Tauri v2.0 because of some changes, but I figured out a way around it. Here’s what I did:

I used the recommended Tauri framework setup along with vanilla JavaScript

[dependencies]
cocoa = "0.25"
tauri = { version = "2.0.0", features = ["macos-private-api"] }

tauri.conf.json:

"app": {
   "macOSPrivateApi": true,
   "windows": [],
...
}

Here’s the code I used to set up the custom drag area and macOS title bar [./src/styles.css]:

.dragble-state {
  width: 100%;
  height: 1.75rem;
  position: fixed;
  user-select: none;
  display: flex;
  justify-content: flex-end;
  top: 0;
  left: 0;
}

[./src/main.ts]:

document.addEventListener("DOMContentLoaded", () => {
  const dragRegionDiv = document.createElement("div");
  dragRegionDiv.setAttribute("data-tauri-drag-region", "");
  dragRegionDiv.className = "dragble-state";
  document.documentElement.insertBefore(dragRegionDiv, document.body);
});

[./src-tauri/capabilities/default.json]:

{
...
"permissions": ["core:window:default", "core:window:allow-start-dragging"]
}

[./src-tauri/src/lib.rs]

pub fn run() {
    tauri::Builder::default()
        .setup(|app| {
            let win_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default())
                .hidden_title(true)
                .inner_size(800.0, 600.0);

            #[cfg(target_os = "macos")]
            let win_builder = win_builder.title_bar_style(TitleBarStyle::Overlay);
            let _window = win_builder.build().unwrap();

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

This setup works fine for me.