ウィンドウの周りの影は、重なったウィンドウの境目を分かりやすくする一方、デスクトップになじませたいウィジェットや、形を自由にした透明ウィンドウでは邪魔になります。影は設定ファイルの shadow(既定は true)で起動時に決め、実行中は JS の setShadow() か Rust の set_shadow() で切り替えます。やっかいなのは、同じ設定でも OS と枠(decorations)の有無で結果が変わることです。フレームレスや透明なウィンドウで影をどう扱うかは、このレシピにまとめます。
前提条件
プラグインは不要です。setShadow() の権限 core:window:allow-set-shadow は core:window:default に含まれないので追加します。後述の「枠を消して影を付け直す」例では core:window:allow-set-decorations も使います。起動時の設定だけで済むなら権限は要りません。
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
"core:default",
"core:window:allow-set-shadow",
"core:window:allow-set-decorations"
]
}
影付きのフレームレスウィンドウにする設定です。shadow は省略しても true ですが、意図を残すために書いておくと後で迷いません。
{
"app": {
"windows": [
{ "label": "main", "width": 800, "height": 600, "decorations": false, "shadow": true }
]
}
}
設定と実際の見た目
shadow の効き方は次のとおりです。macOS は設定どおりに付き外しされますが、Windows は枠の有無で結果が変わり、Linux では設定が効きません。
| 枠 | shadow | Windows | macOS | Linux |
|---|---|---|---|---|
| あり | true | 影あり | 影あり | 非対応 |
| あり | false | 影は消えない | 影なし | 非対応 |
| なし | true | 影あり + 1px の白い枠線(Windows 11 は角丸) | 影あり | 非対応 |
| なし | false | 影なし | 影なし | 非対応 |
つまり Windows では、影を消したければ枠も消すしかなく、枠を消して影を付けると細い白い線が付きます。反対に、Windows 11 でフレームレスの角を丸くしたいときは shadow: true が近道です。
1. フロントエンドから実装する (TypeScript)
実行中に影を切り替える
影の有無を読み取る API は無いので、今の状態はアプリ側で覚えておきます。
import { getCurrentWindow } from '@tauri-apps/api/window';
const win = getCurrentWindow();
let shadowOn = true; // 設定ファイルの shadow と合わせる
// ミニ表示では影を消してデスクトップになじませる
export async function setMiniMode(mini: boolean) {
if (shadowOn === !mini) return;
await win.setShadow(!mini); // core:window:allow-set-shadow が必要
shadowOn = !mini;
}
枠を消して影を付け直す
通常の枠で起動したウィンドウを、実行中に「影付きのフレームレス」に切り替えるときは、枠と影を続けて指定します。
import { getCurrentWindow } from '@tauri-apps/api/window';
const win = getCurrentWindow();
export async function applyFramelessLook() {
await win.setDecorations(false); // core:window:allow-set-decorations
await win.setShadow(true); // Windows 11 では角も丸くなる
}
枠を消すと移動や閉じるボタンも無くなるので、自作のタイトルバーと組み合わせます(フレームレスウィンドウ、自作のタイトルバーにメニューを組み込む)。
白い線を避けて、影を CSS で描く
Windows の白い線をどうしても避けたい場合や、Linux でも同じ見た目にしたい場合は、shadow: false にした透明なウィンドウの中で、影をページ側に描きます。影がはみ出す分だけ内側に余白を取るのがポイントです。
:root,
body {
background: transparent;
margin: 0;
}
/* ウィンドウの端から 12px 内側に本体を置き、余白に影を落とす */
.frame {
position: fixed;
inset: 12px;
border-radius: 10px;
background: #fff;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
}
設定ファイルでは "transparent": true、"decorations": false、"shadow": false を指定します。余白も見えないだけでウィンドウの一部なので、そこをクリックしても背後のアプリに届くとは限りません。気になるなら クリックスルー と組み合わせます。
2. バックエンドから実装する (Rust)
新しく作るウィンドウはビルダーの shadow()、作成済みのウィンドウは set_shadow() で指定します。ウィンドウを作るコマンドは、Windows で固まらないよう async にします。
use tauri::{WebviewUrl, WebviewWindowBuilder};
/// 呼び出し元ウィンドウの影を切り替える
#[tauri::command]
fn set_window_shadow(window: tauri::WebviewWindow, enable: bool) -> Result<(), String> {
window.set_shadow(enable).map_err(|e| e.to_string())
}
/// 呼び出し元ウィンドウを「枠なし + 影あり」にする
#[tauri::command]
fn apply_frameless_look(window: tauri::WebviewWindow) -> Result<(), String> {
window.set_decorations(false).map_err(|e| e.to_string())?;
window.set_shadow(true).map_err(|e| e.to_string())
}
/// 影付きのフレームレスウィンドウを新しく開く
#[tauri::command]
async fn open_palette(app: tauri::AppHandle) -> Result<(), String> {
WebviewWindowBuilder::new(&app, "palette", WebviewUrl::App("palette.html".into()))
.inner_size(360.0, 480.0)
.decorations(false)
.shadow(true)
.build()
.map_err(|e| e.to_string())?;
Ok(())
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
set_window_shadow,
apply_frameless_look,
open_palette
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Rust のコマンド経由なら、JS 側に core:window:allow-set-shadow などの権限は要りません。
import { invoke } from '@tauri-apps/api/core';
await invoke('set_window_shadow', { enable: false });
await invoke('apply_frameless_look');
await invoke('open_palette');
動作確認
npm run tauri dev で起動し、setMiniMode(true) と setMiniMode(false) を交互に呼んで見た目を比べます。Windows では、枠付きのままだと何も変わらないのが正常です。applyFramelessLook() の後に切り替えると、影と白い線がまとめて付いたり消えたりします。Windows 11 では影を付けると角も丸くなります。
よくあるエラーと対処法
- 「window.set_shadow not allowed. Permissions associated with this command: core:window:allow-set-shadow」: 権限の追加漏れです。リリースビルドでは「Command plugin:window|set_shadow not allowed by ACL」と出ます。
- Windows で
setShadow(false)しても影が消えない: 枠付きのウィンドウです。Windows で影を消すにはdecorations: falseにします。 - フレームレスの周りに白い線が出る: Windows で枠なしのまま
shadow: trueになっています。線が不要ならshadow: falseにし、必要なら CSS で影を描きます。 - Linux で見た目が変わらない:
shadowとsetShadow()は Linux では非対応で、指定しても見た目は変わりません。
OS ごとの違いと注意点
- Windows: 枠付きのウィンドウは常に影があり、
falseは効きません。枠なしでtrueにすると 1px の白い枠線が付き、Windows 11 では角が丸くなります。透明なウィンドウでもこの線は出るので、透明なウィンドウ ではshadow: falseを基本にしています。 - macOS: Windows のような例外は無く、枠の有無にかかわらず
shadowの値どおりになります。CSS で影を描く方法を使うなら、透明なウィンドウのためのmacOSPrivateApiが別途必要です。 - Linux: 非対応です。どの OS でも同じ見た目にしたいなら、CSS で影を描く方法を使います。
