Current Project: X11 Window-Manager interface helper functions.
What Does This Code Do...
Wraps some X11 Window-Manager operations into a simpler interface. It also provides a weak method for Startup-Notification and some usefull, to me anyway, debug operations.
What Doesn't This Code Do...
This is legacy code. It is provided because the rest of the library may still be dependent on certain parts. It is currently on the 'deprecated' list.
//----------------------------------------------------------------------------- // xwinhlpr.c // // X11 window management helper implementation. // // Copyright (c) 2013 - No Fun Farms A.K.A. www.smegware.com // // All Smegware software is free; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This software 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. // //----------------------------------------------------------------------------- // // History... // // $Source$ // $Author$ // $Revision$ // // $Log$ // //----------------------------------------------------------------------------- #include <X11/X.h> #include <X11/Xlib.h> #include <X11/Xatom.h> #include <X11/Xutil.h> #include <stdio.h> #include <limits.h> #include <string.h> #include "xwinhlpr.h" #include "xwinatom.h" #include "report.h" //----------------------------------------------------------------------------- Atom xwin_set_window_property_atoms(Display *display, Window window, Atom property, unsigned char *value, int count) { Atom atm = XChangeProperty(display, window, property, XA_ATOM, 32, PropModeReplace, value, count); return atm; } //----------------------------------------------------------------------------- Atom xwin_get_window_property_atom(Display *display, Window window, Atom property, Atom type) { Atom atm_rtn = None; Atom actual_type; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char *prop_return = NULL; int status = XGetWindowProperty(display, window, property, 0L, 1,//sizeof(Atom), False, type, &actual_type, &actual_format, &nitems, &bytes_after, &prop_return); if((status == Success) && (prop_return != NULL)) { atm_rtn = *(Atom*)prop_return; XFree(prop_return); } return atm_rtn; } //----------------------------------------------------------------------------- Atom xwin_get_window_type(Display *display, Window window, Atom property) { Atom window_type = None; Atom actual_type; int actual_format; unsigned long nitems, bytes_after; Atom *prop_return = NULL; int rtn = XGetWindowProperty(display, window, property, 0, 1, False, XA_ATOM, &actual_type, &actual_format, &nitems, &bytes_after, (unsigned char**)&prop_return); if((rtn == Success) && prop_return) { window_type = *prop_return; XFree((unsigned char*)prop_return); } return window_type; } //----------------------------------------------------------------------------- Window xwin_get_active_window(Display *display, Window window, Atom property) { Window active_win = None; Atom actual_type; int actual_format; unsigned long nitems, bytes_after; unsigned char *prop_return = NULL; if(Success == XGetWindowProperty(display, window, property, 0L, sizeof(Window), False, XA_WINDOW, &actual_type, &actual_format, &nitems, &bytes_after, &prop_return) && prop_return) { active_win = *(Window *)prop_return; XFree(prop_return); } return active_win; } //----------------------------------------------------------------------------- Window *xwin_get_client_list(Display *display, Window root, unsigned long *nclients) { Window *clients = NULL; Atom actual_type; int actual_format; unsigned long nitems, bytes_after; unsigned char *prop_ret = NULL; if(Success == XGetWindowProperty(display, root, XInternAtom(display, "_NET_CLIENT_LIST", False), 0L, ULONG_MAX, False, XA_WINDOW, &actual_type, &actual_format, &nitems, &bytes_after, &prop_ret)) { clients = (Window *)prop_ret; *nclients = nitems; } return clients; } //----------------------------------------------------------------------------- void xwin_list_property(Display *display, Window window, Atom property) { int i; int r_format; unsigned long r_items; unsigned long r_leftover; Atom r_property; char *name; unsigned char *items = NULL; Atom *atoms; int *cardinals; // Strings. r_items = 0; XGetWindowProperty(display, window, property, 0, 128, False, XA_STRING, &r_property, &r_format, &r_items, &r_leftover, &items); if(items) { if(r_items) { report(dbglevl_debug, " : %s.\n", items); } XFree(items); } // Cardinals. r_items = 0; XGetWindowProperty(display, window, property, 0, 32/*16*/, False, XA_CARDINAL, &r_property, &r_format, &r_items, &r_leftover, &items); if(items) { cardinals = (int*)items; for(i = 0; i < r_items; i++) { report(dbglevl_debug, " : %08X.\n", cardinals[i]); } XFree(items); } // Atoms. r_items = 0; XGetWindowProperty(display, window, property, 0, 32, False, XA_ATOM, &r_property, &r_format, &r_items, &r_leftover, &items); if(items) { atoms = (Atom*)items; //report(dbglevl_debug, "XGetWindowProperty() returned %i...\n", r_items); for(i = 0; i < r_items; i++) { name = XGetAtomName(display, atoms[i]); report(dbglevl_debug, " : % 5i : %s.\n", atoms[i], name); if(name) { XFree(name); } } XFree(items); } // Hints. r_items = 0; XWMHints *hints; XGetWindowProperty(display, window, property, 0, 128, False, XA_WM_HINTS, &r_property, &r_format, &r_items, &r_leftover, &items); if(items) { if(r_items) { hints = (XWMHints*)items; report(dbglevl_debug, " : flags : %04X.\n", hints->flags); if(hints->flags & InputHint) { report(dbglevl_debug, " : input : %i.\n", hints->input); } if(hints->flags & StateHint) { report(dbglevl_debug, " : initial state : %i.\n", hints->initial_state); } if(hints->flags & IconPixmapHint) { report(dbglevl_debug, " : icon pixmap : %08X.\n", hints->icon_pixmap); } if(hints->flags & IconWindowHint) { report(dbglevl_debug, " : icon window : %08X.\n", hints->icon_window); } if(hints->flags & IconPositionHint) { report(dbglevl_debug, " : icon x : %i.\n", hints->icon_x); report(dbglevl_debug, " : icon y : %i.\n", hints->icon_y); } if(hints->flags & IconMaskHint) { report(dbglevl_debug, " : icon mask : %08X.\n", hints->icon_mask); } if(hints->flags & WindowGroupHint) { report(dbglevl_debug, " : window group : %08X.\n", hints->window_group); } } XFree(items); } r_items = 0; XSizeHints *size; XGetWindowProperty(display, window, property, 0, 128, False, XA_WM_NORMAL_HINTS, &r_property, &r_format, &r_items, &r_leftover, &items); if(items) { if(r_items) { size = (XSizeHints*)atoms; report(dbglevl_debug, " : flags : %04X.\n", size->flags); } XFree(items); } } //----------------------------------------------------------------------------- void xwin_list_properties(Display *display, Window window) { int i; int num_prop_return = 0; Atom *atoms = NULL; char *name; atoms = XListProperties(display, window, &num_prop_return); if(atoms) { report(dbglevl_debug, "XListProperties(%08X) returned %i...\n", window, num_prop_return); for(i = 0; i < num_prop_return; i++) { name = XGetAtomName(display, atoms[i]); report(dbglevl_debug, " % 16i : %s.\n", atoms[i], name); xwin_list_property(display, window, atoms[i]); if(name) { XFree(name); } } XFree(atoms); } } //----------------------------------------------------------------------------- void xwin_list_font_metrics(Display *display, XID id, char *s) { int direction; int ascent; int descent; XCharStruct xchar; XQueryTextExtents(display, id, s, strlen(s), &direction, &ascent, &descent, &xchar); report(dbglevl_debug, "XQueryTextExtents(%s) returned...\n", s); report(dbglevl_debug, " direction : %i.\n", direction); report(dbglevl_debug, " ascent : %i.\n", ascent); report(dbglevl_debug, " descent : %i.\n", descent); report(dbglevl_debug, " combined width : %i.\n", xchar.width); } //----------------------------------------------------------------------------- void xwin_list_font_names(Display *display, char **s) { int n; int ncount; s = XListFonts(display, "*", 32768, &ncount); report(dbglevl_debug, "XListFonts() returned...\n", s); for(n = 0; n < ncount; n++) { report(dbglevl_none, " font : %s.\n", s[n]); } } //----------------------------------------------------------------------------- void xwin_set_opacity(Display *display, Window window, Atom property, unsigned long opacity) { XChangeProperty(display, window, property, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&opacity, 1L); } //----------------------------------------------------------------------------- void xwin_begin_startup_notification(Display *display, Window window, int screen, char *ds_id, char *name) { int i; int x; char message[256]; char partial[21]; if(ds_id) { XEvent event; event.xclient.type = ClientMessage; event.xclient.display = display; event.xclient.window = window; event.xclient.format = 8; event.xclient.message_type = _NET_STARTUP_INFO_BEGIN; snprintf(message, sizeof(message) - 1, "new: ID=\"%s\" NAME=\"%s\" SCREEN=%i", ds_id, name, screen); message[sizeof(message) - 1] = '\0'; x = strlen(message) + 1; partial[20] = '\0'; report(dbglevl_debug, "Startup Notification : "); for(i = 0; i < x; i += 20) { memcpy(event.xclient.data.b, &message[i], 20); memcpy(partial, event.xclient.data.b, 20); if((i + 20) < x) { event.xclient.data.b[x - i] = '\0'; } report(dbglevl_debug, "%s", partial); XSendEvent(display, RootWindow(display, screen), False, PropertyChangeMask, &event); event.xclient.message_type = _NET_STARTUP_INFO; // remainder of message requires this type. } report(dbglevl_debug, ".\n"); } else { report(dbglevl_debug, "Startup Notification : no startup id.\n"); } } //----------------------------------------------------------------------------- void xwin_complete_startup_notification(Display *display, Window window, int screen, char *ds_id, char *name) { int i; int x; char message[256]; char partial[21]; if(ds_id) { XEvent event; event.xclient.type = ClientMessage; event.xclient.display = display; event.xclient.window = window; event.xclient.format = 8; event.xclient.message_type = _NET_STARTUP_INFO_BEGIN; snprintf(message, sizeof(message) - 1, "remove: ID=\"%s\" NAME=\"%s\" SCREEN=%i", ds_id, name, screen); message[sizeof(message) - 1] = '\0'; x = strlen(message) + 1; partial[20] = '\0'; report(dbglevl_debug, "Startup Notification : "); for(i = 0; i < x; i += 20) { memcpy(event.xclient.data.b, &message[i], 20); memcpy(partial, event.xclient.data.b, 20); if((i + 20) < x) { event.xclient.data.b[x - i] = '\0'; } report(dbglevl_debug, "%s", partial); XSendEvent(display, RootWindow(display, screen), False, PropertyChangeMask, &event); event.xclient.message_type = _NET_STARTUP_INFO; // remainder of message requires this type. } report(dbglevl_debug, ".\n"); } } //----------------------------------------------------------------------------- // end: xwinhlpr.c //
And The Companion Header...
//----------------------------------------------------------------------------- // xwinhlpr.h // // X11 window management helper definition. // // Copyright (c) 2013 - No Fun Farms A.K.A. www.smegware.com // // All Smegware software is free; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This software 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. // //----------------------------------------------------------------------------- // // History... // // $Source$ // $Author$ // $Revision$ // // $Log$ // //----------------------------------------------------------------------------- extern Atom xwin_get_window_type(Display*, Window, Atom); extern Window xwin_get_active_window(Display*, Window, Atom); extern Window *xwin_get_client_list(Display*, Window, unsigned long*); extern void xwin_set_opacity(Display*, Window, Atom, unsigned long); extern Atom xwin_set_window_property_atoms(Display*, Window, Atom, unsigned char*, int); extern Atom xwin_get_window_property_atom(Display*, Window, Atom, Atom); extern void xwin_list_property(Display*, Window, Atom); extern void xwin_list_properties(Display*, Window); extern void xwin_list_font_metrics(Display*, XID, char*); extern void xwin_list_font_names(Display*, char**); extern void xwin_begin_startup_notification(Display*, Window, int, char*, char*); extern void xwin_complete_startup_notification(Display*, Window, int, char*, char*); //----------------------------------------------------------------------------- // end: xwinhlpr.h //
The Code Demonstrates The Following Programming Techniques...
Conclusion...
It is known that this code has many 'Freshman' mistakes in it. It is not claimed to be good code. Hopefully though; it demonstrates some of the less obvious interface mechanisms when communicating with both a Window-Manager and a Client program. A definition of how to use the code is also missing. Not purposely, an interface spec just can't be fit into my schedule. For now. Besides... This code is not really meant to be used. Although I use this code it is presented here purely for educational purposes.
6996