#include #include #include #include #include /* 丸いマスクを作る */ char *maru_shape( int r) { int i, j; int r2 = r * 2; int rd = r * r; int w = (r2 + 7) / 8; char *ret = (char*)calloc(1, r2 * w); for (i = 0; i < r2; i++) { int m = i * w; int l1 = (i - r) ; l1 *= l1; for (j = 0; j < r2; j++) { int l2 = (j - r) ; l2 *= l2; if (l1 + l2 <= rd) { ret[m + j / 8] |= 1 << (j % 8); } } } return ret; } /* ウィンドウのタイトルバーを消す */ void change_prop(Display *display, Window window) { #define MWM_HINTS_FUNCTIONS (1L << 0) #define MWM_HINTS_DECORATIONS (1L << 1) #define MWM_HINTS_INPUT_MODE (1L << 2) #define MWM_FUNC_MOVE (1L << 2) #define MWM_INPUT_MODELESS 0 struct { long flags; long functions; long decorations; long inputmode; } prop; prop.flags=MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS|MWM_HINTS_INPUT_MODE; prop.decorations=0; prop.functions=MWM_FUNC_MOVE; prop.inputmode=MWM_INPUT_MODELESS; Atom a=XInternAtom(display,"_MOTIF_WM_HINTS",0); XChangeProperty( display, window, a, a, 32, PropModeReplace, (unsigned char*)&prop, 4); } /* BMPファイルを読みこんで画像データなどを返します。*/ char *loadbmpfile(const char *filename, int *width, int *height, int *bitcount, int *linelen) { char *bmpdata; int i, j, k, size; int off, hs, w = 0, h = 0, bcnt = 0; int line; int pl = 0, bicomp = 0, clrused; char bm[3]; FILE *fi = fopen(filename,"rb"); bcnt = 0; if (fi) { fread(bm, 1, 2, fi); fread(&i , 4, 1, fi);//fsize fread(&i , 2, 2, fi); fread(&off , 4, 1, fi);//offset fread(&hs , 4, 1, fi);//hdsize if (hs == 40) { fread(&w , 4, 1, fi);//width fread(&h , 4, 1, fi);//height fread(&pl , 2, 1, fi);//planes fread(&bcnt , 2, 1, fi);//bitcount fread(&bicomp, 4, 1, fi);//biComp fread(&i , 4, 1, fi);//biSizeImage fread(&i , 4, 1, fi);//biXPixPerMeter fread(&i , 4, 1, fi);//biYPixPerMeter fread(&clrused , 4, 1, fi);//biClrUsed fread(&i , 4, 1, fi);//biClrImpotant } else { fread(&w , 2, 1, fi);//width fread(&h , 2, 1, fi);//height fread(&pl , 2, 1, fi);//planes fread(&bcnt , 2, 1, fi);//bitcount } line = w * (bcnt / 8); line = ((line + 3) / 4) * 4; size = line * h; if (size < 0) size = -size; bmpdata = (char*)malloc(size); fread(bmpdata, 1, size, fi); fclose(fi); } *bitcount = bcnt; *width = w; *height = h; *linelen = line; return bmpdata; } /* BMPファイルを読みこんでXImageを返す */ XImage *load_bmp(Display *d, const char *filename, int *imwidth, int *imheight) { char *bmpdata; int scrn = DefaultScreen(d); int depth = XDefaultDepth(d, 0); Colormap cmap = DefaultColormap(d, scrn); int width, height, bitcount, linelen, bpp; XImage *img; char *data; XColor color; int i, j, h; bmpdata = loadbmpfile(filename, &width, &height, &bitcount, &linelen); bpp = depth >= 24 ? 4 : 2; h = height; if (height < 0) height = -height; data = (char*)malloc(height * width * bpp); for (i = 0; i < height; i++) { int k = h < 0 ? i * linelen : (height - i -1) * linelen; int m = i * width * bpp; for (j = 0; j < width; j++) { int r = k + j*(bitcount/8); int s = m + j * bpp; memcpy(data+s, bmpdata+r, bpp); } } free(bmpdata); img = XCreateImage( d, CopyFromParent, depth, ZPixmap, 0, data, width, height, bpp*8, bpp*width ); *imwidth = width; *imheight = height; return img; } /* 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; } int main() { Display *dsp; Window win, sub; char *mask1, *mask2; Pixmap pm1, pm2; int screen, width, height; int iwidth, iheight, iwidth2, iheight2; GC gc; XImage *image1, *image2; int drag = 0, rx = 0, cx = 0; /* ディスプレイ */ dsp = XOpenDisplay( NULL ); /* イメージを読み込む */ image1 = load_bmp(dsp, "ameya2.bmp", &iwidth, &iheight); image2 = load_bmp(dsp, "balloon.bmp", &iwidth2, &iheight2); /* 画面サイズ */ screen = DefaultScreen(dsp); width = DisplayWidth(dsp, screen); height = DisplayHeight(dsp, screen); /* ウィンドウを生成 */ 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, sub, iwidth, height - iheight - iheight2/3, iwidth2, iheight2); cx = 0; /* グラフックコンテクスト */ gc = DefaultGC(dsp, 0); /* イベントマスク */ XSelectInput( dsp, win, ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask); XSelectInput( dsp, sub, ExposureMask ); XFlush( dsp ); /* アプリループ */ while (1) { XEvent event; XNextEvent( dsp, &event ); switch( event.type ){ 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; 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; } } XCloseDisplay( dsp ); }