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 をインストールして設定する

推薦する

フロントエンドコンポーネント化の基礎知識を詳しく解説

目次コンポーネントの基本概念オブジェクトとコンポーネントの違い成分属性属性とプロパティ属性:財産:ク...

Nginx リバース プロキシはポート 80 のリクエストを 8080 に転送します

まず、一連の概念を理解しましょう。nginx リバース プロキシとは何でしょうか?リバース プロキシ...

jQueryはシンプルなコメントエリアを実装します

この記事では、参考までに、簡単なコメントエリアを実装するためのjQueryの具体的なコードを紹介しま...

jQuery ツリービュー ツリー構造アプリケーション

この記事では、jQueryツリービューツリー構造のアプリケーションコードを例として紹介します。具体的...

レスポンシブWebデザイン学習(1) - 画面サイズと使用率の決定

最近では、モバイルデバイスがますます普及しており、ユーザーがスマートフォンやタブレットを使用して W...

VUE+CanvasはシンプルなGobangゲームの全プロセスを実現します

序文レイアウトの点では、Gobang はランダムな動きを目的とするゲームよりも実装がはるかに簡単で、...

dockerを使用してGrafana+Prometheus構成をデプロイする

docker-compose-monitor.yml バージョン: '2' ネットワ...

Linux 上で Docker コンテナを作成、一覧表示、削除する方法の概要

1. Dockerコンテナを起動する以下のコマンドを使用して新しい Docker コンテナを起動しま...

require loaderの実装原理の深い理解

序文Node は新しいプログラミング言語ではなく、JavaScript のランタイムに過ぎないとよく...

MySQL Routerのインストールと展開

目次01 MySQLルーターの紹介MySQL Router とは何ですか? 02 MySQLルータの...

MySQL 5.7.18 無料インストール版ウィンドウ設定方法

初めてのブログです。データベースの勉強を始めた頃のことを書いています。自分でダウンロードしたのですが...

Linux の操作とメンテナンスの基本 httpd 静的 Web ページ チュートリアル

目次1. ウェアハウスを使用してhttpd lrzsz解凍ファイルを作成する2. ソースコードファイ...

モバイルウェブ画面適応(rem)

序文最近、フロントエンドの学習に関する以前のメモを整理したところ、モバイル Web 画面の適応 (r...

Dockerコンテナを停止および削除できない問題の解決策

実行中のコンテナIDを見つける ドッカーps上記のコンテナの物理的な場所を見つける /var/lib...

MySQL を暗号化および復号化するいくつかの方法 (要約)

目次前面に書かれた双方向暗号化エンコード/デコードAES_ENCRYPT/AES_DECRYPT D...