Annotation of tme/host/gtk/gtk-screen.c, revision 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.