summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--main.c1
-rw-r--r--window.c335
-rw-r--r--window.h8
4 files changed, 298 insertions, 48 deletions
diff --git a/Makefile b/Makefile
index e2136df..837ff55 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/main.c b/main.c
index 60dd1e4..4662ae3 100644
--- a/main.c
+++ b/main.c
@@ -4,4 +4,5 @@ int
main ()
{
printf ("Hello world\n");
+ return 0;
}
diff --git a/window.c b/window.c
index f4350b3..f130204 100644
--- a/window.c
+++ b/window.c
@@ -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)
+{
+
+}
diff --git a/window.h b/window.h
index 3def92e..98a96ce 100644
--- a/window.h
+++ b/window.h
@@ -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;