June 21, 2008

操作 X 的 Cut and Paste Buffer

在 X Window System 要處理 X client 之間的資料分享,因為設計本質上與傳統 GUI 有極大差異,所以,不可等閒視之,也就是說,在 Win32 下很普通的 Clipboard 處理,搬到 X 下,其實得考慮相當多。Win32 Clipboard 無法「直接」對應到 X Clipboard,我們必須分很多層級去思考,一般的 X client 中,以滑鼠(mouse) / 指標(pointer) 作區域的文字 / 物件選擇動作,在真正貼上或複製到標的視窗前,其實涉及到跨越實體環境的資料分享 (考慮到 X Protocol 分散式處理本質) 的議題,所以,光是如何保存這些中間資訊,就是很大的學問。

簡單的文字,可透過名為 X cut buffer 的空間,暫時保存 X cut-paste 過程的內容,但這僅是最基本的操作,一般設計較為複雜的 X Toolkit 如 Gtk+ 或 Qt,其實都援引不同的機制,不過,這不妨礙我們對系統的理解。作為最基本的資料分享機制,X cut and paste buffer 僅是很單純的存取緩衝區的資料,我們可這樣實做簡單的寫入操作,程式如下: (xcutbuf-set.c)
#define _GNU_SOURCE
#include <X11/Xlib.h>
#include <X11/Xatom.h>

#include <stdio.h>
#include <string.h>

#define BUF_LENGTH 8080
int main(int argc, char* argv[])
{
	char buf[BUF_LENGTH];
	Display *disp = XOpenDisplay(0);

	fgets(buf, BUF_LENGTH, stdin);
	XStoreBytes(disp, buf, strnlen(buf, BUF_LENGTH));

	while (XGetSelectionOwner(disp, XA_PRIMARY) != None) {
		XSetSelectionOwner(disp, XA_PRIMARY, None, CurrentTime);
	}
	return 0;
}
這裡用到 XStoreBytes(3) 來對緩衝區作寫入動作,編譯並執行如下:
$ gcc -o xcutbuf-set xcutbuf-set.c -lX11
$ echo -n "Let's Do It" | ./xcutbuf-set
自標準輸入取得資料後,就透過 XStoreBytes(3) 寫入 x cut buffer,需要留意的是,我們必須透過 XSetSelectionOwner(3) 來讓現在的 window selection (X 術語,表示指定的「選擇」動作,像是 cut-n-paste 的動作) 生效。在 rxvt 或 rxvt-unicode 下,我們可按下 "Shift" + "Insert" 按鍵組合,會自 X cut buffer 取出已寫入的資料,也就是剛剛那字串:"Let's Do It"。透過函式呼叫,可取出裡頭的字串,程式碼如下: (xcutbuf-get.c)
#include <X11/Xlib.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
	int count;
	Display *disp = XOpenDisplay(0);
	printf("==> %s\n", XFetchBytes(disp, &count));
	return 0;
}
編譯並執行:
$ gcc -o xcutbuf-get xcutbuf-get.c -lX11
$  ./xcutbuf-get
==> Let's Do It
以上,咱們邁出認識 X client 間資料交換最簡單的機制:X cut buffer 的操作,未來將會探討 X clipboard 運作的機制。
由 jserv 發表於 June 21, 2008 12:11 AM
迴響
發表迴響









記住我的資訊?