飴屋ぷろじぇくと

 ちょっとカテゴリを分けてみようかなっと。

--.--.--[--] スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

2014.11.22[土] xlibでデスクトップに立つ。その2

withballoon.jpg
続編です。ここまでもっていきます。
9.タイトルバーの無いウィンドウをマウスドラッグで動かすには
左端に固定じゃいけません。他にもやり方があると思いますが、ここではマウスイベントを利用して動かします。横ドラッグで下に張り付いたまま場所を移動出来るようにします。
マウスドラッグは、
「ボタンを押し込み」 → 「押したままポインタ移動」 → 「ボタンを離す」
この三つのアクションがあります。それぞれがイベントとしてプログラムに通知されます。
通知を受け取る為に、Windowにイベントマスクを設定しまてやります。
    /* イベントマスク */
XSelectInput( dsp, win, ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
で、イベントループでは、
    /* イベントループ */
while (1) {
XEvent event;
XNextEvent( dsp, &event );
switch( event.type ){
case Expose: /* 再描画など */
if (event.xexpose.count == 0) {
/* ここで再描画の度にイメージを描画する */
XPutImage( dsp, win, gc, image, 0, 0, 0, 0, iwidth, iheight );
}
break;
case ButtonPress: /* ボタンを押し込み */
drag = 1;
rx = ((XButtonEvent*)&event)->x;
break;
case ButtonRelease: /* ボタンを離す */
if (drag) {
drag = 0;
}
break;
case MotionNotify: /* ポインタがウィンドウ上で移動 */
if (drag) {
cx += ((XButtonEvent*)&event)->x - rx;
XMoveWindow(dsp, win, cx, height - iheight);
}
break;

}
こんな風に各イベント毎に処理を行います。
ここで使っている変数はmain関に宣言を追加しておきます。
    int drag = 0, rx = 0, cx = 0;
これでドラッグ移動出来るようになりますが、コレだけの為に動画を作って貼るのはアレなので割愛。
次に行きます。
10.ウィンドウをもう一つ出す
上の画像にあるように吹き出しのウィンドウを出します。
まずは画像読み込み、ウィンドウを生成、マスク生成してウィンドウにセット〜ウィンドウを表示まで。吹き出し用に同じものをもう1セット追加するだけなので説明するまでもないでしょう。
int main()
{
Display *dsp;
Window win, sub;
char *mask1, *mask2;
Pixmap pm1, pm2;

(…中略…)

int iwidth, iheight, iwidth2, iheight2;
GC gc;
XImage *image1, *image2;

(…中略…)

/* イメージを読み込む */
image1 = load_bmp(dsp, "dekfoko.bmp", &iwidth, &iheight);
image2 = load_bmp(dsp, "balloon.bmp", &iwidth2, &iheight2);

(…中略…)

/* ウィンドウを生成 */
win = XCreateSimpleWindow( dsp, RootWindow(dsp, 0),
0, 0, 100, 100, 0,
BlackPixel(dsp,0), WhitePixel(dsp,0) );
sub = XCreateSimpleWindow( dsp, RootWindow(dsp, 0),
0, 0, 100, 100, 0,
BlackPixel(dsp,0), WhitePixel(dsp,0) );


(…中略…)

/* イメージからマスクを作り、ウィンドウの形に設定 */
mask1 = make_shape(image1);
pm1 = XCreateBitmapFromData( dsp, RootWindow(dsp,0), mask1, iwidth, iheight);
mask2 = make_shape(image2);
pm2 = XCreateBitmapFromData( dsp, RootWindow(dsp,0), mask2, iwidth2, iheight2);

free(mask1);
free(mask2);
XShapeCombineMask( dsp, win, ShapeBounding, 0, 0, pm1, ShapeSet);
XShapeCombineMask( dsp, sub, ShapeBounding, 0, 0, pm2, ShapeSet);
/* タイトルバーとサイズボックスなし */
change_prop(dsp, win);
change_prop(dsp, sub);
/* 表示 */
XMapWindow( dsp, win );
XMapWindow( dsp, sub );
/* デスクトップに立つ */
XMoveResizeWindow( dsp, win, 0, height - iheight, iwidth, iheight);
XMoveResizeWindow( dsp, win, iwidth, height - iheight - iheight2/3, iwidth2, iheight2);
ここまでではまだ新しく追加したウィンドウは外形だけでまっ白なはずです。Exposeイベントで画像を描画してやらないといけません。
11.複数のウィンドウのイベント処理は?
まずは追加したウィンドウにもイベントマスクを設定します。
    /* イベントマスク */
XSelectInput( dsp, win, ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
XSelectInput( dsp, sub, ExposureMask );
イベントループ中では渡されるXEventの中にイベント発生源のウィンドウの識別子が含まれていますので、それを使って処理を振り分けます。
        case Expose: /* 再描画など */
if (event.xany.window == win) {
if (event.xexpose.count == 0) {
/* ここで再描画の度にイメージを描画する */
XPutImage( dsp, win, gc, image1, 0, 0, 0, 0, iwidth, iheight );
}
} else if (event.xany.window == sub) {
if (event.xexpose.count == 0) {
XPutImage( dsp, sub, gc, image2, 0, 0, 0, 0, iwidth2, iheight2 );
}
}

break;
これで吹き出しが表示されるはずですが、ここに来てマスク生成関数にバグが発覚!
maru10.jpg
どうやら画像の横幅が8の倍数でない時、表示が乱れてしまうみたいです。
というわけで、make_shape関数を修正。
/* XImageから1pixel=1byte のマスクを作成します */
char *make_shape( XImage *img )
{
char *data = img->data;
int bpp = img->bitmap_pad / 8;
int width = img->width;
int wlen = (width + 7) / 8;
int height = img->height;
int size = wlen * height;

int i, j;
char * ret;
ret = malloc(size);
if (ret == NULL) {
fprintf( stderr, "cannot malloc\n" );
exit( 1 );
}
memset( ret, 0, size );
for( i = 0; i < height; i++ ){
for( j = 0; j < width; j++ ){
int m = i * wlen;
int p = i * width;

for( j = 0; j < width; j++ ){
if (memcmp(data, data + (p + j) * bpp, bpp)) {
ret[m + j / 8] |= 1 << (j % 8);
}
}
}
}
return ret;
}
maru10c.jpg
直りました。
ここまでのソースコード
思ったより長くなってしまいました。
テキスト描画関連はおそらくもっと長くなると思うので今回はここまでにして続きは次回にします。

Comment






(編集・削除用)

Trackback

http://utau2009.blog114.fc2.com/tb.php/33-b039ebab

この記事にトラックバック(FC2Blog User)

Copyright © 飴屋/菖蒲

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。