Linux の文字端末でマウスを使って赤い四角形を移動する方法

Linux の文字端末でマウスを使って赤い四角形を移動する方法

すべてがファイルです! UNIX はすでにそれを言っています。エリック・レイモンドはこう言いました。あなたも同意しませんか?

/dev/fb0 はディスプレイに抽象化されているため、キャラクタ端末上で /dev/fb0 にマップされたメモリを操作することで、32 ビットのトゥルーカラー画像を画面に描画できます。では、マウスとキーボードはどのように操作するのでしょうか。

/dev/input/mouse0 はマウス イベントの読み取りに使用できます。文字端末で cat を実行してマウスを動かすと、何かが起こったことが通知されるようですが、それを解釈することはできません。


正しい解釈方法を見つけるには、Google または Baidu で検索するか、Linux カーネル ソース コード内のファイル mouse0 の読み取りコールバック関数を確認するのが最も直接的な方法です。

静的 ssize_t mousedev_read(構造体ファイル *ファイル、char __user *バッファ、
     size_t カウント、loff_t *ppos)
{
 構造体 mousedev_client *client = file->private_data;
 構造体 mousedev *mousedev = client->mousedev;
 // mousedev_client 構造体にある ps2 のサイズは 6 バイトです。
 符号付きcharデータ[sizeof(client->ps2)];
 戻り値 = 0;

 spin_lock_irq(&client->packet_lock);

 if (!client->buffer && client->ready) {
  // これがコアです。mousedev_packet(client, client->ps2); に従ってください。
  クライアント->バッファ = クライアント->bufsiz;
 }
 ...

mousedev_packet がどのようにパケットを組み立てるかを見てみましょう。

静的void mousedev_packet(構造体mousedev_client *client,
    符号付きchar *ps2_data)
{
 構造体 mousedev_motion *p = &client->packets[client->tail];

 ps2_data[0] = 0x08 |
  ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
 ps2_data[1] = mousedev_limit_delta(p->dx, 127);
 ps2_data[2] = mousedev_limit_delta(p->dy, 127);
 p->dx -= ps2_data[1];
 p->dy -= ps2_data[2];
...

よく理解しています。他のことは気にしていませんし、学ぶ意欲もありません。マウスの X 座標と Y 座標を知りたいだけです。

  • p->dx、p->dy 名前とコードからわかるように、これは前の座標に対する相対的な座標の変更です。

すべての情報がそこにあります。

これで、次のコードを記述できます。

#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <stdlib.h>

// 正方形の辺の長さは 100 ピクセルです #define LENGTH 100

//抽象表示メモリ unsigned int *mem = NULL;
// 最後の画面を保存します unsigned int *old_mem = NULL;
//画面情報 static struct fb_var_screeninfo info;
整数 mouse_fd、fb_fd;

// 四角を赤く塗ります int start = 0xffff0000;

int main(int argc, char **argv)
{
 符号付きchar mouse_event[6];
 char rel_x、rel_y;
 古いxの値は0、古いyの値は0です。
 整数 abs_x = 0、abs_y = 0;

 mouse_fd = open("/dev/input/mouse0", O_RDONLY);
 fb_fd = オープン("/dev/fb0", O_RDWR);

 ioctl(fb_fd、FBIOGET_VSCREENINFO、&info);

 mem = (unsigned int *)mmap(NULL, info.xres*info.yres*info.bits_per_pixel/8, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0);

 mouse_fd、mouse_event[0]、6を読みながら{
 整数 i、w、h;
 静的int idx = 0;

 // カーネルの mousedev_packet の定義に従って、相対変位を解析します。
 rel_x = (char) マウスイベント[1];
 rel_y = (char) マウスイベント[2];
 // 絶対変位を計算します abs_x += rel_x;
 abs_y -= rel_y;
 if (abs_x <= 0 || abs_x >= info.xres - 長さ || abs_y <= 0 || abs_y >= info.yres - 長さ) {
 続く;
 }

 (old_mem == NULL)の場合{
 old_mem = (unsigned int *)mmap(NULL, info.xres*info.yres*info.bits_per_pixel/8, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
 (old_mem == NULL)の場合{
 終了(1);
 }
 } それ以外 {
 // 最後の正方形領域のピクセルを復元します for (w = old_x; w < old_x + LENGTH; w++) {
 (h = old_y; h < old_y + 長さ; h++) {
  idx = h*info.xres + w;
  mem[idx] = 古いmem[idx];
 }
 }
 古いx = abs_x;
 古いy = abs_y;
 }

 // 現在のピクセルを次の復元用に保存します for (w = abs_x; w < abs_x + LENGTH; w++) {
 (h = abs_y; h < abs_y + 長さ; h++) の場合 {
 idx = h*info.xres + w;
 古いメモリ[idx] = mem[idx];
 }
 }

 // マウスの位置に応じて赤い四角形を描画します for (w = abs_x; w < abs_x + LENGTH; w++) {
 (h = abs_y; h < abs_y + 長さ; h++) の場合 {
 idx = h*info.xres + w;
 mem[idx] = 開始;
 }
 }
 }

 0を返します。
}

