asvisual(3x)

✨ asvisual(3x) β€” AfterStep X11 window manager ✨

okay bestie, sit down, hydrate, and let's talk about asvisual β€” the libAfterImage header libAfterImage/asvisual.h that gives us an abstraction layer sitting right on top of X Visuals and zeroes in on color handling. it's giving foundational, it's giving under-appreciated, and you're gonna love it. 🫢


🌸 NAME 🌸

asvisual β€” defines an abstraction layer on top of X Visuals, as well as several fundamental color datatypes. πŸ’…


πŸ¦‹ SEE ALSO πŸ¦‹

Structures πŸŽ€

  • ColorPair
  • ASVisual

Functions πŸŽ€

ASVisual initialization :

  • query_screen_visual(), setup_truecolor_visual(), setup_pseudo_visual(), setup_as_colormap(), create_asvisual(), destroy_asvisual()

ASVisual encoding/decoding :

  • visual2visual_prop(), visual_prop2visual()

ASVisual convenience functions :

  • create_visual_window(), create_visual_pixmap(), create_visual_ximage()

Other libAfterImage modules πŸŽ€

ascmap.h asfont.h asimage.h asvisual.h blender.h export.h import.h transform.h ximage.h


πŸ‘‘ AUTHOR πŸ‘‘

Sasha Vasko <sasha at aftercode dot net>

libAfterImage/alpha


πŸ’œ FUNCTION πŸ’œ

the Alpha channel is literally just a visibility parameter bolted onto your color value. an Alpha channel value of 0xFF means completely visible (iconic, seen, unmasked), and 0 makes that pixel completely transparent β€” like, gone, invisible, not the main character. 😭


πŸŽ€ SOURCE πŸŽ€

#define ALPHA_TRANSPARENT       0x00
#define ALPHA_SEMI_TRANSPARENT  0x7F
#define ALPHA_SOLID             0xFF

⭐ libAfterImage/ARGB32 ⭐

🌈 NAME 🌈

ARGB32 β€” the main color datatype. periodt.

πŸ’… FUNCTION πŸ’…

ARGB32 is the fundamental datatype, holding a 32bit value that corresponds to a pixel's color and its transparency value (the alpha channel) in the ARGB colorspace. it's encoded like this, no cap:

  • lowermost 8 bits β€” Blue channel
  • bits 8 to 15 β€” Green channel
  • bits 16 to 23 β€” Red channel
  • bits 24 to 31 β€” Alpha channel

πŸ¦‹ EXAMPLE πŸ¦‹

ASTile.1

✨ SOURCE ✨

typedef CARD32 ARGB32;
#define ARGB32_White            0xFFFFFFFF
#define ARGB32_Black            0xFF000000
/* default background color is #FF000000 : */
#define ARGB32_DEFAULT_BACK_COLOR ARGB32_Black

#define ARGB32_ALPHA_CHAN       3
#define ARGB32_RED_CHAN         2
#define ARGB32_GREEN_CHAN       1
#define ARGB32_BLUE_CHAN        0
#define ARGB32_CHANNELS         4

#define MAKE_ARGB32(a,r,g,b)    ((( (CARD32)a)        <<24)| \
                                         ((((CARD32)r)&0x00FF)<<16)| \
                                         ((((CARD32)g)&0x00FF)<<8 )| \
                                         (( (CARD32)b)&0x00FF))

#define MAKE_ARGB32_GREY8(a,l)  (((a)<<24)|(((l)&0x00FF)<<16)| \
                                         (((l)&0x00FF)<<8)|((l)&0x00FF))
#define ARGB32_ALPHA8(c)        (((c)>>24)&0x00FF)
#define ARGB32_RED8(c)          (((c)>>16)&0x00FF)
#define ARGB32_GREEN8(c)        (((c)>>8 )&0x00FF)
#define ARGB32_BLUE8(c)         ( (c) &0x00FF)
#define ARGB32_CHAN8(c,i)       (((c)>>((i)<<3))&0x00FF)
#define MAKE_ARGB32_CHAN8(v,i)  (((v)&0x0000FF)<<((i)<<3))

