x11_w3mimg.c (19449B)
1 /* $Id$ */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <ctype.h> 6 #include "config.h" 7 8 #if defined(USE_IMLIB) 9 #include <Imlib.h> 10 #elif defined(USE_IMLIB2) 11 #include <X11/Xlib.h> 12 #include <X11/Xutil.h> 13 #include <Imlib2.h> 14 #elif defined(USE_GDKPIXBUF) 15 #if defined(USE_GTK2) 16 #include <glib-object.h> 17 #include <gdk/gdk.h> 18 #include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h> 19 #else 20 #include <gdk-pixbuf/gdk-pixbuf-xlib.h> 21 #endif 22 #else 23 #error no Imlib and GdkPixbuf support 24 #endif 25 26 #include "w3mimg/w3mimg.h" 27 28 #define OFFSET_X 2 29 #define OFFSET_Y 2 30 31 struct x11_info { 32 Display *display; 33 Window window, parent; 34 unsigned long background_pixel; 35 GC imageGC; 36 #if defined(USE_IMLIB) 37 ImlibData *id; 38 #elif defined(USE_GDKPIXBUF) 39 int init_flag; 40 #endif 41 }; 42 43 #if defined(USE_GDKPIXBUF) 44 struct x11_image { 45 int total; 46 int no; 47 int wait; 48 int delay; 49 Pixmap *pixmap; 50 }; 51 52 #if defined(USE_GTK2) 53 static int 54 get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay) 55 { 56 GdkPixbufAnimationIter *iter; 57 int n, i, d = -1; 58 GTimeVal time; 59 60 g_get_current_time(&time); 61 iter = gdk_pixbuf_animation_get_iter(animation, &time); 62 *w = gdk_pixbuf_animation_get_width(animation); 63 *h = gdk_pixbuf_animation_get_height(animation); 64 for (i = 1; 65 gdk_pixbuf_animation_iter_on_currently_loading_frame(iter) != TRUE; 66 i++) { 67 int tmp; 68 tmp = gdk_pixbuf_animation_iter_get_delay_time(iter); 69 g_time_val_add(&time, tmp * 1000); 70 if (tmp > d) 71 d = tmp; 72 gdk_pixbuf_animation_iter_advance(iter, &time); 73 } 74 if (delay) 75 *delay = d; 76 g_object_unref(G_OBJECT(iter)); 77 n = i; 78 return n; 79 } 80 #else 81 static int 82 get_animation_size(GdkPixbufAnimation * animation, int *w, int *h, int *delay) 83 { 84 GList *frames; 85 int iw, ih, n, i, d = -1; 86 87 frames = gdk_pixbuf_animation_get_frames(animation); 88 n = gdk_pixbuf_animation_get_num_frames(animation); 89 *w = gdk_pixbuf_animation_get_width(animation); 90 *h = gdk_pixbuf_animation_get_height(animation); 91 for (i = 0; i < n; i++) { 92 GdkPixbufFrame *frame; 93 GdkPixbuf *pixbuf; 94 int tmp; 95 96 frame = (GdkPixbufFrame *) g_list_nth_data(frames, i); 97 tmp = gdk_pixbuf_frame_get_delay_time(frame); 98 if (tmp > d) 99 d = tmp; 100 pixbuf = gdk_pixbuf_frame_get_pixbuf(frame); 101 iw = gdk_pixbuf_frame_get_x_offset(frame) 102 + gdk_pixbuf_get_width(pixbuf); 103 ih = gdk_pixbuf_frame_get_y_offset(frame) 104 + gdk_pixbuf_get_height(pixbuf); 105 if (iw > *w) 106 *w = iw; 107 if (ih > *h) 108 *h = ih; 109 } 110 if (delay) 111 *delay = d; 112 return n; 113 } 114 #endif 115 #endif 116 117 static int 118 x11_init(w3mimg_op * self) 119 { 120 struct x11_info *xi; 121 if (self == NULL) 122 return 0; 123 xi = (struct x11_info *)self->priv; 124 if (xi == NULL) 125 return 0; 126 #if defined(USE_IMLIB) 127 if (!xi->id) { 128 xi->id = Imlib_init(xi->display); 129 if (!xi->id) 130 return 0; 131 } 132 #elif defined(USE_GDKPIXBUF) 133 if (!xi->init_flag) { 134 #if defined(USE_GTK2) 135 g_type_init(); 136 #endif 137 gdk_pixbuf_xlib_init(xi->display, 0); 138 xi->init_flag = TRUE; 139 } 140 #endif 141 if (!xi->imageGC) { 142 xi->imageGC = XCreateGC(xi->display, xi->parent, 0, NULL); 143 if (!xi->imageGC) 144 return 0; 145 } 146 return 1; 147 } 148 149 static int 150 x11_finish(w3mimg_op * self) 151 { 152 struct x11_info *xi; 153 if (self == NULL) 154 return 0; 155 xi = (struct x11_info *)self->priv; 156 if (xi == NULL) 157 return 0; 158 if (xi->imageGC) { 159 XFreeGC(xi->display, xi->imageGC); 160 xi->imageGC = NULL; 161 } 162 return 1; 163 } 164 165 static int 166 x11_clear(w3mimg_op * self, int x, int y, int w, int h) 167 { 168 struct x11_info *xi; 169 if (self == NULL) 170 return 0; 171 xi = (struct x11_info *)self->priv; 172 if (xi == NULL) 173 return 0; 174 175 if (x < 0) 176 x = 0; 177 if (y < 0) 178 y = 0; 179 180 XClearArea(xi->display, xi->window, x, y, w, h, False); 181 return 1; 182 } 183 184 static int 185 x11_active(w3mimg_op * self) 186 { 187 struct x11_info *xi; 188 if (self == NULL) 189 return 0; 190 xi = (struct x11_info *)self->priv; 191 if (xi == NULL) 192 return 0; 193 if (!xi->imageGC) 194 return 0; 195 return 1; 196 } 197 198 static void 199 x11_set_background(w3mimg_op * self, char *background) 200 { 201 XColor screen_def, exact_def; 202 struct x11_info *xi; 203 if (self == NULL) 204 return; 205 xi = (struct x11_info *)self->priv; 206 if (xi == NULL) 207 return; 208 209 if (background && 210 XAllocNamedColor(xi->display, DefaultColormap(xi->display, 0), 211 background, &screen_def, &exact_def)) 212 xi->background_pixel = screen_def.pixel; 213 else { 214 Pixmap p; 215 GC gc; 216 XImage *i; 217 218 p = XCreatePixmap(xi->display, xi->window, 1, 1, 219 DefaultDepth(xi->display, 0)); 220 gc = XCreateGC(xi->display, xi->window, 0, NULL); 221 if (!p || !gc) 222 exit(1); /* XXX */ 223 XCopyArea(xi->display, xi->window, p, gc, 224 (self->offset_x >= 1) ? (self->offset_x - 1) : 0, 225 (self->offset_y >= 1) ? (self->offset_y - 1) : 0, 226 1, 1, 0, 0); 227 i = XGetImage(xi->display, p, 0, 0, 1, 1, -1, ZPixmap); 228 if (!i) 229 exit(1); 230 xi->background_pixel = XGetPixel(i, 0, 0); 231 XDestroyImage(i); 232 XFreeGC(xi->display, gc); 233 XFreePixmap(xi->display, p); 234 } 235 } 236 237 static void 238 x11_sync(w3mimg_op * self) 239 { 240 struct x11_info *xi; 241 if (self == NULL) 242 return; 243 xi = (struct x11_info *)self->priv; 244 if (xi == NULL) 245 return; 246 XSync(xi->display, False); 247 } 248 249 static void 250 x11_close(w3mimg_op * self) 251 { 252 /* XCloseDisplay(xi->display); */ 253 } 254 255 #if defined(USE_GDKPIXBUF) 256 static struct x11_image * 257 x11_img_new(struct x11_info *xi, int w, int h, int n) 258 { 259 struct x11_image *img = NULL; 260 int i; 261 262 img = malloc(sizeof(*img)); 263 if (!img) 264 goto ERROR; 265 266 img->pixmap = calloc(n, sizeof(*(img->pixmap))); 267 if (!img->pixmap) 268 goto ERROR; 269 270 for (i = 0; i < n; i++) { 271 img->pixmap[i] = XCreatePixmap(xi->display, xi->parent, w, h, 272 DefaultDepth(xi->display, 0)); 273 if (!img->pixmap[i]) 274 goto ERROR; 275 276 XSetForeground(xi->display, xi->imageGC, xi->background_pixel); 277 XFillRectangle(xi->display, (Pixmap) img->pixmap[i], xi->imageGC, 0, 0, 278 w, h); 279 } 280 281 img->no = 0; 282 img->total = n; 283 img->wait = 0; 284 img->delay = -1; 285 286 return img; 287 ERROR: 288 if (img) { 289 if (img->pixmap) { 290 for (i = 0; i < n; i++) { 291 if (img->pixmap[i]) 292 XFreePixmap(xi->display, (Pixmap) img->pixmap[i]); 293 } 294 free(img->pixmap); 295 } 296 free(img); 297 } 298 return NULL; 299 } 300 301 static GdkPixbuf * 302 resize_image(GdkPixbuf * pixbuf, int width, int height) 303 { 304 GdkPixbuf *resized_pixbuf; 305 int w, h; 306 307 if (pixbuf == NULL) 308 return NULL; 309 w = gdk_pixbuf_get_width(pixbuf); 310 h = gdk_pixbuf_get_height(pixbuf); 311 if (width < 1 || height < 1) 312 return pixbuf; 313 if (w == width && h == height) 314 return pixbuf; 315 resized_pixbuf = 316 gdk_pixbuf_scale_simple(pixbuf, width, height, GDK_INTERP_BILINEAR); 317 if (resized_pixbuf == NULL) 318 return NULL; 319 return resized_pixbuf; 320 } 321 #endif 322 323 static int 324 x11_load_image(w3mimg_op * self, W3MImage * img, char *fname, int w, int h) 325 { 326 struct x11_info *xi; 327 #if defined(USE_IMLIB) 328 ImlibImage *im; 329 #elif defined(USE_IMLIB2) 330 Imlib_Image im; 331 #elif defined(USE_GDKPIXBUF) 332 GdkPixbufAnimation *animation; 333 int j, iw, ih, n, frame_num, delay = -1, max_anim; 334 double ratio_w, ratio_h; 335 struct x11_image *ximg; 336 Pixmap tmp_pixmap; 337 #if defined(USE_GTK2) 338 GdkPixbufAnimationIter *iter; 339 GTimeVal time; 340 #else 341 int i; 342 GList *frames; 343 #endif 344 #endif 345 346 if (self == NULL) 347 return 0; 348 xi = (struct x11_info *)self->priv; 349 if (xi == NULL) 350 return 0; 351 352 #if defined(USE_IMLIB) 353 im = Imlib_load_image(xi->id, fname); 354 if (!im) 355 return 0; 356 if (w <= 0) 357 w = im->rgb_width; 358 if (h <= 0) 359 h = im->rgb_height; 360 img->pixmap = (void *)XCreatePixmap(xi->display, xi->parent, w, h, 361 DefaultDepth(xi->display, 0)); 362 if (!img->pixmap) 363 return 0; 364 XSetForeground(xi->display, xi->imageGC, xi->background_pixel); 365 XFillRectangle(xi->display, (Pixmap) img->pixmap, xi->imageGC, 0, 0, w, h); 366 Imlib_paste_image(xi->id, im, (Pixmap) img->pixmap, 0, 0, w, h); 367 Imlib_kill_image(xi->id, im); 368 #elif defined(USE_IMLIB2) 369 im = imlib_load_image(fname); 370 if (!im) 371 return 0; 372 imlib_context_set_image(im); 373 if (w <= 0) 374 w = imlib_image_get_width(); 375 if (h <= 0) 376 h = imlib_image_get_height(); 377 img->pixmap = (void *)XCreatePixmap(xi->display, xi->parent, w, h, 378 DefaultDepth(xi->display, 0)); 379 if (!img->pixmap) 380 return 0; 381 XSetForeground(xi->display, xi->imageGC, xi->background_pixel); 382 XFillRectangle(xi->display, (Pixmap) img->pixmap, xi->imageGC, 0, 0, w, h); 383 imlib_context_set_display(xi->display); 384 imlib_context_set_visual(DefaultVisual(xi->display, 0)); 385 imlib_context_set_colormap(DefaultColormap(xi->display, 0)); 386 imlib_context_set_drawable((Drawable) img->pixmap); 387 imlib_render_image_on_drawable_at_size(0, 0, w, h); 388 imlib_free_image(); 389 #elif defined(USE_GDKPIXBUF) 390 max_anim = self->max_anim; 391 #if defined(USE_GTK2) 392 animation = gdk_pixbuf_animation_new_from_file(fname, NULL); 393 #else 394 animation = gdk_pixbuf_animation_new_from_file(fname); 395 #endif 396 if (!animation) 397 return 0; 398 frame_num = n = get_animation_size(animation, &iw, &ih, &delay); 399 if (delay <= 0) 400 max_anim = -1; 401 402 if (max_anim < 0) { 403 frame_num = (-max_anim > n) ? n : -max_anim; 404 } 405 else if (max_anim > 0) { 406 frame_num = n = (max_anim > n) ? n : max_anim; 407 } 408 409 if (w < 1 || h < 1) { 410 w = iw; 411 h = ih; 412 ratio_w = ratio_h = 1; 413 } 414 else { 415 ratio_w = 1.0 * w / iw; 416 ratio_h = 1.0 * h / ih; 417 } 418 tmp_pixmap = XCreatePixmap(xi->display, xi->parent, w, h, 419 DefaultDepth(xi->display, 0)); 420 XSetForeground(xi->display, xi->imageGC, xi->background_pixel); 421 XFillRectangle(xi->display, (Pixmap) tmp_pixmap, xi->imageGC, 0, 0, w, h); 422 if (!tmp_pixmap) { 423 #if defined(USE_GTK2) 424 g_object_unref(G_OBJECT(animation)); 425 #else 426 gdk_pixbuf_animation_unref(animation); 427 #endif 428 return 0; 429 } 430 ximg = x11_img_new(xi, w, h, frame_num); 431 if (!ximg) { 432 XFreePixmap(xi->display, tmp_pixmap); 433 #if defined(USE_GTK2) 434 g_object_unref(G_OBJECT(animation)); 435 #else 436 gdk_pixbuf_animation_unref(animation); 437 #endif 438 return 0; 439 } 440 #if defined(USE_GTK2) 441 g_get_current_time(&time); 442 iter = gdk_pixbuf_animation_get_iter(animation, &time); 443 444 if (max_anim < 0 && n > -max_anim) { 445 max_anim = n + max_anim; 446 for (j = 0; j < max_anim; j++) { 447 delay = gdk_pixbuf_animation_iter_get_delay_time(iter); 448 g_time_val_add(&time, delay * 1000); 449 gdk_pixbuf_animation_iter_advance(iter, &time); 450 } 451 } 452 for (j = 0; j < frame_num; j++) { 453 GdkPixbuf *org_pixbuf, *pixbuf; 454 455 org_pixbuf = gdk_pixbuf_animation_iter_get_pixbuf(iter); 456 delay = gdk_pixbuf_animation_iter_get_delay_time(iter); 457 pixbuf = resize_image(org_pixbuf, w, h); 458 459 if (delay > ximg->delay) 460 ximg->delay = delay; 461 462 gdk_pixbuf_xlib_render_to_drawable_alpha(pixbuf, 463 (Drawable) ximg->pixmap[j], 0, 464 0, 0, 0, w, h, 465 GDK_PIXBUF_ALPHA_BILEVEL, 1, 466 XLIB_RGB_DITHER_NORMAL, 0, 0); 467 if (org_pixbuf != pixbuf) 468 g_object_unref(G_OBJECT(pixbuf)); 469 g_time_val_add(&time, delay * 1000); 470 gdk_pixbuf_animation_iter_advance(iter, &time); 471 } 472 XFreePixmap(xi->display, tmp_pixmap); 473 g_object_unref(G_OBJECT(animation)); 474 475 #else 476 frames = gdk_pixbuf_animation_get_frames(animation); 477 478 for (j = 0; j < n; j++) { 479 GdkPixbufFrame *frame; 480 GdkPixbuf *org_pixbuf, *pixbuf; 481 int width, height, ofstx, ofsty; 482 483 if (max_anim < 0) { 484 i = (j - n + frame_num > 0) ? (j - n + frame_num) : 0; 485 } 486 else { 487 i = j; 488 } 489 frame = (GdkPixbufFrame *) g_list_nth_data(frames, j); 490 org_pixbuf = gdk_pixbuf_frame_get_pixbuf(frame); 491 ofstx = gdk_pixbuf_frame_get_x_offset(frame); 492 ofsty = gdk_pixbuf_frame_get_y_offset(frame); 493 delay = gdk_pixbuf_frame_get_delay_time(frame); 494 width = gdk_pixbuf_get_width(org_pixbuf); 495 height = gdk_pixbuf_get_height(org_pixbuf); 496 497 if (ofstx == 0 && ofsty == 0 && width == w && height == h) { 498 pixbuf = resize_image(org_pixbuf, w, h); 499 } 500 else { 501 pixbuf = 502 resize_image(org_pixbuf, width * ratio_w, height * ratio_h); 503 ofstx *= ratio_w; 504 ofsty *= ratio_h; 505 } 506 width = gdk_pixbuf_get_width(pixbuf); 507 height = gdk_pixbuf_get_height(pixbuf); 508 509 if (delay > ximg->delay) 510 ximg->delay = delay; 511 512 XCopyArea(xi->display, tmp_pixmap, ximg->pixmap[i], 513 xi->imageGC, 0, 0, w, h, 0, 0); 514 gdk_pixbuf_xlib_render_to_drawable_alpha(pixbuf, 515 (Drawable) ximg->pixmap[i], 0, 516 0, ofstx, ofsty, width, 517 height, 518 GDK_PIXBUF_ALPHA_BILEVEL, 1, 519 XLIB_RGB_DITHER_NORMAL, 0, 0); 520 521 switch (gdk_pixbuf_frame_get_action(frame)) { 522 case GDK_PIXBUF_FRAME_RETAIN: 523 XCopyArea(xi->display, ximg->pixmap[i], tmp_pixmap, 524 xi->imageGC, 0, 0, w, h, 0, 0); 525 break; 526 case GDK_PIXBUF_FRAME_DISPOSE: 527 XSetForeground(xi->display, xi->imageGC, xi->background_pixel); 528 XFillRectangle(xi->display, tmp_pixmap, xi->imageGC, 529 0, 0, w, h); 530 break; 531 case GDK_PIXBUF_FRAME_REVERT: 532 XCopyArea(xi->display, ximg->pixmap[0], tmp_pixmap, 533 xi->imageGC, 0, 0, w, h, 0, 0); 534 break; 535 default: 536 XCopyArea(xi->display, ximg->pixmap[0], tmp_pixmap, 537 xi->imageGC, 0, 0, w, h, 0, 0); 538 break; 539 } 540 541 542 if (org_pixbuf != pixbuf) 543 gdk_pixbuf_finalize(pixbuf); 544 545 } 546 XFreePixmap(xi->display, tmp_pixmap); 547 gdk_pixbuf_animation_unref(animation); 548 #endif 549 img->pixmap = ximg; 550 #endif 551 552 img->width = w; 553 img->height = h; 554 return 1; 555 } 556 557 static int 558 x11_show_image(w3mimg_op * self, W3MImage * img, int sx, int sy, int sw, 559 int sh, int x, int y) 560 { 561 struct x11_info *xi; 562 #if defined(USE_GDKPIXBUF) 563 struct x11_image *ximg = img->pixmap; 564 int i; 565 #endif 566 if (self == NULL) 567 return 0; 568 569 if (img->pixmap == NULL) 570 return 0; 571 572 xi = (struct x11_info *)self->priv; 573 if (xi == NULL) 574 return 0; 575 576 #if defined(USE_IMLIB) || defined(USE_IMLIB2) 577 XCopyArea(xi->display, (Pixmap) img->pixmap, xi->window, xi->imageGC, 578 sx, sy, 579 (sw ? sw : img->width), 580 (sh ? sh : img->height), x + self->offset_x, y + self->offset_y); 581 #elif defined(USE_GDKPIXBUF) 582 #define WAIT_CNT 4 583 if (ximg->delay <= 0) 584 i = ximg->total - 1; 585 else 586 i = ximg->no; 587 XCopyArea(xi->display, ximg->pixmap[i], xi->window, xi->imageGC, 588 sx, sy, 589 (sw ? sw : img->width), 590 (sh ? sh : img->height), x + self->offset_x, y + self->offset_y); 591 if (ximg->total > 1) { 592 if (ximg->wait > WAIT_CNT) { 593 ximg->wait = 0; 594 if (i < ximg->total - 1) 595 ximg->no = i + 1; 596 else 597 ximg->no = 0; 598 } 599 ximg->wait += 1; 600 } 601 #endif 602 return 1; 603 } 604 605 static void 606 x11_free_image(w3mimg_op * self, W3MImage * img) 607 { 608 struct x11_info *xi; 609 if (self == NULL) 610 return; 611 xi = (struct x11_info *)self->priv; 612 if (xi == NULL) 613 return; 614 #if defined(USE_IMLIB) || defined(USE_IMLIB2) 615 if (img && img->pixmap) { 616 XFreePixmap(xi->display, (Pixmap) img->pixmap); 617 img->pixmap = NULL; 618 img->width = 0; 619 img->height = 0; 620 } 621 #elif defined(USE_GDKPIXBUF) 622 if (img && img->pixmap) { 623 struct x11_image *ximg = img->pixmap; 624 int i, n; 625 if (ximg->pixmap) { 626 n = ximg->total; 627 for (i = 0; i < n; i++) { 628 if (ximg->pixmap[i]) 629 XFreePixmap(xi->display, (Pixmap) ximg->pixmap[i]); 630 } 631 free(ximg->pixmap); 632 } 633 free(ximg); 634 img->pixmap = NULL; 635 img->width = 0; 636 img->height = 0; 637 } 638 #endif 639 } 640 641 static int 642 x11_get_image_size(w3mimg_op * self, W3MImage * img, char *fname, int *w, 643 int *h) 644 { 645 struct x11_info *xi; 646 #if defined(USE_IMLIB) 647 ImlibImage *im; 648 #elif defined(USE_IMLIB2) 649 Imlib_Image im; 650 #elif defined(USE_GDKPIXBUF) 651 GdkPixbufAnimation *animation; 652 #endif 653 654 if (self == NULL) 655 return 0; 656 xi = (struct x11_info *)self->priv; 657 if (xi == NULL) 658 return 0; 659 660 #if defined(USE_IMLIB) 661 im = Imlib_load_image(xi->id, fname); 662 if (!im) 663 return 0; 664 665 *w = im->rgb_width; 666 *h = im->rgb_height; 667 Imlib_kill_image(xi->id, im); 668 #elif defined(USE_IMLIB2) 669 im = imlib_load_image(fname); 670 if (im == NULL) 671 return 0; 672 673 imlib_context_set_image(im); 674 *w = imlib_image_get_width(); 675 *h = imlib_image_get_height(); 676 imlib_free_image(); 677 #elif defined(USE_GDKPIXBUF) 678 #if defined(USE_GTK2) 679 animation = gdk_pixbuf_animation_new_from_file(fname, NULL); 680 #else 681 animation = gdk_pixbuf_animation_new_from_file(fname); 682 #endif 683 if (!animation) 684 return 0; 685 686 get_animation_size(animation, w, h, NULL); 687 #if defined(USE_GTK2) 688 g_object_unref(G_OBJECT(animation)); 689 #else 690 gdk_pixbuf_animation_unref(animation); 691 #endif 692 #endif 693 return 1; 694 } 695 696 /* *INDENT-OFF* */ 697 /* 698 xterm/kterm/hanterm/cxterm 699 top window (WINDOWID) 700 +- text window 701 +- scrollbar 702 rxvt/aterm/Eterm/wterm 703 top window (WINDOWID) 704 +- text window 705 +- scrollbar 706 +- menubar (etc.) 707 gnome-terminal 708 top window 709 +- text window (WINDOWID) 710 +- scrollbar 711 +- menubar 712 mlterm (-s) 713 top window 714 +- text window (WINDOWID) 715 +- scrollbar 716 mlterm 717 top window = text window (WINDOWID) 718 719 powershell 720 top window 721 +- window 722 | +- text window 723 | +- scrollbar 724 +- menubar (etc.) 725 dtterm 726 top window 727 +- window 728 +- window 729 | +- window 730 | +- text window 731 | +- scrollbar 732 +- menubar 733 hpterm 734 top window 735 +- window 736 +- text window 737 +- scrollbar 738 +- (etc.) 739 */ 740 /* *INDENT-ON* */ 741 742 w3mimg_op * 743 w3mimg_x11open() 744 { 745 w3mimg_op *wop = NULL; 746 struct x11_info *xi = NULL; 747 char *id; 748 int revert, i; 749 unsigned int nchildren; 750 XWindowAttributes attr; 751 Window root, *children; 752 753 wop = (w3mimg_op *) malloc(sizeof(w3mimg_op)); 754 if (wop == NULL) 755 return NULL; 756 memset(wop, 0, sizeof(w3mimg_op)); 757 758 xi = (struct x11_info *)malloc(sizeof(struct x11_info)); 759 if (xi == NULL) 760 goto error; 761 memset(xi, 0, sizeof(struct x11_info)); 762 763 xi->display = XOpenDisplay(NULL); 764 if (xi->display == NULL) { 765 goto error; 766 } 767 if ((id = getenv("WINDOWID")) != NULL) 768 xi->window = (Window) atoi(id); 769 else 770 XGetInputFocus(xi->display, &xi->window, &revert); 771 if (!xi->window) 772 exit(1); 773 774 XGetWindowAttributes(xi->display, xi->window, &attr); 775 wop->width = attr.width; 776 wop->height = attr.height; 777 778 while (1) { 779 Window p_window; 780 781 XQueryTree(xi->display, xi->window, &root, &xi->parent, 782 &children, &nchildren); 783 p_window = xi->window; 784 for (i = 0; i < nchildren; i++) { 785 XGetWindowAttributes(xi->display, children[i], &attr); 786 if (attr.width > wop->width * 0.7 && 787 attr.height > wop->height * 0.7) { 788 /* maybe text window */ 789 wop->width = attr.width; 790 wop->height = attr.height; 791 xi->window = children[i]; 792 } 793 } 794 if (p_window == xi->window) 795 break; 796 } 797 wop->offset_x = OFFSET_X; 798 for (i = 0; i < nchildren; i++) { 799 XGetWindowAttributes(xi->display, children[i], &attr); 800 if (attr.x <= 0 && attr.width < 30 && attr.height > wop->height * 0.7) { 801 /* scrollbar of xterm/kterm ? */ 802 wop->offset_x += attr.x + attr.width + attr.border_width * 2; 803 break; 804 } 805 } 806 wop->offset_y = OFFSET_Y; 807 808 wop->priv = xi; 809 810 wop->init = x11_init; 811 wop->finish = x11_finish; 812 wop->active = x11_active; 813 wop->set_background = x11_set_background; 814 wop->sync = x11_sync; 815 wop->close = x11_close; 816 wop->clear = x11_clear; 817 818 wop->load_image = x11_load_image; 819 wop->show_image = x11_show_image; 820 wop->free_image = x11_free_image; 821 wop->get_image_size = x11_get_image_size; 822 823 return wop; 824 error: 825 if (xi) 826 free(xi); 827 free(wop); 828 return NULL; 829 }