2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WSLgのGUIアプリ(Chrome・Obsidian)で文字をくっきり表示し、ウィンドウの端をドラッグでリサイズする

2
Last updated at Posted at 2026-06-01

WSLg(WSL2 の GUI サポート)で Chrome や Obsidian を動かす話です。そもそも Windows ネイティブ版があるのに、なぜ WSL 側で動かすのか。理由は2つです。

  • Windows 版 Obsidian は、WSL ファイルシステム内の vault を開けません。WSL 側で書いているノートをそのまま Obsidian で扱うには、WSL 側の Obsidian が要ります。
  • WSL 内のアプリが URL を開くとき、既定ブラウザを WSL 側の Chrome にしておくと連携が楽です。

ところが WSLg で Chrome や Obsidian などの Chromium / Electron 製アプリを HiDPI ディスプレイで使うと、たいてい次で詰まります。

  1. 文字が小さい、もしくはぼやける(解決)
  2. ウィンドウの端をドラッグしてリサイズできない(解決)
  3. アプリのアイコンが Linux のペンギンのまま(スタートメニューは解決・タスクバーは未解決)

この記事では 1 と 2 を同時に解決する設定を中心に紹介します。3 のうちスタートメニューのアイコンは直せますが、起動中ウィンドウのタスクバーアイコンは WSLg 側のバグで現状直りません(後述)。検証環境は デュアル4Kディスプレイ + WSL2(Ubuntu 24.04)+ WSLg 1.0.73 で、Google Chrome と Obsidian の両方で「くっきり表示」かつ「端をドラッグしてリサイズ可能」を確認しました。

執筆について: この記事は Claude Code が執筆し、Gemini と筆者がレビューしました。

結論(コピペ用)

アプリを次のフラグで起動します。

--ozone-platform=wayland \
--enable-features=WaylandWindowDecorations,WaylandFractionalScaleV1 \
--force-device-scale-factor=2

加えて、Windows のディスプレイ拡大率を「整数」スケール(例: 200%)にし、--force-device-scale-factor をそのスケールに合わせます(200% なら 2)。表示サイズは好みで微調整してよく、たとえば 100% のまま文字を大きくしたいなら 1.5 にもできます。これだけで文字はくっきり、端はドラッグでリサイズできるようになります。楽勝です。

ポイントは「端をドラッグできるかどうかは、スケールではなく表示バックエンド(X11 か Wayland か)で決まる」ことです。

問題1: 文字が小さい → そしてぼやける

小さい

WSLg は Windows の拡大率に応じて GDK_DPI_SCALE / QT_SCALE_FACTOR を設定します(例: 150% なら 1.5)が、これは GTK / Qt アプリ向けです。Chromium / Electron 製アプリはこれらを無視するので、--force-device-scale-factor を明示的に渡す必要があります。

ぼやける(こっちが厄介)

Windows のディスプレイ拡大率が 150% のような「分数」スケールだと、WSLg / Weston は一度 2 倍で描画してから 1.5 倍へリサンプル(縮小)します。この縮小処理が、にじみ・ぼやけの正体です。アプリ側のフラグでは消せません。