#ifdef __GNUC__
#define ARGB32_ALPHA16(c)       ({ CARD32 __c = ARGB32_ALPHA8(c); __c | (__c<<8);})
#define ARGB32_RED16(c)         ({ CARD32 __c = ARGB32_RED8(c); __c | (__c<<8);})
#define ARGB32_GREEN16(c)       ({ CARD32 __c = ARGB32_GREEN8(c); __c | (__c<<8);})
#define ARGB32_BLUE16(c)        ({ CARD32 __c = ARGB32_BLUE8(c); __c | (__c<<8);})
#define ARGB32_CHAN16(c,i)      ({ CARD32 __c = ARGB32_CHAN8(c,i); __c | (__c<<8);})
#else
#define ARGB32_ALPHA16(c)       ((((c)>>16)&0x00FF00)|(((c)>>24)&0x0000FF))
#define ARGB32_RED16(c)         ((((c)>>8 )&0x00FF00)|(((c)>>16)&0x0000FF))
#define ARGB32_GREEN16(c)       ((((c)     &0x00FF00)|(((c)>>8 )&0x0000FF))
#define ARGB32_BLUE16(c)        ((((c)<<8) &0x00FF00)|(((c)    )&0x0000FF))
#define ARGB32_CHAN16(c,i)      ((ARGB32_CHAN8(c,i)<<8)|ARGB32_CHAN8(c,i))
#endif

#define MAKE_ARGB32_CHAN16(v,i) ((((v)&0x00FF00)>>8)<<((i)<<3))

🧚 libAfterImage/ARGB32_manhattan_distance() 🧚

πŸ’– NAME πŸ’–

ARGB32_manhattan_distance() β€” this function can be used to evaluate the closeness of two colors. vibe check for colors fr fr.

⭐ SYNOPSIS ⭐

long ARGB32_manhattan_distance (long a, long b);

🌸 INPUTS 🌸

  • a, b β€” ARGB32 color values to calculate Manhattan distance in between

πŸ’€ RETURN VALUE πŸ’€

returns the calculated Manhattan distance. 🌈


πŸŽ€ libAfterImage/ColorPart πŸŽ€

πŸ‘‘ NAME πŸ‘‘

  • IC_RED β€” red channel
  • IC_GREEN β€” green channel
  • IC_BLUE β€” blue channel
  • IC_ALPHA β€” alpha channel
  • IC_NUM_CHANNELS β€” number of supported channels

πŸ’œ FUNCTION πŸ’œ

these are the Ids of the channels. they're basically synonyms to the related ARGB32 channel numbers β€” same energy, different name, iykyk. ✨

πŸ¦‹ SOURCE πŸ¦‹

typedef enum {
  IC_BLUE   = ARGB32_BLUE_CHAN ,
  IC_GREEN  = ARGB32_GREEN_CHAN,
  IC_RED    = ARGB32_RED_CHAN  ,
  IC_ALPHA  = ARGB32_ALPHA_CHAN,
  IC_NUM_CHANNELS = ARGB32_CHANNELS } ColorPart;

πŸ’– libAfterImage/ColorPair πŸ’–

🌈 NAME 🌈

ColorPair β€” a convenient structure to hold a pair of colors. two colors, one struct, adorable. πŸ₯Ί

⭐ SOURCE ⭐

typedef struct ColorPair {
  ARGB32 fore;
  ARGB32 back; }ColorPair;

πŸ‘‘ libAfterImage/ASVisual πŸ‘‘

πŸŽ€ NAME πŸŽ€

ASVisual β€” an abstraction layer on top of X Server Visual.

✨ DESCRIPTION ✨

so this structure exists to compensate for the fact that X may have, like, so many different types of Visuals. bestie, it's a lot. ASVisual provides shortcuts to most Visual data, compensated for differences in Visuals. πŸ”₯

for PseudoColor visual it also contains a preallocated set of colors. this colormap lets us write XImages very fast and without exhausting the available X colors. this colormap consists of 8, 64, or 4096 colors and constitutes a fraction of the colors available in a particular colordepth. these colors are allocated to be evenly spread around the RGB spectrum. so when converting from internal presentation β€” all we need to do is discard unused bits, and use the rest of those bits as an index in our colormap. the opposite conversion is much trickier and we engage in the nasty business of having a hash table mapping pixel values into colors, or a straight table doing the same in lower colordepths. the idea is that we do all internal processing in 32bit colordepth, and ASVisual provides us with the means to convert it to actual X display format. respectively, ASVisual has methods to write out XImage lines and read XImage lines.

