diff options
Diffstat (limited to 'hardinfo2/x_util.c')
-rw-r--r-- | hardinfo2/x_util.c | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/hardinfo2/x_util.c b/hardinfo2/x_util.c new file mode 100644 index 00000000..2a7febb4 --- /dev/null +++ b/hardinfo2/x_util.c @@ -0,0 +1,342 @@ +/* + * HardInfo - Displays System Information + * Copyright (C) 2003-2017 L. A. F. Pereira <l@tia.mat.br> + * This file + * Copyright (C) 2018 Burt P. <pburt0@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 or later. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "hardinfo.h" +#include "x_util.h" +#include <X11/Xlib.h> + +/* wayland stuff lives here for now */ + +wl_info *get_walyand_info() { + wl_info *s = malloc(sizeof(wl_info)); + memset(s, 0, sizeof(wl_info)); + s->xdg_session_type = g_strdup( getenv("XDG_SESSION_TYPE") ); + if (s->xdg_session_type == NULL) + s->xdg_session_type = strdup("x11"); + s->display_name = g_strdup( getenv("WAYLAND_DISPLAY") ); + return s; +} + +void wl_free(wl_info *s) { + if (s) { + free(s->xdg_session_type); + free(s->display_name); + free(s); + } +} + +/* get x information from xrandr, xdpyinfo, and glxinfo */ + +static char *simple_line_value(char *line, const char *prefix) { + if (g_str_has_prefix(g_strstrip(line), prefix)) { + line += strlen(prefix) + 1; + return g_strstrip(line); + } else + return NULL; +} + +gboolean fill_glx_info(glx_info *glx) { + gboolean spawned; + gchar *out, *err, *p, *l, *next_nl; + gchar *glx_cmd = g_strdup("glxinfo"); + +#define GLX_MATCH_LINE(prefix_str, struct_member) \ + if (l = simple_line_value(p, prefix_str)) { glx->struct_member = g_strdup(l); goto glx_next_line; } + + spawned = hardinfo_spawn_command_line_sync(glx_cmd, + &out, &err, NULL, NULL); + g_free(glx_cmd); + if (spawned) { + p = out; + while(next_nl = strchr(p, '\n')) { + strend(p, '\n'); + g_strstrip(p); + GLX_MATCH_LINE("GLX version", glx_version); + GLX_MATCH_LINE("OpenGL vendor string", ogl_vendor); + GLX_MATCH_LINE("OpenGL renderer string", ogl_renderer); + GLX_MATCH_LINE("OpenGL renderer string", ogl_renderer); + GLX_MATCH_LINE("OpenGL core profile version string", ogl_core_version); + GLX_MATCH_LINE("OpenGL core profile shading language version string", ogl_core_sl_version); + GLX_MATCH_LINE("OpenGL version string", ogl_version); + GLX_MATCH_LINE("OpenGL shading language version string", ogl_sl_version); + GLX_MATCH_LINE("OpenGL ES profile version string", ogles_version); + GLX_MATCH_LINE("OpenGL ES profile shading language version string", ogles_sl_version); + + if (l = simple_line_value(p, "direct rendering")) { + if (strstr(p, "Yes")) + glx->direct_rendering = 1; + goto glx_next_line; + } + + glx_next_line: + p = next_nl + 1; + } + g_free(out); + g_free(err); + return TRUE; + } + return FALSE; +} + +glx_info *glx_create() { + glx_info *s = malloc(sizeof(glx_info)); + memset(s, 0, sizeof(glx_info)); + return s; +} + +void glx_free(glx_info *s) { + if (s) { + free(s->glx_version); + free(s->ogl_vendor); + free(s->ogl_renderer); + free(s->ogl_core_version); + free(s->ogl_core_sl_version); + free(s->ogl_version); + free(s->ogl_sl_version); + free(s->ogles_version); + free(s->ogles_sl_version); + free(s); + } +} + +gboolean fill_xinfo(xinfo *xi) { + gboolean spawned; + gchar *out, *err, *p, *l, *next_nl; + gchar *xi_cmd = g_strdup("xdpyinfo"); + +#define XI_MATCH_LINE(prefix_str, struct_member) \ + if (l = simple_line_value(p, prefix_str)) { xi->struct_member = g_strdup(l); goto xi_next_line; } + + spawned = hardinfo_spawn_command_line_sync(xi_cmd, + &out, &err, NULL, NULL); + g_free(xi_cmd); + if (spawned) { + p = out; + while(next_nl = strchr(p, '\n')) { + strend(p, '\n'); + g_strstrip(p); + XI_MATCH_LINE("name of display", display_name); + XI_MATCH_LINE("vendor string", vendor); + XI_MATCH_LINE("vendor release number", release_number); + XI_MATCH_LINE("XFree86 version", version); + XI_MATCH_LINE("X.Org version", version); + + xi_next_line: + p = next_nl + 1; + } + g_free(out); + g_free(err); + return TRUE; + } + return FALSE; +} + +gboolean fill_xrr_info(xrr_info *xrr) { + gboolean spawned; + gchar *out, *err, *p, *next_nl; + gchar *xrr_cmd = g_strdup("xrandr --prop"); + int ec; + + x_screen ts; + x_output to; + char output_id[128]; + char status[128]; + char alist[512]; + + memset(&ts, 0, sizeof(x_screen)); + memset(&to, 0, sizeof(x_output)); + memset(output_id, 0, sizeof(output_id)); + memset(status, 0, sizeof(status)); + memset(alist, 0, sizeof(alist)); + + spawned = hardinfo_spawn_command_line_sync(xrr_cmd, + &out, &err, NULL, NULL); + g_free(xrr_cmd); + if (spawned) { + p = out; + while(next_nl = strchr(p, '\n')) { + strend(p, '\n'); + g_strstrip(p); + + ec = sscanf(p, "Screen %d: minimum %d x %d, current %d x %d, maximum %d x %d", + &ts.number, + &ts.min_px_width, &ts.min_px_height, + &ts.px_width, &ts.px_height, + &ts.max_px_width, &ts.max_px_height); + if (ec == 7) { + /* new screen */ + xrr->screen_count++; + if (xrr->screens == NULL) + xrr->screens = malloc(xrr->screen_count * sizeof(x_screen)); + else + xrr->screens = realloc(xrr->screens, xrr->screen_count * sizeof(x_screen)); + memcpy(&xrr->screens[xrr->screen_count-1], &ts, sizeof(x_screen)); + memset(&ts, 0, sizeof(x_screen)); /* clear the temp */ + goto xrr_next_line; + } + + /* looking for: + * <output_id> (connected|disconnected|unknown connection) (primary|?) <%dx%d+%d+%d> (attribute_list) mm x mm + */ + ec = sscanf(p, "%127s %127[^(](%511[^)]", output_id, status, alist); + if (ec == 3) { + int is_output = 0, found_rect = 0, n = 0; + gchar **ot = g_strsplit(status, " ", 0); + + /* find rect */ + while (ot[n] != NULL) { + ec = sscanf(ot[n], "%dx%d+%d+%d", &to.px_width, &to.px_height, &to.px_offset_x, &to.px_offset_y); + if (ec == 4) { + found_rect = 1; + break; + } + n++; + } + if (found_rect) + to.screen = xrr->screen_count - 1; + else + to.screen = -1; + + if (strcmp("disconnected", ot[0]) == 0) { + is_output = 1; + to.connected = 0; + } else + if (strcmp("unknown", ot[0]) == 0 && strcmp("connection", ot[1]) == 0) { + is_output = 1; + to.connected = -1; + } else + if (strcmp("connected", ot[0]) == 0) { + is_output = 1; + to.connected = 1; + } + g_strfreev(ot); + if (is_output) { + strncpy(to.name, output_id, 63); + xrr->output_count++; + if (xrr->outputs == NULL) + xrr->outputs = malloc(xrr->output_count * sizeof(x_output)); + else + xrr->outputs = realloc(xrr->outputs, xrr->output_count * sizeof(x_output)); + memcpy(&xrr->outputs[xrr->output_count-1], &to, sizeof(x_output)); + memset(&to, 0, sizeof(x_output)); /* clear the temp */ + goto xrr_next_line; + } + } + + xrr_next_line: + p = next_nl + 1; + } + g_free(out); + g_free(err); + return TRUE; + } + return FALSE; +} + +gboolean fill_basic_xlib(xinfo *xi) { + Display *display; + int s, w, h, rn; + + display = XOpenDisplay(NULL); + if (display) { + if (!xi->display_name) + xi->display_name = XDisplayName(NULL); + + if (!xi->vendor) + xi->vendor = XServerVendor(display); + + if (!xi->release_number) { + rn = XVendorRelease(display); + xi->release_number = g_strdup_printf("%d", rn); + } + + if (!xi->xrr->screen_count) { + s = DefaultScreen(display); + w = XDisplayWidth(display, s); + h = XDisplayHeight(display, s); + + /* create at least one screen */ + x_screen ts; + memset(&ts, 0, sizeof(x_screen)); + ts.number = s; + ts.px_width = w; + ts.px_height = h; + + xi->xrr->screen_count++; + if (xi->xrr->screens == NULL) + xi->xrr->screens = malloc(xi->xrr->screen_count * sizeof(x_screen)); + else + xi->xrr->screens = realloc(xi->xrr->screens, xi->xrr->screen_count * sizeof(x_screen)); + memcpy(&xi->xrr->screens[xi->xrr->screen_count-1], &ts, sizeof(x_screen)); + } + return TRUE; + } + return FALSE; +} + +xrr_info *xrr_create() { + xrr_info *xrr = malloc(sizeof(xrr_info)); + memset(xrr, 0, sizeof(xrr_info)); + return xrr; +} + +void xrr_free(xrr_info *xrr) { + if (xrr) { + free(xrr->screens); + free(xrr->outputs); + free(xrr->providers); + free(xrr->monitors); + free(xrr); + } +} + +xinfo *xinfo_get_info() { + int fail = 0; + xinfo *xi = malloc(sizeof(xinfo)); + memset(xi, 0, sizeof(xinfo)); + xi->glx = glx_create(); + xi->xrr = xrr_create(); + + if ( !fill_xinfo(xi) ) + fail++; + if ( !fill_xrr_info(xi->xrr) ) + fail++; + if ( !fill_glx_info(xi->glx) ) + fail++; + + if (fail) { + /* as fallback, try xlib directly */ + if ( !fill_basic_xlib(xi) ) + xi->nox = 1; + } + return xi; +} + +void xinfo_free(xinfo *xi) { + if (xi) { + free(xi->display_name); + free(xi->vendor); + free(xi->version); + free(xi->release_number); + xrr_free(xi->xrr); + glx_free(xi->glx); + free(xi); + } +} |