summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2009-07-01 13:30:14 -0700
committerAaron Plattner <aplattner@nvidia.com>2009-07-01 13:30:14 -0700
commit531dc3a06023a147df5a6965b6751f5b6eff818b (patch)
tree5aa87d4617c2e1328fa1fce3fadfdd0ed81fbc87
parent8775a7ac7c2cdc2ee752d9933c247a190f45e5bb (diff)
-rw-r--r--src/XF86Config-parser/Generate.c261
-rw-r--r--src/XF86Config-parser/Screen.c62
-rw-r--r--src/XF86Config-parser/xf86Parser.h8
-rw-r--r--src/config-file.c6
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig.c17
-rw-r--r--src/gtk+-2.x/ctkframelock.c2
-rw-r--r--src/parse.c8
-rw-r--r--src/parse.h3
-rw-r--r--src/query-assign.c4
9 files changed, 352 insertions, 19 deletions
diff --git a/src/XF86Config-parser/Generate.c b/src/XF86Config-parser/Generate.c
index 22ce212..0897fe3 100644
--- a/src/XF86Config-parser/Generate.c
+++ b/src/XF86Config-parser/Generate.c
@@ -141,9 +141,10 @@ XConfigScreenPtr xconfigGenerateAddScreen(XConfigPtr config,
/*
- * assign_screen_adjacencies() - setup all the adjacency information
- * for the X screens in the given layout. Nothing fancy here: just
- * position all the screens horizontally, moving from left to right.
+ * xconfigGenerateAssignScreenAdjacencies() - setup all the adjacency
+ * information for the X screens in the given layout. Nothing fancy
+ * here: just position all the screens horizontally, moving from left
+ * to right.
*/
void xconfigGenerateAssignScreenAdjacencies(XConfigLayoutPtr layout)
@@ -375,6 +376,15 @@ static void add_modules(GenerateOptions *gop, XConfigPtr config)
{
XConfigLoadPtr l = NULL;
+ /*
+ * if the X server will automatically autoload GLX, then don't
+ * bother adding a modules section; it is difficult for
+ * nvidia-xconfig to know if modules like "type1" are present,
+ * anyway.
+ */
+
+ if (gop->autoloads_glx) return;
+
config->modules = xconfigAlloc(sizeof(XConfigModuleRec));
l = xconfigAddNewLoadDirective(l, xconfigStrdup("dbe"),
@@ -1297,3 +1307,248 @@ int xconfigAddKeyboard(GenerateOptions *gop, XConfigPtr config)
return TRUE;
} /* xconfigAddKeyboard() */
+
+
+
+/*
+ * xconfigGetDefaultProjectRoot() - scan some common directories for the X
+ * project root.
+ *
+ * Users of this information should be careful to account for the
+ * modular layout.
+ */
+
+static char *xconfigGetDefaultProjectRoot(void)
+{
+ char *paths[] = { "/usr/X11R6", "/usr/X11", NULL };
+ struct stat stat_buf;
+ int i;
+
+ for (i = 0; paths[i]; i++) {
+
+ if (stat(paths[i], &stat_buf) == -1) {
+ continue;
+ }
+
+ if (S_ISDIR(stat_buf.st_mode)) {
+ return paths[i];
+ }
+ }
+
+ /* default to "/usr/X11R6", I guess */
+
+ return paths[0];
+
+} /* xconfigGetDefaultProjectRoot() */
+
+
+
+
+/*
+ * get_xserver_information() - parse the versionString (from `X
+ * -version`) and assign relevant information that we infer from the X
+ * server version.
+ *
+ * Note: this implementation should be shared with nvidia-installer
+ */
+
+static int get_xserver_information(const char *versionString,
+ int *isXorg,
+ int *isModular,
+ int *autoloadsGLX,
+ int *supportsExtensionSection)
+{
+#define XSERVER_VERSION_FORMAT_1 "X Window System Version"
+#define XSERVER_VERSION_FORMAT_2 "X.Org X Server"
+
+ int major, minor, found;
+ const char *ptr;
+
+ /* check if this is an XFree86 X server */
+
+ if (strstr(versionString, "XFree86 Version")) {
+ *isXorg = FALSE;
+ *isModular = FALSE;
+ *autoloadsGLX = FALSE;
+ *supportsExtensionSection = FALSE;
+ return TRUE;
+ }
+
+ /* this must be an X.Org X server */
+
+ *isXorg = TRUE;
+
+ /* attempt to parse the major.minor version out of the string */
+
+ found = FALSE;
+
+ if (((ptr = strstr(versionString, XSERVER_VERSION_FORMAT_1)) != NULL) &&
+ (sscanf(ptr, XSERVER_VERSION_FORMAT_1 " %d.%d", &major, &minor) == 2)) {
+ found = TRUE;
+ }
+
+ if (!found &&
+ ((ptr = strstr(versionString, XSERVER_VERSION_FORMAT_2)) != NULL) &&
+ (sscanf(ptr, XSERVER_VERSION_FORMAT_2 " %d.%d", &major, &minor) == 2)) {
+ found = TRUE;
+ }
+
+ /* if we can't parse the version, give up */
+
+ if (!found) return FALSE;
+
+ /*
+ * isModular: X.Org X11R6.x X servers are monolithic, all others
+ * are modular
+ */
+
+ if (major == 6) {
+ *isModular = FALSE;
+ } else {
+ *isModular = TRUE;
+ }
+
+ /*
+ * supportsExtensionSection: support for the "Extension" xorg.conf
+ * section was added between X.Org 6.7 and 6.8. To account for
+ * the X server version wrap, it is easier to check for X servers
+ * that do not support the Extension section: 6.x (x < 8) X
+ * servers.
+ */
+
+ if ((major == 6) && (minor < 8)) {
+ *supportsExtensionSection = FALSE;
+ } else {
+ *supportsExtensionSection = TRUE;
+ }
+
+ /*
+ * support for autoloading GLX was added in X.Org 1.5. To account
+ * for the X server version wrap, it is easier to check for X
+ * servers that do not support GLX autoloading: 6.x, 7.x, or < 1.5
+ * X servers.
+ */
+
+ if ((major == 6) || (major == 7) || ((major == 1) && (minor < 5))) {
+ *autoloadsGLX = FALSE;
+ } else {
+ *autoloadsGLX = TRUE;
+ }
+
+ return TRUE;
+
+} /* get_xserver_information() */
+
+
+
+/*
+ * xconfigGetXServerInUse() - try to determine which X server is in use
+ * (XFree86, Xorg); also determine if the X server supports the
+ * Extension section of the X config file; support for the "Extension"
+ * section was added between X.Org 6.7 and 6.8.
+ *
+ * Some of the parsing here mimics what is done in the
+ * check_for_modular_xorg() function in nvidia-installer
+ */
+
+#define NV_LINE_LEN 1024
+#define EXTRA_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin:/usr/bin/X11"
+#if defined(NV_SUNOS)
+#define XSERVER_BIN_NAME "Xorg"
+#else
+#define XSERVER_BIN_NAME "X"
+#endif
+
+
+void xconfigGetXServerInUse(GenerateOptions *gop)
+{
+ FILE *stream = NULL;
+ int xserver = -1;
+ int isXorg;
+ int dummy, len, found;
+ char *cmd, *ptr, *ret;
+
+ gop->supports_extension_section = FALSE;
+ gop->autoloads_glx = FALSE;
+
+ /* run `X -version` with a PATH that hopefully includes the X binary */
+
+ cmd = xconfigStrcat("PATH=", gop->x_project_root, ":",
+ EXTRA_PATH, ":$PATH ", XSERVER_BIN_NAME,
+ " -version 2>&1", NULL);
+
+ if ((stream = popen(cmd, "r"))) {
+ char buf[NV_LINE_LEN];
+
+ /* read in as much of the input as we can fit into the buffer */
+
+ ptr = buf;
+
+ do {
+ len = NV_LINE_LEN - (ptr - buf) - 1;
+ ret = fgets(ptr, len, stream);
+ ptr = strchr(ptr, '\0');
+ } while ((ret != NULL) && (len > 1));
+
+ /*
+ * process the `X -version` output to infer relevant
+ * information from this X server
+ */
+
+ found = get_xserver_information(buf,
+ &isXorg,
+ &dummy, /* isModular */
+ &gop->autoloads_glx,
+ &gop->supports_extension_section);
+
+ if (found) {
+ if (isXorg) {
+ xserver = X_IS_XORG;
+ } else {
+ xserver = X_IS_XF86;
+ }
+ } else {
+ xconfigErrorMsg(WarnMsg, "Unable to parse X.Org version string.");
+ }
+ }
+ /* Close the popen()'ed stream. */
+ pclose(stream);
+ free(cmd);
+
+ if (xserver == -1) {
+ char *xorgpath;
+
+ xorgpath = xconfigStrcat(gop->x_project_root, "/bin/Xorg", NULL);
+ if (access(xorgpath, F_OK)==0) {
+ xserver = X_IS_XORG;
+ } else {
+ xserver = X_IS_XF86;
+ }
+ free(xorgpath);
+ }
+
+ gop->xserver=xserver;
+
+} /* xconfigGetXServerInUse() */
+
+
+
+/*
+ * xconfigGenerateLoadDefaultOptions - initialize a GenerateOptions
+ * structure with default values by peeking at the file system.
+ */
+
+void xconfigGenerateLoadDefaultOptions(GenerateOptions *gop)
+{
+ memset(gop, 0, sizeof(GenerateOptions));
+
+ gop->x_project_root = xconfigGetDefaultProjectRoot();
+
+ /* XXX What to default the following to?
+ gop->xserver
+ gop->keyboard
+ gop->mouse
+ gop->keyboard_driver
+ */
+
+} /* xconfigGenerateLoadDefaultOptions() */
diff --git a/src/XF86Config-parser/Screen.c b/src/XF86Config-parser/Screen.c
index f58d76b..2adcb79 100644
--- a/src/XF86Config-parser/Screen.c
+++ b/src/XF86Config-parser/Screen.c
@@ -79,6 +79,8 @@ static XConfigSymTabRec DisplayTab[] =
#define CLEANUP xconfigFreeDisplayList
+static int addImpliedScreen(XConfigPtr config);
+
XConfigDisplayPtr
xconfigParseDisplaySubSection (void)
{
@@ -490,12 +492,12 @@ xconfigValidateScreen (XConfigPtr p)
XConfigDevicePtr device;
XConfigAdaptorLinkPtr adaptor;
- if (!screen)
- {
- xconfigErrorMsg(ValidationErrorMsg, "At least one Screen section "
- "is required.");
- return (FALSE);
- }
+ /*
+ * if we do not have a screen, just return TRUE; we'll add a
+ * screen later during the Sanitize step
+ */
+
+ if (!screen) return TRUE;
while (screen)
{
@@ -559,6 +561,10 @@ int xconfigSanitizeScreen(XConfigPtr p)
{
XConfigScreenPtr screen = p->screens;
XConfigMonitorPtr monitor;
+
+ if (!addImpliedScreen(p)) {
+ return FALSE;
+ }
while (screen) {
@@ -600,8 +606,9 @@ int xconfigSanitizeScreen(XConfigPtr p)
screen->monitor_name = xconfigStrdup(monitor->identifier);
- if (!xconfigValidateMonitor(p, screen))
- return (FALSE);
+ if (!xconfigValidateMonitor(p, screen)) {
+ return FALSE;
+ }
}
}
@@ -676,4 +683,43 @@ xconfigRemoveMode(XConfigModePtr head, const char *name)
}
+static int addImpliedScreen(XConfigPtr config)
+{
+ XConfigScreenPtr screen;
+ XConfigDevicePtr device;
+ XConfigMonitorPtr monitor;
+ if (config->screens) return TRUE;
+
+ xconfigErrorMsg(WarnMsg, "No Screen specified, constructing implicit "
+ "screen section.\n");
+
+ /* allocate the new screen section */
+
+ screen = calloc(1, sizeof(XConfigScreenRec));
+ if (!screen) return FALSE;
+
+ screen->identifier = xconfigStrdup("Default Screen");
+
+ /*
+ * Use the first device section if there is one.
+ */
+ if (config->devices) {
+ device = config->devices;
+ screen->device_name = xconfigStrdup(device->identifier);
+ screen->device = device;
+ }
+
+ /*
+ * Use the first monitor section if there is one.
+ */
+ if (config->monitors) {
+ monitor = config->monitors;
+ screen->monitor_name = xconfigStrdup(monitor->identifier);
+ screen->monitor = monitor;
+ }
+
+ config->screens = screen;
+
+ return TRUE;
+}
diff --git a/src/XF86Config-parser/xf86Parser.h b/src/XF86Config-parser/xf86Parser.h
index 6598d5e..a68962a 100644
--- a/src/XF86Config-parser/xf86Parser.h
+++ b/src/XF86Config-parser/xf86Parser.h
@@ -591,6 +591,10 @@ typedef struct {
char *keyboard;
char *mouse;
char *keyboard_driver;
+
+ int supports_extension_section;
+ int autoloads_glx;
+
} GenerateOptions;
@@ -724,6 +728,10 @@ void xconfigGenerateAssignScreenAdjacencies(XConfigLayoutPtr layout);
void xconfigGeneratePrintPossibleMice(void);
void xconfigGeneratePrintPossibleKeyboards(void);
+void xconfigGenerateLoadDefaultOptions(GenerateOptions *gop);
+
+void xconfigGetXServerInUse(GenerateOptions *gop);
+
/*
* check (and update, if necessary) the inputs in the specified layout
diff --git a/src/config-file.c b/src/config-file.c
index df4d5b3..2145627 100644
--- a/src/config-file.c
+++ b/src/config-file.c
@@ -214,7 +214,8 @@ int nv_write_config_file(const char *filename, CtrlHandles *h,
NVCTRLAttributeValidValuesRec valid;
uint32 mask;
CtrlHandleTarget *t;
- char *tmp_d_str, *tmp, *prefix, scratch[4];
+ char *tmp_d_str, *prefix, scratch[4];
+ const char *tmp;
char *locale = "C";
stream = fopen(filename, "w");
@@ -380,7 +381,8 @@ int nv_write_config_file(const char *filename, CtrlHandles *h,
continue;
}
- tmp = nv_get_attribute_name(p->attr);
+ tmp = nv_get_attribute_name(p->attr, NV_PARSER_TYPE_STRING_ATTRIBUTE,
+ p->flags);
if (!tmp) {
nv_error_msg("Failure to save unknown attribute %d.", p->attr);
p = p->next;
diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c
index 2061434..f593f54 100644
--- a/src/gtk+-2.x/ctkdisplayconfig.c
+++ b/src/gtk+-2.x/ctkdisplayconfig.c
@@ -6392,6 +6392,7 @@ static gboolean update_xconfig_save_buffer(CtkDisplayConfig *ctk_object)
mergable = FALSE;
} else {
+ GenerateOptions gop;
/* Must be able to parse the file as an X config file */
error = xconfigReadConfigFile(&mergeConfig);
@@ -6411,6 +6412,22 @@ static gboolean update_xconfig_save_buffer(CtkDisplayConfig *ctk_object)
mergeConfig = NULL;
mergable = FALSE;
}
+
+ /* Sanitize the X config file */
+ xconfigGenerateLoadDefaultOptions(&gop);
+ xconfigGetXServerInUse(&gop);
+
+ if (!xconfigSanitizeConfig(mergeConfig, NULL, &gop)) {
+ gchar *msg = g_strdup_printf("Failed to sanitize existing X "
+ "config file '%s'!",
+ filename);
+ ctk_display_warning_msg
+ (ctk_get_parent_window(GTK_WIDGET(ctk_object)), msg);
+ g_free(msg);
+
+ xconfigFreeConfig(&mergeConfig);
+ mergable = FALSE;
+ }
}
/* If we're not actualy doing a merge, close the file */
diff --git a/src/gtk+-2.x/ctkframelock.c b/src/gtk+-2.x/ctkframelock.c
index 33af997..f937e53 100644
--- a/src/gtk+-2.x/ctkframelock.c
+++ b/src/gtk+-2.x/ctkframelock.c
@@ -5381,7 +5381,7 @@ static gint add_devices(CtkFramelock *ctk_framelock,
static void add_entry_to_parsed_attributes(nvListEntryPtr entry,
ParsedAttribute *head)
{
- ParsedAttribute a;
+ ParsedAttribute a = { 0 };
char *display_name = NULL;
int target_type = 0;
int target_id = 0;
diff --git a/src/parse.c b/src/parse.c
index f55dc63..a2a78d1 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -1060,12 +1060,16 @@ void nv_parsed_attribute_clean(ParsedAttribute *p)
* corresponds to the attribute constant.
*/
-char *nv_get_attribute_name(const int attr)
+const char *nv_get_attribute_name(const int attr, const int flagsMask,
+ const int flags)
{
int i;
for (i = 0; attributeTable[i].name; i++) {
- if (attributeTable[i].attr == attr) return attributeTable[i].name;
+ if (attributeTable[i].attr == attr &&
+ (attributeTable[i].flags & flagsMask) == (flags & flagsMask)) {
+ return attributeTable[i].name;
+ }
}
return NULL;
diff --git a/src/parse.h b/src/parse.h
index 1e0d510..78cd0f6 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -286,7 +286,8 @@ void nv_parsed_attribute_add(ParsedAttribute *head, ParsedAttribute *a);
void nv_parsed_attribute_free(ParsedAttribute *p);
void nv_parsed_attribute_clean(ParsedAttribute *p);
-char *nv_get_attribute_name(const int attr);
+const char *nv_get_attribute_name(const int attr, const int flagsMask,
+ const int flags);
char *nv_standardize_screen_name(const char *display_name, int screen);
diff --git a/src/query-assign.c b/src/query-assign.c
index 2920762..02b0142 100644
--- a/src/query-assign.c
+++ b/src/query-assign.c
@@ -701,8 +701,8 @@ static void print_valid_values(char *name, uint32 flags,
}
if (flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE) {
- nv_msg(INDENT, "Valid values for '%s' are: [%s], [%s].", name, str,
- str2);
+ nv_msg(INDENT, "Valid values for '%s' are: [%s], [%s].", name, str2,
+ str);
} else {
nv_msg(INDENT, "Valid values for '%s' are: %s.", name, str);
}