対策は「整数」スケールを使うことです。拡大率ごとの挙動は次のとおり。

  • Windows 100% → Weston は scale:1(整数) → くっきり(--force-device-scale-factor=1.5
  • Windows 150% → Weston は clientScale:1.5(分数) → ぼやける(2倍描画→縮小)
  • Windows 200% → Weston は scale:2(整数) → くっきり(--force-device-scale-factor=2

現在のスケールは次で確認できます。

grep -i scale /mnt/wslg/weston.log
# 例: scale:2, clientScale:2.000000 なら整数スケールでくっきり

問題2: ウィンドウの端をドラッグできない

ここが一番ハマります。原因はスケールではなく表示バックエンドです。

  • X11 / XWayland(--ozone-platform=x11)の場合、ウィンドウ枠とリサイズは WSLg の RAIL シェルがサーバーサイドで処理しますが、ローカルでの移動・リサイズは実装されていません(microsoft/wslg#633)。リサイズの当たり判定がずれていて、小さな点でしか効かず、リサイズのたびにズレが増えるという挙動になります(microsoft/wslg#1008)。これが「たまにドラッグできて、たまにできない」の正体です。
  • ネイティブ Wayland(--ozone-platform=wayland + WaylandWindowDecorations)の場合、アプリが自分でウィンドウ枠を描画します(クライアントサイド装飾)。端のドラッグもアプリ自身が検知し、xdg_toplevel.resize でコンポジターにリサイズを要求します。枠とドラッグ判定がアプリ側にあるので、普通の Linux ウィンドウと同じように端をドラッグできます。

つまり、端をドラッグできるようにする決め手は「ネイティブ Wayland + クライアントサイド装飾でアプリを起動する」ことです。くっきり表示は WaylandFractionalScaleV1 と、整数スケールに合わせた --force-device-scale-factor で保てます。

試したけどダメだった説(時間節約のため)

デバッグ中に「それっぽいけど違った」仮説です。同じ沼にハマらないように残しておきます。

  1. スケール値が原因では? → 違う。X11 では 1.52 もドラッグ不可。Wayland ではどちらもくっきり&ドラッグ可。
  2. マルチモニタのオフセットが原因では?(プライマリ=原点のモニタだけ効く) → 違う。プライマリでも効かない。
  3. Chrome の「システムのタイトルバーと枠を使用する」をオフにすれば? → X11 では効果なし。

端のドラッグ可否を切り替える唯一の変数は X11 か Wayland か、でした。

恒久設定(2つの起動経路をカバーする)

アプリはシェルからもスタートメニューからも起動されるので、両方に同じフラグを効かせます。

シェルからの起動:~/.local/bin/ にラッパー

~/.local/binPATH の先頭にあるので、ここに同名のラッパーを置くと優先されます。

~/.local/bin/google-chrome
#!/bin/sh
exec /usr/bin/google-chrome-stable --class=google-chrome-wsl --ozone-platform=wayland \
  --enable-features=WaylandWindowDecorations,WaylandFractionalScaleV1 \
  --force-device-scale-factor=2 "$@"

--class=google-chrome-wsl は Wayland の app_id を固定します(タスクバーアイコンで使用。後述)。Chromium はこの --class を app_id として尊重します。~/.local/bin/obsidian-app(バイナリは /opt/Obsidian/obsidian)も同様に作りますが、Obsidian(Electron)は --class を Wayland の app_id には反映せず、常に obsidian を名乗ります(後述)。なお Obsidian 用のラッパー名は obsidian-app にしておくこと。~/.local/bin/obsidian は Obsidian 公式の CLI バイナリ(実行ファイル)なので、こちらは上書きせず残してください。

作ったラッパーには実行権限を付けます(chmod +x ~/.local/bin/google-chrome ~/.local/bin/obsidian-app)。~/.local/bin を新規に作った場合、PATH に載るのは次回ログイン以降なので、すぐ使うなら source ~/.profile しておくこと。

スタートメニューからの起動:Windows ショートカットを手で作る

WSLg は本来、/usr/share/applications/.desktop を読んで、スタートメニュー(Windows 側の「Ubuntu-24.04」フォルダ)にショートカットを自動生成します。ところがこの自動生成のアプリ一覧は、一度できると凍結されがちです。あとから入れたアプリは、/usr/share/applications/ に正しい .desktop があっても、NoDisplay を外しても、別名にしても、wsl --shutdown で distro を再起動しても、一覧に出てこないことがあります。

実際、手元では最初から入っていた8個(LibreOffice Writer / Calc / Impress、xpdf、gv、Zutty など)だけが毎回再生成され、あとから入れた Chrome・Obsidian は出てきませんでした。さらに、同じ LibreOffice パッケージの Draw すら出ません(Writer は出るのに)。WSLg のプラグインキャッシュ %LOCALAPPDATA%\Temp\WSLDVCPlugin\<distro名>\ を見ると、この8個分の .ico しか無く、distro 起動のたびにその8個だけが焼き直されていました。.desktop の内容で選んでいるのではなく、凍結した一覧を再生成しているだけ、という挙動です。

なので自動生成に頼らず、Windows のショートカットを自分で作ります。WSLg のショートカットは結局 wslg.exe を起動しているだけなので、同じ形を手で再現します(自動生成された LibreOffice のショートカットは C:\Program Files\WSL\wslg.exe -d <distro名> --cd "~" -- <コマンド> という形でした)。

まずアイコンを用意します。.lnk のアイコンは .ico 形式が要るので、アプリの PNG を .ico に変換します。ImageMagick などが無くても、PNG をそのまま埋めた単一画像 .ico を Python だけで作れます(Windows は PNG 圧縮の .ico を読めます)。

WSL で実行(PNG → ICO、外部ツール不要)
import struct
def png2ico(src, dst):
    d = open(src, "rb").read()
    w, h = struct.unpack(">II", d[16:24])      # PNG の IHDR から幅・高さ
    hdr = struct.pack("<HHH", 0, 1, 1)
    ent = struct.pack("<BBBBHHII", w % 256, h % 256, 0, 0, 1, 32, len(d), 22)
    open(dst, "wb").write(hdr + ent + d)        # 256 以上は w%256=0 となり「256」を意味する

base = "/mnt/c/Users/<Windowsユーザー名>/AppData/Local/WSLApps"
png2ico("/usr/share/icons/hicolor/256x256/apps/google-chrome.png", base + "/google-chrome-wsl.ico")
png2ico("/opt/Obsidian/resources/icon.png", base + "/obsidian-wsl.ico")

事前に mkdir -p /mnt/c/Users/<Windowsユーザー名>/AppData/Local/WSLApps でフォルダを作っておきます。Temp ではなくここに置くのは、WSLDVCPlugin のキャッシュと違って消えないようにするためです。

次にショートカットを作ります。distro名wsl -l -q で確認してください。

Windows(PowerShell)で実行
$ws=New-Object -ComObject WScript.Shell
$distro='Ubuntu-24.04'              # wsl -l -q で確認した distro 名
$prog=[Environment]::GetFolderPath('Programs')
$ico=$env:LOCALAPPDATA+'\WSLApps'
function New-WslLnk($name,$cmd,$icon){
  $s=$ws.CreateShortcut("$prog\$name.lnk")
  $s.TargetPath='C:\Program Files\WSL\wslg.exe'
  $s.Arguments='-d '+$distro+' --cd "~" -- '+$cmd
  $s.IconLocation="$ico\$icon"
  $s.Save()
}
New-WslLnk 'Google Chrome (WSL)' '/home/<ユーザー名>/.local/bin/google-chrome' 'google-chrome-wsl.ico'
New-WslLnk 'Obsidian (WSL)'      '/home/<ユーザー名>/.local/bin/obsidian-app'  'obsidian-wsl.ico'

ショートカットはトップレベルの Programsスタートメニュー\プログラム)に置きます。WSLg が再生成する「Ubuntu-24.04」フォルダの中に置くと、自動生成のタイミングで消される恐れがあるためです。表示名を (WSL) 付きにしているのは、Windows ネイティブの Chrome / Obsidian と区別するためです。これでスタートメニューに、アプリのアイコン付きで両方が出ます。wsl --shutdown も不要です。

なおショートカットのコマンドをラッパー(前節)に向けているので、起動フラグはラッパー1か所で管理できます。

起動中ウィンドウのタスクバーアイコン(ペンギンが残ることがある)

スタートメニューのアイコンは上の .ico で直りますが、起動中ウィンドウのタスクバーアイコンは別系統です。WSLg はウィンドウの Wayland app_id を /usr/share/applications/.desktopStartupWMClass 一致)に対応づけてアイコンを決めます。対応が取れないと、WSLg 既定のペンギンになります。

まずラッパー側で --class=<app_id> を渡して app_id を固定します。Chrome は --class=google-chrome-wsl を Wayland の app_id として尊重するので、StartupWMClass=google-chrome-wsl.desktop/usr/share/applications/ に置けば対応づけの土台ができます(このディレクトリへの書き込みには sudo が要ります)。

/usr/share/applications/google-chrome-wsl.desktop
[Desktop Entry]
Type=Application
Name=Google Chrome (WSL)
Exec=/home/<ユーザー名>/.local/bin/google-chrome %U
Icon=/usr/share/icons/hicolor/256x256/apps/google-chrome.png
StartupWMClass=google-chrome-wsl
Categories=Network;WebBrowser;

一方 Obsidian(Electron)は --class を Wayland の app_id に反映せず、常に obsidian を名乗ります。ps では --class=obsidian-wsl が渡っていても、weston.logappId:obsidian のままです。なので Obsidian 用に obsidian-wsl.desktop を作っても永遠に一致しません。Obsidian については、標準で入っている obsidian.desktopIcon=obsidian が既存のテーマ PNG に解決される)が対応相手になります。--class で名前を分けることに意味があるのは、Chrome 側の app_id を Obsidian と衝突させないためです(これをやらないと両方が同じ app_id に合流し、タスクバーで1つのペンギンにまとまってしまいます)。

