diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | window.c | 335 | ||||
-rw-r--r-- | window.h | 8 |
4 files changed, 298 insertions, 48 deletions
@@ -1,4 +1,4 @@ -CFLAGS = `pkg-config --cflags pixman-1 x11` +CFLAGS = `pkg-config --cflags pixman-1 x11` -Wall LDFLAGS = `pkg-config --libs pixman-1 x11` pintria: window.c window.h main.c @@ -4,4 +4,5 @@ int main () { printf ("Hello world\n"); + return 0; } @@ -1,26 +1,138 @@ #include <stdlib.h> #include <X11/Xlib.h> +#include <X11/Xutil.h> #include "window.h" struct ws_t { - Display *display; + Display * display; + Visual * visual; + pixman_format_code_t format; + pixman_bool_t composited; + pixman_bool_t has_alpha; }; struct window_t { + ws_t *ws; XID xid; + int ref_count; + pixman_image_t *backing_store; + int x, y; }; +static pixman_bool_t +is_composited (Display *dpy) +{ + Atom atom = XInternAtom (dpy, "_NET_WM_CM_S0", True); + + return atom && XGetSelectionOwner (dpy, atom) != None; +} + +static int +popcount (uint32_t v) +{ + int n = 0; + while (v) + { + if (v & 1) + n++; + v >>= 1; + } + return n; +} + +static pixman_bool_t +visual_to_format (Visual *visual, int depth, pixman_format_code_t *format_o) +{ + pixman_format_code_t format; + int format_type, bpp; + int a, r, g, b; + + /* Not bothering with anything but TrueColor */ + if (visual->class != TrueColor) + return FALSE; + + r = popcount (visual->red_mask); + g = popcount (visual->green_mask); + b = popcount (visual->blue_mask); + a = depth - (r + g + b); + + if (visual->red_mask > visual->blue_mask) + format_type = PIXMAN_TYPE_ARGB; + else + format_type = PIXMAN_TYPE_ABGR; + + if (depth > 16) + bpp = 32; + else if (depth > 8) + bpp = 16; + else if (depth > 4) + bpp = 8; + else if (depth == 4) + bpp = 4; + else + return FALSE; + + format = PIXMAN_FORMAT (bpp, format_type, a, r, g, b); + + if (!pixman_format_supported_destination (format)) + return FALSE; + + *format_o = format; + return TRUE; +} + /* Window system */ ws_t * ws_open (void) { - ws_t *ws = malloc (sizeof *ws); + ws_t *ws; + Display *display; + int depth; - ws->display = XOpenDisplay (NULL); + if (!(display = XOpenDisplay (NULL))) + return NULL; + + ws = malloc (sizeof *ws); + ws->display = display; + ws->composited = is_composited (display); + + /* Use the default visual ... */ + depth = DefaultDepth (ws->display, 0); + ws->visual = DefaultVisual (ws->display, 0); + ws->has_alpha = FALSE; + + /* ... unless there is an ARGB visual available */ + if (ws->composited) + { + XVisualInfo *visual_list; + XVisualInfo visual_template; + int n_visuals, i; + + n_visuals = 0; + visual_template.screen = 0; + visual_list = XGetVisualInfo (ws->display, VisualScreenMask, &visual_template, &n_visuals); - if (!ws->display) + for (i = 0; i < n_visuals; ++i) + { + XVisualInfo *visinfo = &(visual_list[i]); + + if (visinfo->class == TrueColor && + visinfo->depth == 32 && + (visinfo->red_mask == 0x00ff0000 && + visinfo->green_mask == 0x0000ff00 && + visinfo->blue_mask == 0x000000ff)) + { + depth = 32; + ws->visual = visinfo->visual; + ws->has_alpha = TRUE; + break; + } + } + } + + if (!visual_to_format (ws->visual, depth, &ws->format)) return NULL; return ws; @@ -28,54 +140,183 @@ ws_open (void) /* Window */ window_t * -ws_create_window (ws_t *ws, - int x, - int y, - int width, - int height) +ws_create_window (ws_t *ws, + int x, + int y, + int width, + int height) { window_t *window = malloc (sizeof *window); Window root = DefaultRootWindow (ws->display); + XSetWindowAttributes attr; + + attr.background_pixmap = None; - window->xid = XCreateSimpleWindow ( - ws->display, root, x, y, width, height, 0, 0, None); + window->xid = XCreateWindow ( + ws->display, root, x, y, width, height, 0, + DefaultDepth (ws->display, 0), InputOutput, + DefaultVisual (ws->display, 0), CWBackPixmap, &attr); + window->ref_count = 1; + window->backing_store = + pixman_image_create_bits (PIXMAN_a8r8g8b8, width, height, NULL, -1); + window->ws = ws; + window->x = x; + window->y = y; return window; } -void ws_window_ref (window_t *window); -void ws_window_unref (window_t *window); -void ws_window_show (window_t *window); -void ws_window_hide (window_t *window); -void ws_window_move (window_t *window, - int x, - int y); -void ws_window_resize (window_t *window, - int w, - int h); -void ws_window_copy_area (window_t *window, - int src_x, - int src_y, - int dst_x, - int dst_y, - int width, - int height); -void ws_window_copy_from_image (window_t *window, - pixman_image_t *image, - int image_x, - int image_y, - int win_x, - int win_y, - int width, - int height); -void ws_window_copy_to_image (window_t *window, - pixman_image_t *image, - int image_x, - int image_y, - int win_x, - int win_y, - int width, - int height); - -void ws_window_finish (window_t **windows, - int n_windows); +void +ws_window_ref (window_t *window) +{ + window->ref_count++; + return; +} + +void +ws_window_unref (window_t *window) +{ + if (--window->ref_count == 0) + { + XDestroyWindow (window->ws->display, window->xid); + free (window); + } +} + +void +ws_window_show (window_t *window) +{ + XMapWindow (window->ws->display, window->xid); +} + +void +ws_window_hide (window_t *window) +{ + XUnmapWindow (window->ws->display, window->xid); +} + +static int +get_width (window_t *window) +{ + return pixman_image_get_width (window->backing_store); +} + +static int +get_height (window_t *window) +{ + return pixman_image_get_height (window->backing_store); +} + +#define MIN(a,b) (((a) < (b))? (a) : (b)) + +static void +ws_window_move_resize (window_t *window, + int x, + int y, + int width, + int height) +{ + int old_width = get_width (window); + int old_height = get_height (window); + + if (width != old_width || height != old_height) + { + pixman_image_t *new_backing = + pixman_image_create_bits (PIXMAN_a8r8g8b8, width, height, NULL, -1); + + pixman_image_composite32 ( + PIXMAN_OP_SRC, + window->backing_store, NULL, new_backing, + 0, 0, 0, 0, 0, 0, + MIN (width, old_width), + MIN (height, old_height)); + + pixman_image_unref (window->backing_store); + window->backing_store = new_backing; + } + + window->x = x; + window->y = y; + + XMoveResizeWindow ( + window->ws->display, window->xid, x, y, width, height); +} + +void +ws_window_move (window_t *window, + int x, + int y) +{ + ws_window_move_resize ( + window, x, y, get_width (window), get_height (window)); +} + +void +ws_window_resize (window_t *window, + int w, + int h) +{ + ws_window_move_resize ( + window, window->x, window->y, w, h); +} + +void +ws_window_copy_area (window_t *window, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) +{ + pixman_image_t *tmp = + pixman_image_create_bits (PIXMAN_a8r8g8b8, width, height, NULL, -1); + + pixman_image_composite32 (PIXMAN_OP_SRC, + window->backing_store, NULL, tmp, + src_x, src_y, 0, 0, 0, 0, width, height); + pixman_image_composite32 (PIXMAN_OP_SRC, + tmp, NULL, window->backing_store, + 0, 0, 0, 0, dst_x, dst_y, width, height); +} + +void +ws_window_copy_from_image (window_t *window, + pixman_image_t *image, + int image_x, + int image_y, + int win_x, + int win_y, + int width, + int height) +{ + /* copy from image to backing */ + pixman_image_composite32 (PIXMAN_OP_SRC, + window->backing_store, NULL, image, + win_x, win_y, 0, 0, image_x, image_y, + width, height); +} + +void +ws_window_copy_to_image (window_t *window, + pixman_image_t *image, + int image_x, + int image_y, + int win_x, + int win_y, + int width, + int height) +{ + /* copy from backing to image */ + pixman_image_composite32 (PIXMAN_OP_SRC, + image, NULL, window->backing_store, + image_x, image_y, 0, 0, win_x, win_y, + width, height); +} + +void +ws_window_finish (window_t **windows, + int n_windows) +{ + +} @@ -1,6 +1,14 @@ #include <stdio.h> #include <pixman.h> +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + typedef struct ws_t ws_t; typedef struct drawable_t drawable_t; typedef struct window_t window_t; |