1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Weston/Wayland入門⑤ シェルを実装する

Last updated at Posted at 2025-07-03

Weston/Wayland入門まとめ

Westonではウインドウ等をどのように配置して表示するかといったことはシェルと呼ばれる特別なモジュールが実現している。
例えばタイトルバーをドラッグしてウインドウを移動させるという当たり前の操作もWestonにおいてはシェルが担っている。
それどころかどのウインドウを表示するかといったことすらもシェルが制御しているため、シェルが何もしない場合、Weston上には何も表示されないことになる。

今回は「サーフェスが作られたらデフォルト位置(原点)に表示する」という機能だけを持った非常に簡単なシェルを実装する。

開発環境

コードは前回までと同様以下の環境で開発している。

  • OS: Debian trixie(testing)
  • 言語: C++20
  • Weston14

シェルとシェルプロトコルについて

Westonはxdg_shellivi_applicationといったシェルプロトコルをサポートしており、シェルモジュールは必ずどれか(もしくは複数)のシェルプロトコルを実装している。

しかし本来シェルはウインドウサーフェスの管理をすることが目的であり、クライアントからの要求等を一切受け付けず、内部で完結した管理をするのであれば「シェルプロトコルを実装しないシェル」というのも実現可能である。

ただし現時点においてはほぼすべてのクライアントが何からのシェルプロトコルのバインドを要求するため、もし「シェルプロトコルを実装しないシェル」というものを実装してもほとんど全てのクライアントが動作しないシェルとなってしまう。

まとめると「シェルにシェルプロトコル実装は必須ではない、しかし実装しないと役立たずになる」というわけである。

今回はシェルプロトコルを実装していなくても動作するEGLWLMocknavigationを利用して確認していくこととする。

wayland-ivi-extensionインストール

EGLWLMocknavigationは以下のプロジェクトにある。
プロジェクトのREADME.mdに従ってインストールをおこなう。

注意
おそらくweston13以降だとlibweston.hの互換性がなくなっているためwayland-ivi-extensionのインストールができない。
その場合は次回分まで実装して動作確認はQtアプリでおこなってほしい。

スケルトン実装

いつもどおり何もしない実装をまず書いてみる。基本的にはモジュールのときと同じだが唯一違うのが呼び出される関数がwet_module_init()からwet_shell_init()になることである。

my-shell.cpp
#include <libweston/libweston.h>

extern "C" {

WL_EXPORT int wet_shell_init(struct weston_compositor *compositor, int *argc, char *argv[])
{
    weston_log("my-shell: init\n");

    return 0;
}
}

CMakeLists.txtについては前回とほぼ同じになるため割愛するが、my-shell.soが作られるように書いてほしい。

いつもどおりビルドする。

$ cmake -S . -B build
$ cmake --build build

westonコマンドに--shellオプションを指定することでシェルとして実行できる。

$ weston --shell=$(pwd)/build/my-shell.so

シェルとしての機能を一切果たしていないため、黒画面が表示されるだけとなる。
wet_shell_init()が実行されたことをログで確認する。

[12:26:58.068] my-shell: init

この時点ではEGLWLMocknavigationを起動してももちろん表示はされない。

サーフェス表示の実装

最低限表示をおこなうためには以下の処理が必要となる。

  1. 表示領域であるweston_layerを作成する
  2. サーフェス作成のコールバック作成
  3. サーフェスコミットのコールバック作成
  4. 初回コミット時に表示処理を行う

順にみていく前に、まずはシェルの状態を保持するためのMyShellを作る。

struct MyShell {
    wl_listener surface_created_listener;
    weston_layer layer;
};

表示領域であるweston_layerを作成する

wet_shell_init()内でweston_layer_initで表示領域を初期化する。

    auto *shell = new MyShell{};

    weston_layer_init(&shell->layer, compositor);
    weston_layer_set_position(&shell->layer, WESTON_LAYER_POSITION_NORMAL);

サーフェス作成のコールバック作成

wet_shell_init()内でサーフェスのコールバックとしてsurface_created()(後述)を設定する。

    shell->surface_created_listener.notify = surface_created;
    wl_signal_add(&compositor->create_surface_signal, &shell->surface_created_listener);

サーフェスコミットのコールバック作成

サーフェス作成時に呼び出されるsurface_created()内でサーフェスコミット(サーフェス変更内容反映要求)のコールバックとしてsurface_committed()(後述)を設定する。

static void surface_created(struct wl_listener *listener, void *data)
{
    MyShell *shell = wl_container_of(listener, shell, surface_created_listener);
    auto *wet_surf = static_cast<weston_surface *>(data);

    wet_surf->committed = surface_committed;
    wet_surf->committed_private = shell;
}

ここではweston_surfaceが持っているcommittedコールバックを設定することでコミット時に処理がおこなわれる。

なおcommittedコールバックは基本的にシェルのみが設定することが期待されている。

初回コミット時に表示処理を行う

ビューを作成し、レイヤーに登録することで描画処理が行われる。

static void surface_committed(struct weston_surface *wet_surf, struct weston_coord_surface)
{
    auto *shell = static_cast<MyShell*>(wet_surf->committed_private);
    weston_view *view = nullptr;

    if (!weston_surface_has_content(wet_surf)) {
        return;
    }

    if (wl_list_empty(&wet_surf->views)) {
        view = weston_view_create(wet_surf);
        if (!view)
            return;
    } else {
        view = wl_container_of(wet_surf->views.next, view, surface_link);
    }

    if (weston_surface_is_mapped(wet_surf)) {
        return;
    }

    weston_surface_map(wet_surf);
    weston_view_move_to_layer(view, &shell->layer.view_list);
}

Westonにはバッファがアタッチされていないサーフェスに対してコミット処理をおこなってはいけないという暗黙の了解があるために冒頭でweston_surface_has_content(wet_surf)によるガードが入っている。

実行

ビルドし前述同様に実行してサーフェスが表示されることを確認する。

image.png

C/C++初級者への課題

課題

  • 前々回、クライアントを実装したときにはクライアントの状態を保持するAppはスタック上に確保した。今回シェルの状態を保持するMyShellnewしている。2つの違いについて理由を考えよう

変更履歴

  • 2025-07-09 weston13以降でwayland-ivi-extensionがインストールできないことが判明したため注意を記載
  • 2025-07-02 コミット時処理をcommit_signalからweston_surface.committedコールバックに変更
1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?