ここまでで「Chrome と Obsidian が同じペンギンに合流する」状態は解消し、2つは別々のタスクバーグループに分かれます。ただし、app_id と .desktop を正しく揃えても、起動中アイコンがアプリ本来のものにならない環境があります。手元(Ubuntu-24.04 + 2024年春ビルドの WSLg)がまさにそれで、Chrome はペンギン、Obsidian はノートのアイコンのまま直りませんでした(Obsidian 側は標準で入っている obsidian.desktop が後述の名前空間破綻より前に読まれているとみられ、あとから足した Chrome 用 .desktop は読まれずペンギンのまま、という非対称です)。

原因は .desktop でもアイコンファイルでもなく、WSLg 側のバグです。/mnt/wslg/weston.log を見ると、システムディストロ(WSLg 本体が動く側)がユーザーディストロのマウント名前空間に入って .desktop/アイコンを読みに行く処理が、attach_app_list_namespace failed Invalid argument で繰り返し失敗していました(起動直後の最初の数個を読んだあと破綻し、以降はオンデマンドのアイコン読み込みでも毎回失敗)。この状態だと、.desktop やアイコンをどれだけ正しく置いても WSLg がそもそも読めないため、アイコンは載りません。スタートメニュー側を Windows ショートカット(前節)で手作りしたのは、まさにこの読み取りに依存しないためです。

