Annotation of tme/host/gtk/gtk-screen.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.