diff options
author | Alexander Larsson <alexl@redhat.com> | 2000-11-09 12:15:40 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2000-11-09 12:15:40 +0000 |
commit | 8898529c12e0d2d4a5dd4e3b9917a6a1272f4882 (patch) | |
tree | a39b6ae3282377218c9f7f85c764fcbef8499222 /gdk/linux-fb/gdkmain-fb.c | |
parent | 8ced8f9d842a75dda1ed650a83b1465f868d50f6 (diff) | |
download | gtk+-8898529c12e0d2d4a5dd4e3b9917a6a1272f4882.tar.gz |
Changes to make the new testgtk compile after gtk_menu_append was removed.
2000-11-09 Alexander Larsson <alexl@redhat.com>
* demos/testgtk/menus.c:
Changes to make the new testgtk compile after
gtk_menu_append was removed.
* gdk/linux-fb/gdkdrawable-fb2.c
(gdk_fb_get_depth, gdk_fb_get_visual,
gdk_drawable_impl_fb_class_init): Implement
these drawable functions. Now GtkImages work again.
* gdk/linux-fb/gdkimage-fb.c (_gdk_fb_get_image): Change prototype.
* gdk/linux-fb/gdkprivate-fb.h (_gdk_fb_get_image): Change prototype.
* gdk/linux-fb/gdkmain-fb.c (fb_modes_parse_mode,
gdk_fb_setup_mode_from_name, gdk_fb_set_mode, gdk_fb_display_new);
Parse /etc/fb.modes, use the environment variables GDK_DISPLAY_MODE,
GDK_DISPLAY_DEPTH, GDK_DISPLAY_WIDTH, GDK_DISPLAY_HEIGHT.
Diffstat (limited to 'gdk/linux-fb/gdkmain-fb.c')
-rw-r--r-- | gdk/linux-fb/gdkmain-fb.c | 418 |
1 files changed, 415 insertions, 3 deletions
diff --git a/gdk/linux-fb/gdkmain-fb.c b/gdk/linux-fb/gdkmain-fb.c index 69926c98ac..d4d38c083a 100644 --- a/gdk/linux-fb/gdkmain-fb.c +++ b/gdk/linux-fb/gdkmain-fb.c @@ -34,6 +34,7 @@ #include <stdio.h> #include <time.h> #include <stdlib.h> +#include <string.h> #include "gdk.h" @@ -60,6 +61,412 @@ GdkArgDesc _gdk_windowing_args[] = { { NULL } }; +static const GScannerConfig fb_modes_scanner_config = +{ + ( + " \t\n" + ) /* cset_skip_characters */, + ( + G_CSET_a_2_z + G_CSET_A_2_Z + ) /* cset_identifier_first */, + ( + G_CSET_a_2_z + "_-0123456789" + G_CSET_A_2_Z + ) /* cset_identifier_nth */, + ( "#\n" ) /* cpair_comment_single */, + + FALSE /* case_sensitive */, + + FALSE /* skip_comment_multi */, + TRUE /* skip_comment_single */, + FALSE /* scan_comment_multi */, + TRUE /* scan_identifier */, + TRUE /* scan_identifier_1char */, + FALSE /* scan_identifier_NULL */, + TRUE /* scan_symbols */, + FALSE /* scan_binary */, + FALSE /* scan_octal */, + FALSE /* scan_float */, + FALSE /* scan_hex */, + FALSE /* scan_hex_dollar */, + FALSE /* scan_string_sq */, + TRUE /* scan_string_dq */, + TRUE /* numbers_2_int */, + FALSE /* int_2_float */, + FALSE /* identifier_2_string */, + TRUE /* char_2_token */, + FALSE /* symbol_2_token */, + FALSE /* scope_0_fallback */, +}; + +enum { + FB_MODE, + FB_ENDMODE, + FB_GEOMETRY, + FB_TIMINGS, + FB_LACED, + FB_HSYNC, + FB_VSYNC, + FB_CSYNC, + FB_EXTSYNC, + FB_DOUBLE +}; + +char *fb_modes_keywords[] = +{ + "mode", + "endmode", + "geometry", + "timings", + "laced", + "hsync", + "vsync", + "csync", + "extsync", + "double" +}; + +static int +fb_modes_parse_mode (GScanner *scanner, + struct fb_var_screeninfo *modeinfo, + char *specified_modename) +{ + guint token; + int keyword; + int i; + char *modename; + int geometry[5]; + int timings[7]; + int vsync=0, hsync=0, csync=0, extsync=0, doublescan=0, laced=0; + int found_geometry = 0; + int found_timings = 0; + + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_SYMBOL) + return -1; + + keyword = GPOINTER_TO_INT(scanner->value.v_symbol); + if (keyword != FB_MODE) + return -1; + + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_STRING) + return -1; + + modename = g_strdup(scanner->value.v_string); + + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_SYMBOL) + { + g_free (modename); + return -1; /* Not a valid keyword */ + } + keyword = GPOINTER_TO_INT(scanner->value.v_symbol); + while ( keyword != FB_ENDMODE ) + { + + switch (GPOINTER_TO_INT(scanner->value.v_symbol)) + { + case FB_GEOMETRY: + for (i=0;i<5;i++) { + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_INT) + { + g_free (modename); + return -1; /* need a integer */ + } + geometry[i] = scanner->value.v_int; + } + found_geometry = TRUE; + break; + case FB_TIMINGS: + for (i=0;i<7;i++) { + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_INT) + { + g_free (modename); + return -1; /* need a integer */ + } + timings[i] = scanner->value.v_int; + } + found_timings = TRUE; + break; + case FB_LACED: + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_IDENTIFIER) + { + g_free (modename); + return -1; + } + if (g_strcasecmp(scanner->value.v_identifier, "true")==0) + laced = 1; + else if (g_strcasecmp(scanner->value.v_identifier, "false")==0) + laced = 0; + else + { + g_free (modename); + return -1; + } + break; + case FB_EXTSYNC: + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_IDENTIFIER) + { + g_free (modename); + return -1; + } + if (g_strcasecmp(scanner->value.v_identifier, "true")==0) + extsync = 1; + else if (g_strcasecmp(scanner->value.v_identifier, "false")==0) + extsync = 0; + else + { + g_free (modename); + return -1; + } + break; + case FB_DOUBLE: + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_IDENTIFIER) + { + g_free (modename); + return -1; + } + if (g_strcasecmp(scanner->value.v_identifier, "true")==0) + doublescan = 1; + else if (g_strcasecmp(scanner->value.v_identifier, "false")==0) + doublescan = 0; + else + { + g_free (modename); + return -1; + } + break; + case FB_VSYNC: + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_IDENTIFIER) + { + g_free (modename); + return -1; + } + if (g_strcasecmp(scanner->value.v_identifier, "high")==0) + vsync = 1; + else if (g_strcasecmp(scanner->value.v_identifier, "low")==0) + vsync = 0; + else + { + g_free (modename); + return -1; + } + break; + case FB_HSYNC: + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_IDENTIFIER) + { + g_free (modename); + return -1; + } + if (g_strcasecmp(scanner->value.v_identifier, "high")==0) + hsync = 1; + else if (g_strcasecmp(scanner->value.v_identifier, "low")==0) + hsync = 0; + else + { + g_free (modename); + return -1; + } + break; + case FB_CSYNC: + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_IDENTIFIER) + { + g_free (modename); + return -1; + } + if (g_strcasecmp(scanner->value.v_identifier, "high")==0) + csync = 1; + else if (g_strcasecmp(scanner->value.v_identifier, "low")==0) + csync = 0; + else + { + g_free (modename); + return -1; + } + break; + } + + token = g_scanner_get_next_token(scanner); + if (token != G_TOKEN_SYMBOL) + { + g_free (modename); + return -1; /* Not a valid keyword */ + } + keyword = GPOINTER_TO_INT(scanner->value.v_symbol); + } + + if (strcmp(modename, specified_modename)== 0) { + if (!found_geometry) + g_warning("Geometry not specified\n"); + + if (found_geometry) + { + modeinfo->xres = geometry[0]; + modeinfo->yres = geometry[1]; + modeinfo->xres_virtual = geometry[2]; + modeinfo->yres_virtual = geometry[3]; + modeinfo->bits_per_pixel = geometry[4]; + } + + if (!found_timings) + g_warning("Timing not specified\n"); + + if (found_timings) + { + modeinfo->pixclock = timings[0]; + modeinfo->left_margin = timings[1]; + modeinfo->right_margin = timings[2]; + modeinfo->upper_margin = timings[3]; + modeinfo->lower_margin = timings[4]; + modeinfo->hsync_len = timings[5]; + modeinfo->vsync_len = timings[6]; + + modeinfo->vmode = 0; + if (laced) + modeinfo->vmode |= FB_VMODE_INTERLACED; + if (doublescan) + modeinfo->vmode |= FB_VMODE_DOUBLE; + + modeinfo->sync = 0; + if (hsync) + modeinfo->sync |= FB_SYNC_HOR_HIGH_ACT; + if (vsync) + modeinfo->sync |= FB_SYNC_VERT_HIGH_ACT; + } + + g_free(modename); + return 1; + } + + g_free(modename); + + return 0; +} + +static int +gdk_fb_setup_mode_from_name(struct fb_var_screeninfo *modeinfo, char *modename) +{ + GScanner *scanner; + char *filename; + gint result; + int fd, i; + int retval; + + retval = 0; + + filename = "/etc/fb.modes"; + + fd = open (filename, O_RDONLY); + if (fd < 0) + { + g_warning ("Cannot read %s\n", filename); + return retval; + } + + scanner = g_scanner_new ((GScannerConfig *) &fb_modes_scanner_config); + scanner->input_name = filename; + + for (i=0;i<sizeof(fb_modes_keywords)/sizeof(fb_modes_keywords[0]);i++) + g_scanner_add_symbol(scanner, fb_modes_keywords[i], GINT_TO_POINTER(i)); + + g_scanner_input_file (scanner, fd); + + while (1) { + if (g_scanner_peek_next_token(scanner) == G_TOKEN_EOF) { + break; + } + result = fb_modes_parse_mode(scanner, modeinfo, modename); + + if (result < 0) { + g_warning("parse error in %s at line %d\n", filename, scanner->line); + break; + } + if (result > 0) + { + retval = 1; + break; + } + } + + g_scanner_destroy (scanner); + + close(fd); + + return retval; +} + + +static int +gdk_fb_set_mode(GdkFBDisplay *display) +{ + char *env, *end; + int depth, height, width; + + if (ioctl (display->fd, FBIOGET_VSCREENINFO, &display->modeinfo) < 0) + return -1; + + env = getenv("GDK_DISPLAY_MODE"); + if (env) + { + if (!gdk_fb_setup_mode_from_name(&display->modeinfo, env)) + g_warning("Couldn't find mode named '%s'\n", env); + } + + env = getenv("GDK_DISPLAY_DEPTH"); + if (env) + { + depth = strtol(env, &end, 10); + if (env != end) + display->modeinfo.bits_per_pixel = depth; + } + + env = getenv("GDK_DISPLAY_WIDTH"); + if (env) + { + width = strtol(env, &end, 10); + if (env != end) + { + display->modeinfo.xres = width; + display->modeinfo.xres_virtual = width; + } + } + + env = getenv("GDK_DISPLAY_HEIGHT"); + if (env) + { + height = strtol(env, &end, 10); + if (env != end) + { + display->modeinfo.yres = height; + display->modeinfo.yres_virtual = height; + } + } + + if (ioctl (display->fd, FBIOPUT_VSCREENINFO, &display->modeinfo) < 0) + { + g_warning("Couldn't set specified mode\n"); + return -1; + } + + if (ioctl (display->fd, FBIOGET_FSCREENINFO, &display->sinfo) < 0) + { + g_warning("Error getting fixed screen info\n"); + return -1; + } + return 0; +} + static GdkFBDisplay * gdk_fb_display_new(const char *filename) { @@ -72,16 +479,21 @@ gdk_fb_display_new(const char *filename) retval = g_new0(GdkFBDisplay, 1); retval->fd = fd; + + if (gdk_fb_set_mode(retval) < 0) + { + g_free (retval); + return NULL; + } + ioctl(retval->fd, FBIOBLANK, 0); - n = ioctl(fd, FBIOGET_FSCREENINFO, &retval->sinfo); - n |= ioctl(fd, FBIOGET_VSCREENINFO, &retval->modeinfo); - g_assert(!n); /* We used to use sinfo.smem_len, but that seemed to be broken in many cases */ retval->fbmem = mmap(NULL, retval->modeinfo.yres * retval->sinfo.line_length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); g_assert(retval->fbmem != MAP_FAILED); + if(retval->sinfo.visual == FB_VISUAL_PSEUDOCOLOR) { guint16 red[256], green[256], blue[256]; |