|
|
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.