ASVisual creation is a tricky process. basically first we have to go through the list of available Visuals and choose the best suitable one. then, based on the type of this Visual, we have to set up our data members and method hooks. several functions are provided for that:

  • query_screen_visual() β€” will lookup best suitable visual
  • setup_truecolor_visual() β€” will setup hooks if visual is TrueColor
  • setup_pseudo_visual() β€” will setup hooks and data if Visual is PseudoColor.
  • setup_as_colormap() β€” will preallocate colors for PseudoColor.

an alternative to the above is:

  • create_asvisual() β€” it encapsulates all of the above functionality, and returns a completely set up ASVisual object.

since the Visual selected for ASVisual may differ from the default (we choose the best suitable one), all the window creation functions must provide a colormap and some other parameters, like border color for example. so we created some convenience functions. these should be used instead of standard Xlib calls:

  • create_visual_window() β€” to create window
  • create_visual_pixmap() β€” to create pixmap
  • create_visual_ximage() β€” to create XImage

ASVisual could be deallocated and its resources freed with:

  • destroy_asvisual()
πŸ’€ seriously, when it's giving manual resource management, use the helpers. don't raw-dog the Xlib calls and then act surprised.

🌸 EXAMPLE 🌸

asview.c: ASView


✨ SOURCE ✨

