KDOC 201: スクリーンルーラーを作る
この文書のステータス
- 作成
- 2024-07-20 貴島
- レビュー
- 2024-07-22 貴島
DONE プロジェクトステータス
プロジェクトは完了である。
概要
X Window Systemでスクリーンルーラーを作る。
Tasks
TODO イベントループを使う
ルーラー追従を、単純なループにsleepを入れて実装していてすごいダサい。カーソルイベントを受け取って同期したい。
DONE 動作するようにする
swillner/highlight-pointer的な感じで自作したい。
- 極小のウィンドウを作って、それをカーソル周辺に描画しているように見える
XRectangle rect; XserverRegion region = XFixesCreateRegion(dpy, &rect, 1); XFixesSetWindowShapeRegion(dpy, win, ShapeInput, 0, 0, region); XFixesDestroyRegion(dpy, region);
https://github.com/swillner/highlight-pointer/blob/32bf4c60696a4764e8060574ca3031f4fb4ca20d/highlight-pointer.c#L353-L357
} else if (highlight_visible) { get_pointer_position(&x, &y); XMoveWindow(dpy, win, x - total_radius - 1, y - total_radius - 1); * unfortunately, this causes increase of the X server’s cpu usage * }
https://github.com/swillner/highlight-pointer/blob/32bf4c60696a4764e8060574ca3031f4fb4ca20d/highlight-pointer.c#L155
static void set_window_mask() {
https://github.com/swillner/highlight-pointer/blob/32bf4c60696a4764e8060574ca3031f4fb4ca20d/highlight-pointer.c#L245-L253
static void redraw() { XSetForeground(dpy, gc, button_pressed ? pressed_color.pixel : released_color.pixel); if (options.outline) { XSetLineAttributes(dpy, gc, options.outline, LineSolid, CapButt, JoinBevel); XDrawArc(dpy, win, gc, options.outline, options.outline, 2 * options.radius + 1, 2 * options.radius + 1, 0, 360 * 64); } else { XFillArc(dpy, win, gc, options.outline, options.outline, 2 * options.radius + 1, 2 * options.radius + 1, 0, 360 * 64); } }
https://github.com/swillner/highlight-pointer/blob/32bf4c60696a4764e8060574ca3031f4fb4ca20d/highlight-pointer.c#L130-L146
static int init_events() { XIEventMask events; unsigned char mask[(XI_LASTEVENT + 7) / 8]; memset(mask, 0, sizeof(mask));
XISetMask(mask, XI_RawButtonPress); XISetMask(mask, XI_RawButtonRelease); XISetMask(mask, XI_RawMotion);
events.deviceid = XIAllMasterDevices; events.mask = mask; events.mask_len = sizeof(mask);
XISelectEvents(dpy, root, &events, 1);
return 0; }
- イベントマスクとは、特定のイベントが発生したときに通知を受け取るための機構。一般的に、イベントマスクはビットマスクとして表現され、各ビットが特定のイベントタイプに対応している
https://github.com/swillner/highlight-pointer/blob/32bf4c60696a4764e8060574ca3031f4fb4ca20d/highlight-pointer.c#L115-L123
static void show_highlight() { int x, y; int total_radius = options.radius + options.outline; get_pointer_position(&x, &y); XMoveWindow(dpy, win, x - total_radius - 1, y - total_radius - 1); XMapWindow(dpy, win); redraw(); highlight_visible = 1; }
- 新しく作成されるウィンドウはウィンドウマネージャによって制御されず、直接画面に表示される
func (w *Window) Create(parent xproto.Window, x, y, width, height, valueMask int, valueList ...uint32) {
- valueMaskで、ビット形式で指定したマスクに対して、可変長引数の値を設定していく
- xfixesで対象領域のクリックを無視する
BadRequest {NiceName: Request, Sequence: 2, BadValue: 0, MinorOpcode: 5, MajorOpcode: 138} exit status 1
xdpyinfo -queryExtensions | grep opcode
BIG-REQUESTS (opcode: 133) Composite (opcode: 142) DAMAGE (opcode: 143, base event: 91, base error: 152) DOUBLE-BUFFER (opcode: 145, base error: 153) DPMS (opcode: 147) DRI2 (opcode: 155, base event: 119) DRI3 (opcode: 149) GLX (opcode: 152, base event: 95, base error: 158) Generic Event Extension (opcode: 128) MIT-SCREEN-SAVER (opcode: 144, base event: 92) MIT-SHM (opcode: 130, base event: 65, base error: 128) Present (opcode: 148) RANDR (opcode: 140, base event: 89, base error: 147) RECORD (opcode: 146, base error: 154) RENDER (opcode: 139, base error: 142) SECURITY (opcode: 137, base event: 86, base error: 138) SHAPE (opcode: 129, base event: 64) SYNC (opcode: 134, base event: 83, base error: 134) X-Resource (opcode: 150) XC-MISC (opcode: 136) XFIXES (opcode: 138, base event: 87, base error: 140) XFree86-DGA (opcode: 154, base event: 112, base error: 179) XFree86-VidModeExtension (opcode: 153, base error: 172) XINERAMA (opcode: 141) XInputExtension (opcode: 131, base event: 66, base error: 129) XKEYBOARD (opcode: 135, base event: 85, base error: 137) XTEST (opcode: 132) XVideo (opcode: 151, base event: 93, base error: 155)
コードは138で、
XFIXES
である。ここからは何もわからない
xtrace -o output.log ./xpoint
001:<:0003: 16: XFIXES-Request(138,5): CreateRegion region=0x05600001 rectangles={x=0 y=0 w=0 h=0}; 001:<:0004: 4: Request(43): GetInputFocus 001:>:0003:Error 1=Request: major=138, minor=5, bad=0x00000000, seq=0003
000:<:0009: 12: XFIXES-Request(138,0): QueryVersion major version=6 minor version=0 000:>:0009:32: Reply to QueryVersion: major version=6 minor version=0 000:<:000a: 16: XFIXES-Request(138,5): CreateRegion region=0x05400002 rectangles={x=0 y=0 w=0 h=0}; 000:<:000b: 20: XFIXES-Request(138,21): SetWindowShapeRegion window=0x05400001 kind=Input(0x02) x offset=0 y offset=0 region=0x05400002 000:<:000c: 8: XFIXES-Request(138,10): DestroyRegion region=0x05400002 000:<:000d: 24: Request(98): QueryExtension name='XInputExtension'
- 正常なプログラムではXFIXESがまとまって存在しているが、エラーが起きるコードでは見知らぬGetInputFocusが混じっている。こいつがうまくいっていない可能性がある
- なぜか先にバージョンを確認すると動作するようになった
DONE 透明度を設定する
半透明にする。
- comptonが起動してないと透明にならない
- X Window Systemは透明の表示をサポートしてない。受け取れるが描画はできない
- comptonはコンポジットマネージャ。コンポジットマネージャはウィンドウを描画し合成する責任を持つ
DONE コード整理する
きれいにする。
関連
なし。