これを実行し、文字端末でマウスを動かすと、効果は次のようになります。

まあ、長方形はマウスと一緒に移動し、どこへ行っても文字が破壊されることはありません。

さて、今週末に私が何をしたか、そしてそれが何を意味するかを振り返ってみましょう。

  • キャラクタ端末に 32 ビットのトゥルーカラー画像を描画できます。
  • マウスとキーボードのイベントを検出して反応できます。

つまり、時間とエネルギーがあれば、GUI システムを実装できるということです。

もちろん、GUI システムとネットワーク プロトコル スタックは山のように離れているため、2 つのファイルの読み取りと書き込みだけでなく、多くの問題が発生することは間違いありません。

  • /dev/fb0
  • /dev/input/マウス0

それは可能です。

実際、実際の G​​UI システムではこのアプローチは使用されません。彼らは、すべてがファイルであるという UNIX の哲学に反抗し、これがより優れていることを証明しているようです。ああ、Windows GUI の成功は、最新バージョンの MacOS と同様に、このことを証明しています...

キャラクター端末になるとキャラクターも描かれます。大したことじゃないよ。ただし、ピクセルを使用して文字を設定する場合は、文字のドットマトリックスの情報を理解する必要があります...これは別の分野の別のトピックです。

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。

以下もご興味があるかもしれません:
  • Linux システムターミナルでフォントを変更する方法
  • Linux ターミナルのコマンドラインでよく使われるショートカットキーの詳細な説明
  • Linux でターミナル画面を分割する 2 つの方法 (screen と tmux)
  • Linux シェル スクリプト シリーズ チュートリアル (パート 2): ターミナル印刷コマンドの詳細な説明
  • Linux コマンドラインターミナルで Python を使用する簡単な方法 (推奨)
  • LinuxターミナルでPythonコマンドラインを終了する方法
  • Linux オペレーティングシステムの端末の文字化けに対する完璧なソリューション
  • 自作 Linux ターミナル ロック画面ツール
  • Linux のターミナルでパスワードを入力するときにアスタリスクを表示する方法

<<:  Node.js のワーカー スレッドの詳細な理解

>>:  CentOS 7 で MySQL 5.7 をインストールして設定する

推薦する

1 つの記事で Vue ミドルウェア パイプラインを学ぶ

SPA を構築する場合、多くの場合、特定のルートを保護する必要があります。たとえば、認証されたユーザ...

MySQL 8.0.23 インストールの超詳細なチュートリアル

目次序文1. 公式サイトからMySQLをダウンロードする2. 解凍ファイルを設定する3. 初期化4....

ActiveMQ メッセージ サービスを構築するための Docker 学習方法の手順

序文ActiveMQ は、Apache が開発した最も人気があり強力なオープン ソース メッセージ ...

Ubuntu 20.04 Firefox でビデオを再生できない (Flash プラグインがない) 場合の解決策

1. Flashプラグインパッケージのダウンロードアドレス: https://get.adobe.c...

nginx で正規表現を使用してワイルドカードドメイン名を自動的に一致させる方法

Nginxは正規表現を使用して、ワイルドカードドメイン名をディレクトリに自動的に一致させます。 Ng...

Vue.js ソースコード解析のカスタム手順の詳細な説明

序文コア機能のデフォルトの組み込みディレクティブ (v-model および v-show) に加えて...

MySQL の datetime フィールドの丸め操作

目次序文1. 背景2. シミュレーションテスト3. 結論要約する序文もし私が罠に陥っていなかったら、...

MySql マスタースレーブレプリケーションメカニズムの包括的な分析

目次マスタースレーブレプリケーションメカニズム非同期レプリケーション準同期レプリケーションマスタース...

tdが空の場合に境界線を表示する方法

以前、CSS を使用してテーブルの border + bordercolordark + borde...

Docker を使用して Go Web アプリケーションをデプロイする方法

目次なぜ Docker が必要なのでしょうか? Docker デプロイメントの例コードの準備Dock...

FileZilla を使用して FTP サーバーに接続するプロセスの図

最初にサーバー上に FTP サーバーをセットアップし始めたとき、接続できないことがわかったので、Fi...

Windows システムで MySQL が起動しない場合の一般的な解決策

MySQL 起動エラーWindows 10 に MySQL をインストールする前は、net star...

Webデザインチュートリアル(2):模倣と盗作について

<br />前回の記事では、Webデザインの手順と方法を紹介しました。詳細については、前...

MySQL 最適化ソリューション リファレンス

最適化によって発生する可能性のある問題最適化は必ずしも単純な環境で実行されるわけではなく、実稼働環境...

リンク内の href=# はどういう意味ですか?

現在のページへのリンク。 -------------------一般的な使用法は次のとおりです。 &...