diff options
| author | Burt P <pburt0@gmail.com> | 2018-03-10 23:32:28 -0600 | 
|---|---|---|
| committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2018-04-24 07:43:43 -0700 | 
| commit | 664b6bd2aff36e8567c74d6acab45bd03d0e6801 (patch) | |
| tree | 41e6360269ca0e5a7d9ee0598180cc7beffac8c3 | |
| parent | dffc0b9dd005015f5df36448b1f2952493f5fc1e (diff) | |
[new] x_util: functions and data structures for x server information
Get X display info from Xlib,  xrandr, xdpyinfo, and glxinfo.
Also, Some simple Wayland info lives here for now.
Signed-off-by: Burt P <pburt0@gmail.com>
| -rw-r--r-- | CMakeLists.txt | 8 | ||||
| -rw-r--r-- | hardinfo/x_util.c | 347 | ||||
| -rw-r--r-- | includes/x_util.h | 104 | 
3 files changed, 459 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 628583b5..faf19262 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,6 +88,8 @@ if(NOT HARDINFO_NOSYNC)  	pkg_check_modules(LIBSOUP libsoup-2.4>=2.24)  endif() +pkg_check_modules(X11 REQUIRED x11) +  include(FindZLIB REQUIRED)  include_directories( @@ -99,10 +101,12 @@ include_directories(  	${GTK_INCLUDE_DIRS}  	${LIBSOUP_INCLUDE_DIRS}  	${ZLIB_INCLUDE_DIRS} +	${X11_INCLUDE_DIRS}  )  link_directories(  	${GTK_LIBRARY_DIRS}  	${LIBSOUP_LIBRARY_DIRS} +	${X11_LIBRARY_DIRS}  )  set(HARDINFO_MODULES @@ -226,6 +230,7 @@ add_executable(hardinfo  	hardinfo/cpu_util.c  	hardinfo/dmi_util.c  	hardinfo/dt_util.c +	hardinfo/x_util.c  	shell/callbacks.c  	shell/iconcache.c  	shell/menu.c @@ -241,6 +246,7 @@ target_link_libraries(hardinfo  	${LIBSOUP_LIBRARIES}  	m  	${ZLIB_LIBRARIES} +	${X11_LIBRARIES}  )  else()  add_executable(hardinfo @@ -256,6 +262,7 @@ add_executable(hardinfo  	hardinfo/cpu_util.c  	hardinfo/dmi_util.c  	hardinfo/dt_util.c +	hardinfo/x_util.c  	shell/callbacks.c  	shell/iconcache.c  	shell/menu.c @@ -270,6 +277,7 @@ target_link_libraries(hardinfo  	${LIBSOUP_LIBRARIES}  	m  	${ZLIB_LIBRARIES} +	${X11_LIBRARIES}  )  endif() diff --git a/hardinfo/x_util.c b/hardinfo/x_util.c new file mode 100644 index 00000000..49372f56 --- /dev/null +++ b/hardinfo/x_util.c @@ -0,0 +1,347 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2003-2017 Leandro A. F. Pereira <leandro@hardinfo.org> + *    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. + * + *    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, *t, *next_nl; +    gchar *glx_cmd = g_strdup("glxinfo"); + +    int ec; + +#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 = g_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, *t, *next_nl; +    gchar *xi_cmd = g_strdup("xdpyinfo"); + +    int ec; + +#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 = g_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, *l, *t, *next_nl; +    gchar *xrr_cmd = g_strdup("xrandr"); + +    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, 128); +    memset(status, 0, 128); +    memset(alist, 0, 128); + +    spawned = g_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, "%s %[^(](%[^)]", 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); +    } +} diff --git a/includes/x_util.h b/includes/x_util.h new file mode 100644 index 00000000..ed66cc55 --- /dev/null +++ b/includes/x_util.h @@ -0,0 +1,104 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2003-2017 Leandro A. F. Pereira <leandro@hardinfo.org> + *    This file + *    Copyright (C) 2017 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. + * + *    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 + */ + +#ifndef __X_UTIL_H__ +#define __X_UTIL_H__ + +/* wayland information (lives here in x_util for now) */ +typedef struct { +    char *xdg_session_type; +    char *display_name; +} wl_info; + +wl_info *get_walyand_info(); +void wl_free(wl_info *); + +typedef struct { +    char *glx_version; +    int direct_rendering; +    char *ogl_vendor, *ogl_renderer; + +    char *ogl_core_version, *ogl_core_sl_version; +    char *ogl_version, *ogl_sl_version; /* compat */ +    char *ogles_version, *ogles_sl_version; +} glx_info; + +glx_info *glx_create(); +gboolean fill_glx_info(glx_info *glx); +void glx_free(glx_info *glx); + +typedef struct { +    int number; +    int px_width; +    int px_height; +    int min_px_width; +    int min_px_height; +    int max_px_width; +    int max_px_height; +} x_screen; + +typedef struct { +    /* I guess it is kindof like gpu? */ +    int reserved; /* TODO: */ +} x_provider; + +typedef struct { +    char name[64]; +    int connected; +    int screen; /* index into xrr_info.screens[], look there for x screen number */ +    int px_width; +    int px_height; +    int px_offset_x; +    int px_offset_y; +    int mm_width; +    int mm_height; +} x_output; + +typedef struct { +    int reserved; /* TODO: */ +} x_monitor; + +typedef struct { +    char *display_name; +    int screen_count; +    x_screen *screens; +    int provider_count; +    x_provider *providers; +    int output_count; +    x_output *outputs; +    int monitor_count; +    x_monitor *monitors; +} xrr_info; + +xrr_info *xrr_create(); +gboolean fill_xrr_info(xrr_info *xrr); +void xrr_free(xrr_info *xrr); + +typedef struct { +    int nox; /* complete failure to find X */ +    char *display_name, *vendor, *version, *release_number; +    xrr_info *xrr; +    glx_info *glx; +} xinfo; + +xinfo *xinfo_get_info(); +void xinfo_free(xinfo *xi); + +#endif  | 
