|
|
1.1 ! root 1: /* $Id: gtk-screen.c,v 1.3 2003/10/29 02:03:26 fredette Exp $ */ ! 2: ! 3: /* host/gtk/gtk-screen.c - GTK screen support: */ ! 4: ! 5: /* ! 6: * Copyright (c) 2003 Matt Fredette ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. All advertising materials mentioning features or use of this software ! 18: * must display the following acknowledgement: ! 19: * This product includes software developed by Matt Fredette. ! 20: * 4. The name of the author may not be used to endorse or promote products ! 21: * derived from this software without specific prior written permission. ! 22: * ! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 33: * POSSIBILITY OF SUCH DAMAGE. ! 34: */ ! 35: ! 36: #include <tme/common.h> ! 37: _TME_RCSID("$Id: gtk-screen.c,v 1.3 2003/10/29 02:03:26 fredette Exp $"); ! 38: ! 39: /* we are aware of the problems with gdk_image_new_bitmap, and we cope ! 40: with them, so we define GDK_ENABLE_BROKEN to get its prototype ! 41: under GTK 2: */ ! 42: #define GDK_ENABLE_BROKEN ! 43: ! 44: /* includes: */ ! 45: #include "gtk-display.h" ! 46: #include <stdlib.h> ! 47: ! 48: /* macros: */ ! 49: ! 50: /* the GTK 1.x gtk_image_new function is the GTK 2.x ! 51: gtk_image_new_from_image function: */ ! 52: #if GTK_MAJOR_VERSION == 1 ! 53: #define gtk_image_new_from_image gtk_image_new ! 54: #endif /* GTK_MAJOR_VERSION == 1 */ ! 55: ! 56: /* the GTK screens update thread: */ ! 57: void ! 58: _tme_gtk_screen_th_update(struct tme_gtk_display *display) ! 59: { ! 60: struct tme_gtk_screen *screen; ! 61: struct tme_fb_connection *conn_fb_other; ! 62: int changed; ! 63: int rc; ! 64: ! 65: /* loop forever: */ ! 66: for (;;) { ! 67: ! 68: /* lock the mutex: */ ! 69: tme_mutex_lock(&display->tme_gtk_display_mutex); ! 70: ! 71: /* loop over all screens: */ ! 72: for (screen = display->tme_gtk_display_screens; ! 73: screen != NULL; ! 74: screen = screen->tme_gtk_screen_next) { ! 75: ! 76: /* skip this screen if it's unconnected: */ ! 77: if (screen->tme_gtk_screen_fb == NULL) { ! 78: continue; ! 79: } ! 80: ! 81: /* get the other side of this connection: */ ! 82: conn_fb_other ! 83: = ((struct tme_fb_connection *) ! 84: screen->tme_gtk_screen_fb->tme_fb_connection.tme_connection_other); ! 85: ! 86: /* if the framebuffer has an update function, call it: */ ! 87: if (conn_fb_other->tme_fb_connection_update != NULL) { ! 88: rc = (*conn_fb_other->tme_fb_connection_update)(conn_fb_other); ! 89: assert (rc == TME_OK); ! 90: } ! 91: ! 92: /* translate this framebuffer's contents: */ ! 93: changed = (*screen->tme_gtk_screen_fb_xlat) ! 94: (((struct tme_fb_connection *) ! 95: screen->tme_gtk_screen_fb->tme_fb_connection.tme_connection_other), ! 96: screen->tme_gtk_screen_fb); ! 97: ! 98: /* if those contents changed, redraw the widget: */ ! 99: if (changed) { ! 100: gtk_widget_queue_draw(screen->tme_gtk_screen_gtkimage); ! 101: } ! 102: } ! 103: ! 104: /* unlock the mutex: */ ! 105: tme_mutex_unlock(&display->tme_gtk_display_mutex); ! 106: ! 107: /* update again in .5 seconds: */ ! 108: tme_thread_sleep_yield(0, 500000); ! 109: } ! 110: /* NOTREACHED */ ! 111: } ! 112: ! 113: /* this recovers the bits-per-pixel value for a GdkImage: */ ! 114: static unsigned int ! 115: _tme_gtk_gdkimage_bipp(GdkImage *image) ! 116: { ! 117: unsigned int bipp, total_bits_halved; ! 118: ! 119: total_bits_halved = image->bpl; ! 120: total_bits_halved = (total_bits_halved * 8) / 2; ! 121: for (bipp = image->depth; ! 122: (bipp * image->width) <= total_bits_halved; ! 123: bipp <<= 1); ! 124: return (bipp); ! 125: } ! 126: ! 127: /* this recovers the scanline-pad value for a GdkImage: */ ! 128: static unsigned int ! 129: _tme_gtk_gdkimage_scanline_pad(GdkImage *image) ! 130: { ! 131: ! 132: if ((image->bpl % sizeof(tme_uint32_t)) == 0) { ! 133: return (32); ! 134: } ! 135: if ((image->bpl % sizeof(tme_uint16_t)) == 0) { ! 136: return (16); ! 137: } ! 138: if ((image->bpl % sizeof(tme_uint8_t)) == 0) { ! 139: return (8); ! 140: } ! 141: } ! 142: ! 143: /* this is called for a mode change: */ ! 144: int ! 145: _tme_gtk_screen_mode_change(struct tme_fb_connection *conn_fb) ! 146: { ! 147: struct tme_gtk_display *display; ! 148: struct tme_gtk_screen *screen; ! 149: struct tme_fb_connection *conn_fb_other; ! 150: struct tme_fb_xlat fb_xlat_q; ! 151: const struct tme_fb_xlat *fb_xlat_a; ! 152: int scale; ! 153: unsigned long fb_area, avail_area, percentage; ! 154: gint width, height; ! 155: GdkImage *gdkimage; ! 156: GdkVisual *visual; ! 157: int color_count, color_i; ! 158: GdkColor color; ! 159: ! 160: /* recover our data structures: */ ! 161: display = conn_fb->tme_fb_connection.tme_connection_element->tme_element_private; ! 162: conn_fb_other = (struct tme_fb_connection *) conn_fb->tme_fb_connection.tme_connection_other; ! 163: ! 164: /* lock our mutex: */ ! 165: tme_mutex_lock(&display->tme_gtk_display_mutex); ! 166: ! 167: /* find the screen that this framebuffer connection references: */ ! 168: for (screen = display->tme_gtk_display_screens; ! 169: (screen != NULL ! 170: && screen->tme_gtk_screen_fb != conn_fb); ! 171: screen = screen->tme_gtk_screen_next); ! 172: assert (screen != NULL); ! 173: ! 174: /* if the user hasn't specified a scaling, pick one: */ ! 175: scale = screen->tme_gtk_screen_fb_scale; ! 176: if (scale < 0) { ! 177: ! 178: /* calulate the areas, in square pixels, of the emulated ! 179: framebuffer and the host's screen: */ ! 180: fb_area = (conn_fb_other->tme_fb_connection_width ! 181: * conn_fb_other->tme_fb_connection_height); ! 182: avail_area = (gdk_screen_width() ! 183: * gdk_screen_height()); ! 184: ! 185: /* see what percentage of the host's screen would be taken up by ! 186: an unscaled emulated framebuffer: */ ! 187: percentage = (fb_area * 100) / avail_area; ! 188: ! 189: /* if this is at least 70%, halve the emulated framebuffer, else ! 190: if this is 30% or less, double the emulated framebuffer: */ ! 191: if (percentage >= 70) { ! 192: scale = TME_FB_XLAT_SCALE_HALF; ! 193: } ! 194: else if (percentage <= 30) { ! 195: scale = TME_FB_XLAT_SCALE_DOUBLE; ! 196: } ! 197: else { ! 198: scale = TME_FB_XLAT_SCALE_NONE; ! 199: } ! 200: ! 201: screen->tme_gtk_screen_fb_scale = -scale; ! 202: } ! 203: ! 204: /* get the system's default visual: */ ! 205: visual = gdk_visual_get_system(); ! 206: ! 207: /* create the new GdkImage for the screen: */ ! 208: width = ((conn_fb_other->tme_fb_connection_width ! 209: * scale) ! 210: / TME_FB_XLAT_SCALE_NONE); ! 211: height = ((conn_fb_other->tme_fb_connection_height ! 212: * scale) ! 213: / TME_FB_XLAT_SCALE_NONE); ! 214: gdkimage = gdk_image_new(GDK_IMAGE_FASTEST, ! 215: visual, ! 216: width, ! 217: height); ! 218: ! 219: /* set the new image on the image widget: */ ! 220: gtk_image_set(GTK_IMAGE(screen->tme_gtk_screen_gtkimage), ! 221: gdkimage, ! 222: NULL); ! 223: ! 224: /* destroy the previous gdkimage and remember the new one: */ ! 225: gdk_image_destroy(screen->tme_gtk_screen_gdkimage); ! 226: screen->tme_gtk_screen_gdkimage = gdkimage; ! 227: ! 228: /* update our framebuffer connection: */ ! 229: conn_fb->tme_fb_connection_width = width; ! 230: conn_fb->tme_fb_connection_height = height; ! 231: conn_fb->tme_fb_connection_depth = gdkimage->depth; ! 232: conn_fb->tme_fb_connection_bits_per_pixel = _tme_gtk_gdkimage_bipp(gdkimage); ! 233: conn_fb->tme_fb_connection_skipx = 0; ! 234: conn_fb->tme_fb_connection_scanline_pad = _tme_gtk_gdkimage_scanline_pad(gdkimage); ! 235: conn_fb->tme_fb_connection_order = (gdkimage->byte_order == GDK_LSB_FIRST ! 236: ? TME_ENDIAN_LITTLE ! 237: : TME_ENDIAN_BIG); ! 238: conn_fb->tme_fb_connection_buffer = gdkimage->mem; ! 239: ! 240: /* when we're showing a framebuffer with a depth of one, we need to ! 241: provide the pixel values for black and white, and, if we're ! 242: halving, three shades of gray in between: */ ! 243: if (conn_fb->tme_fb_connection_depth1_map != NULL) { ! 244: ! 245: /* XXX we almost certainly should free colors ! 246: previously allocated: */ ! 247: tme_free(conn_fb->tme_fb_connection_depth1_map); ! 248: } ! 249: if (conn_fb_other->tme_fb_connection_depth == 1) { ! 250: ! 251: /* allocate the depth-one map: */ ! 252: color_count = (scale == TME_FB_XLAT_SCALE_HALF ! 253: ? 5 ! 254: : 2); ! 255: conn_fb->tme_fb_connection_depth1_map ! 256: = tme_new(tme_uint32_t, color_count); ! 257: ! 258: /* allocate the colors it needs: */ ! 259: for (color_i = 0; ! 260: color_i < color_count; ! 261: color_i++) { ! 262: ! 263: /* set the RGB values: */ ! 264: color.red ! 265: = (((65535UL * color_i) / (color_count - 1)) ! 266: ^ screen->tme_gtk_screen_mono_invert_mask); ! 267: color.green = color.red; ! 268: color.blue = color.red; ! 269: ! 270: /* allocate the color: */ ! 271: gdk_colormap_alloc_color(gdk_colormap_get_system(), ! 272: &color, ! 273: FALSE, ! 274: TRUE); ! 275: conn_fb->tme_fb_connection_depth1_map[color_i] ! 276: = color.pixel; ! 277: } ! 278: } ! 279: else { ! 280: conn_fb->tme_fb_connection_depth1_map = NULL; ! 281: } ! 282: ! 283: /* compose the framebuffer translation question: */ ! 284: fb_xlat_q.tme_fb_xlat_width = conn_fb_other->tme_fb_connection_width; ! 285: fb_xlat_q.tme_fb_xlat_height = conn_fb_other->tme_fb_connection_height; ! 286: fb_xlat_q.tme_fb_xlat_scale = (unsigned int) scale; ! 287: fb_xlat_q.tme_fb_xlat_src_depth = conn_fb_other->tme_fb_connection_depth; ! 288: fb_xlat_q.tme_fb_xlat_src_bits_per_pixel = conn_fb_other->tme_fb_connection_bits_per_pixel; ! 289: fb_xlat_q.tme_fb_xlat_src_skipx = conn_fb_other->tme_fb_connection_skipx; ! 290: fb_xlat_q.tme_fb_xlat_src_scanline_pad = conn_fb_other->tme_fb_connection_scanline_pad; ! 291: fb_xlat_q.tme_fb_xlat_src_order = conn_fb_other->tme_fb_connection_order; ! 292: fb_xlat_q.tme_fb_xlat_dst_depth = conn_fb->tme_fb_connection_depth; ! 293: fb_xlat_q.tme_fb_xlat_dst_bits_per_pixel = conn_fb->tme_fb_connection_bits_per_pixel; ! 294: fb_xlat_q.tme_fb_xlat_dst_skipx = conn_fb->tme_fb_connection_skipx; ! 295: fb_xlat_q.tme_fb_xlat_dst_scanline_pad = conn_fb->tme_fb_connection_scanline_pad; ! 296: fb_xlat_q.tme_fb_xlat_dst_order = conn_fb->tme_fb_connection_order; ! 297: ! 298: /* ask the framebuffer translation question: */ ! 299: fb_xlat_a = tme_fb_xlat_best(&fb_xlat_q); ! 300: ! 301: /* if this translation isn't optimal, log a note: */ ! 302: if (!tme_fb_xlat_is_optimal(fb_xlat_a)) { ! 303: tme_log(&display->tme_gtk_display_element->tme_element_log_handle, 0, TME_OK, ! 304: (&display->tme_gtk_display_element->tme_element_log_handle, ! 305: _("no optimal framebuffer translation function available"))); ! 306: } ! 307: ! 308: /* save the translation function: */ ! 309: screen->tme_gtk_screen_fb_xlat = fb_xlat_a->tme_fb_xlat_func; ! 310: ! 311: /* force the next translation to do a complete redraw: */ ! 312: tme_fb_xlat_redraw(conn_fb_other); ! 313: ! 314: /* unlock our mutex: */ ! 315: tme_mutex_unlock(&display->tme_gtk_display_mutex); ! 316: ! 317: /* done: */ ! 318: return (TME_OK); ! 319: } ! 320: ! 321: /* this sets the screen size: */ ! 322: static void ! 323: _tme_gtk_screen_scale_set(GtkWidget *widget, ! 324: struct tme_gtk_screen *screen, ! 325: int scale_new) ! 326: { ! 327: struct tme_gtk_display *display; ! 328: int scale_old; ! 329: int rc; ! 330: ! 331: /* return now if the menu item isn't active: */ ! 332: if (!GTK_CHECK_MENU_ITEM(GTK_MENU_ITEM(widget))->active) { ! 333: return; ! 334: } ! 335: ! 336: /* get the display: */ ! 337: display = screen->tme_gtk_screen_display; ! 338: ! 339: /* lock our mutex: */ ! 340: tme_mutex_lock(&display->tme_gtk_display_mutex); ! 341: ! 342: /* get the old scaling and set the new scaling: */ ! 343: scale_old = screen->tme_gtk_screen_fb_scale; ! 344: if (scale_old < 0 ! 345: && scale_new < 0) { ! 346: scale_new = scale_old; ! 347: } ! 348: screen->tme_gtk_screen_fb_scale = scale_new; ! 349: ! 350: /* unlock our mutex: */ ! 351: tme_mutex_unlock(&display->tme_gtk_display_mutex); ! 352: ! 353: /* call the mode change function if the scaling has changed: */ ! 354: if (scale_new != scale_old) { ! 355: rc = _tme_gtk_screen_mode_change(screen->tme_gtk_screen_fb); ! 356: assert (rc == TME_OK); ! 357: } ! 358: } ! 359: ! 360: /* this sets the screen scaling to default: */ ! 361: static void ! 362: _tme_gtk_screen_scale_default(GtkWidget *widget, ! 363: struct tme_gtk_screen *screen) ! 364: { ! 365: _tme_gtk_screen_scale_set(widget, ! 366: screen, ! 367: -TME_FB_XLAT_SCALE_NONE); ! 368: } ! 369: ! 370: /* this sets the screen scaling to half: */ ! 371: static void ! 372: _tme_gtk_screen_scale_half(GtkWidget *widget, ! 373: struct tme_gtk_screen *screen) ! 374: { ! 375: _tme_gtk_screen_scale_set(widget, ! 376: screen, ! 377: TME_FB_XLAT_SCALE_HALF); ! 378: } ! 379: ! 380: /* this sets the screen scaling to none: */ ! 381: static void ! 382: _tme_gtk_screen_scale_none(GtkWidget *widget, ! 383: struct tme_gtk_screen *screen) ! 384: { ! 385: _tme_gtk_screen_scale_set(widget, ! 386: screen, ! 387: TME_FB_XLAT_SCALE_NONE); ! 388: } ! 389: ! 390: /* this sets the screen scaling to double: */ ! 391: static void ! 392: _tme_gtk_screen_scale_double(GtkWidget *widget, ! 393: struct tme_gtk_screen *screen) ! 394: { ! 395: _tme_gtk_screen_scale_set(widget, ! 396: screen, ! 397: TME_FB_XLAT_SCALE_DOUBLE); ! 398: } ! 399: ! 400: /* this makes a new screen: */ ! 401: struct tme_gtk_screen * ! 402: _tme_gtk_screen_new(struct tme_gtk_display *display) ! 403: { ! 404: struct tme_gtk_screen *screen, **_prev; ! 405: GtkWidget *menu_bar; ! 406: GtkWidget *menu; ! 407: GtkWidget *submenu; ! 408: GtkWidget *menu_item; ! 409: GtkWidget **_menu_item; ! 410: GSList *menu_group; ! 411: tme_uint8_t *bitmap_data; ! 412: unsigned int y; ! 413: const char *menu_label; ! 414: GtkSignalFunc menu_func; ! 415: int i; ! 416: #define BLANK_SIDE (16 * 8) ! 417: ! 418: /* create the new screen and link it in: */ ! 419: for (_prev = &display->tme_gtk_display_screens; ! 420: (screen = *_prev) != NULL; ! 421: _prev = &screen->tme_gtk_screen_next); ! 422: screen = *_prev = tme_new0(struct tme_gtk_screen, 1); ! 423: ! 424: /* the backpointer to the display: */ ! 425: screen->tme_gtk_screen_display = display; ! 426: ! 427: /* there is no framebuffer connection yet: */ ! 428: screen->tme_gtk_screen_fb = NULL; ! 429: ! 430: /* the user hasn't specified a scaling yet: */ ! 431: screen->tme_gtk_screen_fb_scale ! 432: = -TME_FB_XLAT_SCALE_NONE; ! 433: ! 434: /* XXX this should be controlled by an argument somewhere: */ ! 435: screen->tme_gtk_screen_mono_invert_mask = 0xffff; ! 436: ! 437: /* create the top-level window, and allow it to shrink, grow, ! 438: and auto-shrink: */ ! 439: screen->tme_gtk_screen_window ! 440: = gtk_window_new(GTK_WINDOW_TOPLEVEL); ! 441: gtk_window_set_policy(GTK_WINDOW(screen->tme_gtk_screen_window), ! 442: TRUE, TRUE, TRUE); ! 443: ! 444: /* create the outer vertical packing box: */ ! 445: screen->tme_gtk_screen_vbox0 ! 446: = gtk_vbox_new(FALSE, 0); ! 447: ! 448: /* add the outer vertical packing box to the window: */ ! 449: gtk_container_add(GTK_CONTAINER(screen->tme_gtk_screen_window), ! 450: screen->tme_gtk_screen_vbox0); ! 451: ! 452: /* create the menu bar and pack it into the outer vertical packing ! 453: box: */ ! 454: menu_bar = gtk_menu_bar_new (); ! 455: gtk_box_pack_start(GTK_BOX(screen->tme_gtk_screen_vbox0), ! 456: menu_bar, ! 457: FALSE, FALSE, 0); ! 458: gtk_widget_show(menu_bar); ! 459: ! 460: /* create the Screen menu: */ ! 461: menu = gtk_menu_new(); ! 462: ! 463: /* create the Screen scaling submenu: */ ! 464: submenu = gtk_menu_new(); ! 465: ! 466: /* create the Screen scaling submenu options: */ ! 467: menu_group = NULL; ! 468: for (i = 0;; i++) { ! 469: if (i == 0) { ! 470: menu_label = _("Default"); ! 471: _menu_item = &screen->tme_gtk_screen_scale_default; ! 472: menu_func = GTK_SIGNAL_FUNC(_tme_gtk_screen_scale_default); ! 473: } ! 474: else if (i == 1) { ! 475: menu_label = _("Half"); ! 476: _menu_item = &screen->tme_gtk_screen_scale_half; ! 477: menu_func = GTK_SIGNAL_FUNC(_tme_gtk_screen_scale_half); ! 478: } ! 479: else if (i == 2) { ! 480: menu_label = _("Full"); ! 481: _menu_item = NULL; ! 482: menu_func = GTK_SIGNAL_FUNC(_tme_gtk_screen_scale_none); ! 483: } ! 484: else if (i == 3) { ! 485: menu_label = _("Double"); ! 486: _menu_item = NULL; ! 487: menu_func = GTK_SIGNAL_FUNC(_tme_gtk_screen_scale_double); ! 488: } ! 489: else { ! 490: break; ! 491: } ! 492: menu_item ! 493: = gtk_radio_menu_item_new_with_label(menu_group, ! 494: menu_label); ! 495: if (_menu_item != NULL) { ! 496: *_menu_item = menu_item; ! 497: } ! 498: menu_group ! 499: = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(menu_item)); ! 500: gtk_signal_connect(GTK_OBJECT(menu_item), ! 501: "activate", ! 502: menu_func, ! 503: (gpointer) screen); ! 504: gtk_menu_append(GTK_MENU(submenu), menu_item); ! 505: gtk_widget_show(menu_item); ! 506: } ! 507: ! 508: /* create the Screen scaling submenu item: */ ! 509: menu_item = gtk_menu_item_new_with_label(_("Scale")); ! 510: gtk_widget_show(menu_item); ! 511: gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), submenu); ! 512: gtk_menu_append(GTK_MENU(menu), menu_item); ! 513: ! 514: /* create the Screen menu bar item, attach the menu to it, and ! 515: attach the menu bar item to the menu bar: */ ! 516: menu_item = gtk_menu_item_new_with_label("Screen"); ! 517: gtk_widget_show(menu_item); ! 518: gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu); ! 519: gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), menu_item); ! 520: ! 521: /* create an event box for the framebuffer area: */ ! 522: screen->tme_gtk_screen_event_box ! 523: = gtk_event_box_new(); ! 524: ! 525: /* pack the event box into the outer vertical packing box: */ ! 526: gtk_box_pack_start(GTK_BOX(screen->tme_gtk_screen_vbox0), ! 527: screen->tme_gtk_screen_event_box, ! 528: FALSE, FALSE, 0); ! 529: ! 530: /* show the event box: */ ! 531: gtk_widget_show(screen->tme_gtk_screen_event_box); ! 532: ! 533: /* create a GdkImage of an alternating-bits area. we must use ! 534: malloc() here since this memory will end up as part of an XImage, ! 535: and X will call free() on it: */ ! 536: bitmap_data = (tme_uint8_t *) ! 537: malloc((BLANK_SIDE * BLANK_SIDE) / 8); ! 538: assert(bitmap_data != NULL); ! 539: for (y = 0; ! 540: y < BLANK_SIDE; ! 541: y++) { ! 542: memset(bitmap_data ! 543: + (y * BLANK_SIDE / 8), ! 544: (y & 1 ! 545: ? 0x33 ! 546: : 0xcc), ! 547: (BLANK_SIDE / 8)); ! 548: } ! 549: screen->tme_gtk_screen_gdkimage ! 550: = gdk_image_new_bitmap(gdk_visual_get_system(), ! 551: bitmap_data, ! 552: BLANK_SIDE, ! 553: BLANK_SIDE); ! 554: ! 555: /* create the GtkImage for the framebuffer area: */ ! 556: screen->tme_gtk_screen_gtkimage ! 557: = gtk_image_new_from_image(screen->tme_gtk_screen_gdkimage, NULL); ! 558: ! 559: /* add the GtkImage to the event box: */ ! 560: gtk_container_add(GTK_CONTAINER(screen->tme_gtk_screen_event_box), ! 561: screen->tme_gtk_screen_gtkimage); ! 562: ! 563: /* show the GtkImage: */ ! 564: gtk_widget_show(screen->tme_gtk_screen_gtkimage); ! 565: ! 566: /* show the outer vertical packing box: */ ! 567: gtk_widget_show(screen->tme_gtk_screen_vbox0); ! 568: ! 569: /* show the top-level window: */ ! 570: gtk_widget_show(screen->tme_gtk_screen_window); ! 571: ! 572: /* there is no translation function: */ ! 573: screen->tme_gtk_screen_fb_xlat = NULL; ! 574: ! 575: /* attach the mouse to this screen: */ ! 576: _tme_gtk_mouse_attach(screen); ! 577: ! 578: /* attach the keyboard to this screen: */ ! 579: _tme_gtk_keyboard_attach(screen); ! 580: ! 581: return (screen); ! 582: } ! 583: ! 584: /* this breaks a framebuffer connection: */ ! 585: static int ! 586: _tme_gtk_screen_connection_break(struct tme_connection *conn, unsigned int state) ! 587: { ! 588: abort(); ! 589: } ! 590: ! 591: /* this makes a new framebuffer connection: */ ! 592: static int ! 593: _tme_gtk_screen_connection_make(struct tme_connection *conn, ! 594: unsigned int state) ! 595: { ! 596: struct tme_gtk_display *display; ! 597: struct tme_gtk_screen *screen; ! 598: struct tme_fb_connection *conn_fb; ! 599: struct tme_fb_connection *conn_fb_other; ! 600: ! 601: /* recover our data structures: */ ! 602: display = (struct tme_gtk_display *) conn->tme_connection_element->tme_element_private; ! 603: conn_fb = (struct tme_fb_connection *) conn; ! 604: conn_fb_other = (struct tme_fb_connection *) conn->tme_connection_other; ! 605: ! 606: /* both sides must be framebuffer connections: */ ! 607: assert(conn->tme_connection_type ! 608: == TME_CONNECTION_FRAMEBUFFER); ! 609: assert(conn->tme_connection_other->tme_connection_type ! 610: == TME_CONNECTION_FRAMEBUFFER); ! 611: ! 612: /* we're always set up to answer calls across the connection, so we ! 613: only have to do work when the connection has gone full, namely ! 614: taking the other side of the connection: */ ! 615: if (state == TME_CONNECTION_FULL) { ! 616: ! 617: /* lock our mutex: */ ! 618: tme_mutex_lock(&display->tme_gtk_display_mutex); ! 619: ! 620: /* if our initial screen is already connected, make a new screen: */ ! 621: screen = display->tme_gtk_display_screens; ! 622: if (screen->tme_gtk_screen_fb != NULL) { ! 623: screen = _tme_gtk_screen_new(display); ! 624: } ! 625: ! 626: /* save our connection: */ ! 627: screen->tme_gtk_screen_fb = conn_fb; ! 628: ! 629: /* unlock our mutex: */ ! 630: tme_mutex_unlock(&display->tme_gtk_display_mutex); ! 631: ! 632: /* call our mode change function: */ ! 633: _tme_gtk_screen_mode_change(conn_fb); ! 634: } ! 635: ! 636: return (TME_OK); ! 637: } ! 638: ! 639: /* this makes a new connection side for a GTK screen: */ ! 640: int ! 641: _tme_gtk_screen_connections_new(struct tme_gtk_display *display, ! 642: struct tme_connection **_conns) ! 643: { ! 644: struct tme_fb_connection *conn_fb; ! 645: struct tme_connection *conn; ! 646: ! 647: /* allocate a new framebuffer connection: */ ! 648: conn_fb = tme_new0(struct tme_fb_connection, 1); ! 649: conn = &conn_fb->tme_fb_connection; ! 650: ! 651: /* fill in the generic connection: */ ! 652: conn->tme_connection_next = *_conns; ! 653: conn->tme_connection_type = TME_CONNECTION_FRAMEBUFFER; ! 654: conn->tme_connection_score = tme_fb_connection_score; ! 655: conn->tme_connection_make = _tme_gtk_screen_connection_make; ! 656: conn->tme_connection_break = _tme_gtk_screen_connection_break; ! 657: ! 658: /* fill in the framebuffer connection: */ ! 659: conn_fb->tme_fb_connection_mode_change = _tme_gtk_screen_mode_change; ! 660: ! 661: /* return the connection side possibility: */ ! 662: *_conns = conn; ! 663: ! 664: /* done: */ ! 665: return (TME_OK); ! 666: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.