okay bestie, here's the literal ASVisual struct definition β€” it's the blueprint, the whole vibe. Don't skim this, it's lowkey important. πŸ‘‘

           typedef struct ASVisual {
               Display      *dpy;

               /* This envvar will be used to determine what X Visual
                * (in hex) to use. If unset then best possible will
                * be selected automagically : */ #define ASVISUAL_ID_ENVVAR
           "AFTERIMAGE_VISUAL_ID"

               XVisualInfo   visual_info;
               /* this things are calculated based on Visual : */
               unsigned long rshift, gshift, bshift;
               unsigned long rbits,  gbits,  bbits;
               unsigned long true_depth;   /* could be 15 when X reports 16 */
               Bool          BGR_mode;
               Bool          msb_first;
               /* we must have colormap so that we can safely create windows
                * with different visuals even if we are in TrueColor mode : */
               Colormap      colormap;
               Bool          own_colormap; /* tells us to free colormap when we
                                            * done */
               unsigned long black_pixel, white_pixel;
               /* for PseudoColor mode we need some more stuff : */
               enum {
                   ACM_None = 0,
                   ACM_3BPP,
                   ACM_6BPP,
                   ACM_12BPP
               } as_colormap_type ;    /* there can only be 64 or 4096 entries
                                        * so far ( 6 or 12 bpp) */
               unsigned long *as_colormap; /* array of preallocated colors for
                                            * PseudoColor mode */
               union                       /* reverse color lookup tables : */
               {
                   ARGB32              *xref;
                   struct ASHashTable  *hash;
               }as_colormap_reverse ;

               /* different useful callbacks : */
               CARD32 (*color2pixel_func)    ( struct ASVisual *asv,
                                               CARD32 encoded_color,
                                               unsigned long *pixel);
               void   (*pixel2color_func)    ( struct ASVisual *asv,
                                               unsigned long pixel,
                                               CARD32 *red, CARD32 *green,
                                               CARD32 *blue);
               void   (*ximage2scanline_func)( struct ASVisual *asv,
                                               XImage *xim,
                                               struct ASScanline *sl, int y,
                                               unsigned char *xim_data );
               void   (*scanline2ximage_func)( struct ASVisual *asv,
                                               XImage *xim,
                                               struct ASScanline *sl, int y,
                                               unsigned char *xim_data );

           #define ASGLX_Unavailable           0 #define ASGLX_Available
           (0x01<<0) #define ASGLX_DoubleBuffer          (0x01<<1) #define
           ASGLX_RGBA                  (0x01<<2) #define ASGLX_UseForImageTx
           (0x01<<3)
               ASFlagType glx_support ;    /* one of the above flags */

               void *glx_scratch_gc_indirect ; /* (GLXContext) */
               void *glx_scratch_gc_direct ;   /* (GLXContext) */

               Window scratch_window;

           #ifndef X_DISPLAY_MISSING #define ARGB2PIXEL(asv,argb,pixel)
           \
               (asv)->color2pixel_func((asv),(argb),(pixel)) #define
           GET_SCANLINE(asv,xim,sl,y,xim_data) \
               (asv)->ximage2scanline_func((asv),(xim),(sl),(y),(xim_data))
           #define PUT_SCANLINE(asv,xim,sl,y,xim_data) \
               (asv)->scanline2ximage_func((asv),(xim),(sl),(y),(xim_data))
           #else #define ARGB2PIXEL(asv,argb,pixel)         \
               do{ break; }while(0) #define GET_SCANLINE(asv,xim,sl,y,xim_data)
           \
               do{ break; }while(0) #define PUT_SCANLINE(asv,xim,sl,y,xim_data)
           \
               do{ break; }while(0) #endif }ASVisual;
the way that AFTERIMAGE_VISUAL_ID env var determines what X Visual (in hex) to use, and if it's unset, best possible is selected automagically ✨. No cap.

and this whole struct lives in libAfterImage/query_screen_visual().


now let's talk about the functions that actually do stuff with it. first up:

✨ NAME ✨

query_screen_visual_id() query_screen_visual()

✨ SYNOPSIS ✨

       Bool query_screen_visual_id( ASVisual *asv, Display *dpy, int screen,
                                 Window root, int default_depth,
                                    VisualID visual_id, Colormap cmap ); Bool
       query_screen_visual( ASVisual *asv, Display *dpy, int screen,
                                 Window root, int default_depth );

✨ INPUTS ✨

  • asv β€” preallocated ASVisual structure.
  • dpy β€” valid pointer to opened X display.
  • screen β€” screen number on which to query visuals.
  • root β€” root window on that screen.
  • default_depth β€” default colordepth of the screen.
  • visual_id β€” optional ID of preferred Visual.
  • cmap β€” optional colormap to be used.

✨ RETURN VALUE ✨

True on success, False on failure. The ASVisual structure pointed by asv will have the following data members set on success: dpy, visual_info, colormap, own_colormap, black_pixel, white_pixel.

✨ DESCRIPTION ✨

query_screen_visual_id() will go through a prioritized list of possible Visuals and attempt to match those to what is available on the specified screen. If all items from the list fail, then it goes about querying the default visual. query_screen_visual is identical to query_screen_visual_id with visual_id and cmap set to 0. Once X Visual has been identified, we create an X colormap and allocate white and black pixels from it. πŸ’…

source: libAfterImage/setup_truecolor_visual()


✨ NAME ✨

setup_truecolor_visual()

✨ SYNOPSIS ✨

       Bool setup_truecolor_visual( ASVisual *asv );

✨ INPUTS ✨

  • asv β€” preallocated ASVisual structure.

✨ RETURN VALUE ✨

True on success, False if visual is not TrueColor.

✨ DESCRIPTION ✨

setup_truecolor_visual() checks if the Visual is indeed TrueColor and if so it goes about querying color masks, deducing real XImage colordepth, and whether we work in BGR mode. It then goes about setting up correct hooks to X IO functions. 🎨

source: libAfterImage/setup_pseudo_visual()


✨ NAME ✨

setup_pseudo_visual()

✨ SYNOPSIS ✨

       void setup_pseudo_visual( ASVisual *asv  );

✨ INPUTS ✨

  • asv β€” preallocated ASVisual structure.

✨ DESCRIPTION ✨

setup_pseudo_visual() assumes that Visual is PseudoColor. It then tries to decide as to how many colors preallocate, and goes about setting up correct X IO hooks and possibly initialization of reverse colormap in case ASVisual already has colormap preallocated. 🌈

source: libAfterImage/setup_as_colormap()


✨ NAME ✨

setup_as_colormap()

✨ SYNOPSIS ✨

       void setup_as_colormap( ASVisual *asv );

✨ INPUTS ✨

  • asv β€” preallocated ASVisual structure.

✨ DESCRIPTION ✨

That has to be called in order to pre-allocate a sufficient number of colors. It uses colormap size identification supplied in ASVisual structure. If colors where preallocated successfully β€” it will also create reverse lookup colormap. πŸ’–

source: libAfterImage/create_asvisual_for_id()


✨ NAME ✨

create_asvisual_for_id()

✨ SYNOPSIS ✨

       ASVisual *create_asvisual_for_id( Display *dpy, int screen,
                                         int default_depth,
                                         VisualID visual_id, Colormap cmap,
                                         ASVisual *reusable_memory );

✨ INPUTS ✨

  • dpy β€” valid pointer to opened X display.
  • screen β€” screen number on which to query visuals.
  • root β€” root window on that screen.
  • default_depth β€” default colordepth of the screen.
  • visual_id β€” ID of X visual to use.
  • cmap β€” optional ID of the colormap to be used.
  • reusable_memory β€” pointer to preallocated ASVisual structure.

✨ RETURN VALUE ✨

Pointer to ASVisual structure initialized with enough information to be able to deal with current X Visual.

✨ DESCRIPTION ✨

This function calls all the needed functions in order to setup a new ASVisual structure for the specified screen and visual. If reusable_memory is not null β€” it will not allocate a new ASVisual structure, but instead will use the supplied one. Useful for allocating ASVisual on stack. This particular function will not do any autodetection and will use the Visual ID supplied. That is useful when libAfterImage is used with an app that has its own approach to Visual handling, and since Visuals on all Windows, Pixmaps and colormaps must match, there is a need to synchronise visuals used by an app and libAfterImage. πŸ‘‘

source: libAfterImage/create_asvisual()


✨ NAME ✨

create_asvisual()

✨ SYNOPSIS ✨

       ASVisual *create_asvisual( Display *dpy, int screen,
                                  int default_depth,
                                  ASVisual *reusable_memory );

✨ INPUTS ✨

  • dpy β€” valid pointer to opened X display.
  • screen β€” screen number on which to query visuals.
  • root β€” root window on that screen.
  • default_depth β€” default colordepth of the screen.
  • reusable_memory β€” pointer to preallocated ASVisual structure.

✨ RETURN VALUE ✨

Pointer to ASVisual structure initialized with enough information to be able to deal with current X Visual.

✨ DESCRIPTION ✨

This function calls all the needed functions in order to setup a new ASVisual structure for the specified screen. If reusable_memory is not null β€” it will not allocate a new ASVisual structure, but instead will use the supplied one. Useful for allocating ASVisual on stack. It is different from create_asvisualfor_id() in that it will attempt to autodetect the best possible visual for the screen. For example on some SUN Solaris X servers there will be both 8bpp pseudocolor and 24bpp truecolor, and default will be 8bpp. In this scenario libAfterImage will detect and use 24bpp true color visual, thus producing much better results. 🌞

source: libAfterImage/destroy_asvisual()


✨ NAME ✨

destroy_asvisual()

✨ SYNOPSIS ✨

       void destroy_asvisual( ASVisual *asv, Bool reusable );

✨ INPUTS ✨

  • asv β€” valid ASVisual structure.
  • reusable β€” if True it will cause function to not free object itself.

✨ DESCRIPTION ✨

Cleanup function. Frees all the memory and deallocates all the resources. If reusable is False it will also free the object, pointed to by asv. πŸ’€


✨ EXAMPLE ✨

asview.c: ASView.2

source: libAfterImage/visual2visual_prop()


✨ NAME ✨

visual2visual_prop()

✨ SYNOPSIS ✨

       Bool visual2visual_prop( ASVisual *asv, size_t *size,
                                unsigned long *version, unsigned long **data );

✨ INPUTS ✨

  • asv β€” valid ASVisual structure.

✨ RETURN VALUE ✨

  • size β€” size of the encoded memory block.
  • version β€” version of the encoding.
  • data β€” actual encoded memory block.
  • True on success, False on failure.

✨ DESCRIPTION ✨

This function will encode ASVisual structure into a memory block of 32 bit values, suitable for storing in X property. πŸ“¦

source: libAfterImage/visual_prop2visual()


✨ NAME ✨

visual_prop2visual()

✨ SYNOPSIS ✨

       Bool visual_prop2visual( ASVisual *asv, Display *dpy, int screen,
                                size_t size,
                                unsigned long version, unsigned long *data );

✨ INPUTS ✨

  • asv β€” valid ASVisual structure.
  • dpy β€” valid pointer to open X display.
  • screen β€” screen number.
  • size β€” encoded memory block's size.
  • version β€” version of encoding.
  • data β€” actual encoded memory block.

✨ RETURN VALUE ✨

True on success, False on failure.

bestie, so visual_prop2visual() reads ASVisual data right back out of that memory block that visual2visual_prop() encoded for you πŸ’–. It's the whole point of the round trip: yank data out of an X property and turn it into stuff you can actually use β€” colormap, visual info, all of it ✨. Just know that setup_truecolor_visual() or setup_pseudo_visual() has to be invoked, otherwise your ASVisual setup is literally unfinished, no cap 🫢.

libAfterImage/create_visual_window()


🌈 NAME β€” create_visual_window()

πŸ¦‹ SYNOPSIS

Window  create_visual_window( ASVisual *asv, Window parent,
                              int x, int y,
                              unsigned int width, unsigned int height,
                              unsigned int border_width,
                              unsigned int wclass,
                              unsigned long mask,
                              XSetWindowAttributes *attributes );

✨ INPUTS

  • asv β€” pointer to the valid ASVisual structure, bestie. Gotta be valid, okay?
  • parent β€” Window ID of the parent the window πŸ‘‘.
  • x, y β€” where the new window first spawns, its initial position πŸ“.
  • width, height β€” the new window's initial size πŸ“.
  • border_width β€” initial border width of the new window πŸŽ€.
  • wclass β€” Window class, and the only two vibes allowed are InputOnly or InputOutput πŸ’….
  • mask β€” defines what attributes are set 🌸.
  • attributes β€” the different window attributes, all the little extras πŸ¦‹.

πŸ’œ RETURN VALUE

The ID of the newly created window when it works out, bestie πŸ₯³. None when it does not 😭.

🌟 DESCRIPTION

create_visual_window() does sanity checks on the parameters you passed in β€” vibe check first, always β€” then it adds the mandatory attributes if they're needed, and after that it attempts to create a window for the specified ASVisual ✨.

libAfterImage/create_visual_gc()


🌈 NAME β€” create_visual_gc()

πŸ¦‹ SYNOPSIS

GC      create_visual_gc( ASVisual *asv, Window root,
                          unsigned long mask, XGCValues *gcvalues );

✨ INPUTS

  • asv β€” pointer to the valid ASVisual structure πŸ’–.
  • root β€” Window ID of the root window of destination screen 🌍.
  • mask, gcvalues β€” values for creation of the new GC β€” go look at XCreateGC() for the deets, iykyk πŸ‘€.

πŸ’œ RETURN VALUE

A new GC created for a regular window on success πŸŽ‰. NULL on failure πŸ’€.

🌟 DESCRIPTION

create_visual_gc() makes a temporary window for the depth and Visual that's specific to the ASVisual, and then it creates a GC for that window 🎨. The GC you get back is good to be used for manipulation of windows and Pixmaps created for that same ASVisual β€” same ASVisual, same energy, periodt πŸ‘‘.

libAfterImage/create_visual_pixmap()


🌈 NAME β€” create_visual_pixmap()

πŸ¦‹ SYNOPSIS

Pixmap  create_visual_pixmap( ASVisual *asv, Window root,
                              unsigned int width, unsigned int height,
                              unsigned int depth );

✨ INPUTS

  • asv β€” pointer to the valid ASVisual structure 🫢.
  • root β€” Window ID of the root window of destination screen 🌍.
  • width, height β€” size of the pixmap to create πŸ“.
  • depth β€” depth of the pixmap to create. If it's 0, then asv->true_depth gets used instead πŸŒ€.

πŸ’œ RETURN VALUE

The ID of the newly created pixmap on success ✨. None on failure 😭.

🌟 DESCRIPTION

create_visual_pixmap() performs sanity checks on the parameters you passed, and then it attempts to create a pixmap for the specified ASVisual, root and depth β€” three-for-three, slay πŸŽ€.

libAfterImage/create_visual_ximage()


🌈 NAME β€” create_visual_ximage()

πŸ¦‹ SYNOPSIS

XImage* create_visual_ximage( ASVisual *asv,
                              unsigned int width, unsigned int height,
                              unsigned int depth );

✨ INPUTS

  • asv β€” pointer to the valid ASVisual structure πŸ’œ.
  • width, height β€” size of the XImage to create πŸ“.
  • depth β€” depth of the XImage to create. If it's 0, then asv->true_depth gets used instead πŸŒ€.

πŸ’œ RETURN VALUE

A pointer to the newly created XImage on success 🌟. NULL on failure πŸ’€.

🌟 DESCRIPTION

create_visual_ximage() performs sanity checks on the parameters you passed, and it will attempt to create an XImage of sufficient size, at the colordepth you specified πŸ–ΌοΈ. It also sets up hooks so that XImage deallocation gets handled by a custom function β€” cleanup is handled, we love to see it 🫢✨.


okay that's genuinely the whole page, bestie πŸ₯ΉπŸ’– we did it. no skipped options, no skipped nothin'.

Source: the 3rd Berkeley Distribution 🌈, and this is AfterStep v.2.2.12 πŸ’…, living in section asvisual(3x) of the manual. Footer didn't hand me a date, so that's all she wrote β€” mwah πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from