切り分けは /mnt/wslg/weston.logattach_app_list_namespace failed の有無で付きます。出ていれば .desktop/アイコン側の修正では直らないので、Windows 側で wsl --update を試してください(新しい WSLg で名前空間アタッチが直る可能性があります)。更新後、同じログにこの行が出なくなったかで確認できます。

なお --ozone-platform=x11 で起動すると、ウィンドウが _NET_WM_ICON を自前で持つためタスクバーアイコンは正しく出ます。ただし本記事の主目的である「端をドラッグできるリサイズ」が X11/RAIL のバグで壊れるので、ここでは採れないトレードオフです。

ハマりどころ

  • Wayland のウィンドウが出ない(タスクバーのアイコンだけ)。なお Chrome の SingletonLock を死んだプロセスが掴んでいるか、Weston / RAIL の状態が壊れています。アプリを終了し、rm -f ~/.config/google-chrome/Singleton* してから Windows 側で wsl --shutdown してください。その後はネイティブ Wayland も正常に表示されます。(この初回失敗が「WSLg で Wayland は無理」という誤解の元になりがちですが、ちゃんと動きます。)
  • TMPDIR を差し替えるシェルから起動すると、二度と窓が出なくなる。Chromium / Electron は SingletonSocketTMPDIR 配下に作ります。サンドボックス環境(bwrap 系のサンドボックスや、TMPDIR を一時ディレクトリへ向けるエージェント実行環境など)から一度起動すると、そのディレクトリが消えた後も SingletonLock が死んだソケットを指し続け、以降の起動は無言で既存(幽霊)インスタンスへ委譲して窓を出しません。バイナリ自体は正常です。なお対策は、起動ラッパーに「プロセスが無ければ Singleton* を消してから起動する」自己修復を入れること(例: pgrep -x <app> >/dev/null || rm -f ~/.config/<app>/Singleton*)。wsl --shutdown は不要になります。
  • pkill -f <パターン> で自分のシェルごと死にます。パターン文字列がシェル自身のコマンドラインに一致するためです。pkill -x <名前> か PID 指定を使いましょう。
  • モニタの X11 名・座標(rdp-0 / rdp-2 やオフセット)は wsl --shutdown で変わります。毎回 xrandr --listmonitors で確認し、ハードコードしないこと。
  • .wslgconfig の分数スケール設定ではくっきりになりません。WESTON_RDP_FRACTIONAL_HI_DPI_SCALING=true は公式設定ですが、分数スケールは原理的にぼやけます。直すのは「整数スケール+一致した --force-device-scale-factor」であって、このファイルではありません。

設定の要点

  • 文字がぼやける → 整数のディスプレイ拡大率(200% など)+一致した --force-device-scale-factor
  • 端をドラッグできない → ネイティブ Wayland + WaylandWindowDecorations(X11/RAIL のサーバーサイドリサイズのバグを回避)。
  • 両方をまとめた起動フラグ:
--ozone-platform=wayland --enable-features=WaylandWindowDecorations,WaylandFractionalScaleV1 --force-device-scale-factor=2

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?