hexagram/src/window.c

214 lines
6.2 KiB
C
Raw Normal View History

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xdbe.h>
#include <cairo-xlib.h>
#include <hexagram/window.h>
struct _hexagram_window {
Display *display;
int screen,
width, height;
Window root,
win;
Pixmap shape,
bg;
GC gc;
XGCValues gc_values;
XdbeBackBuffer buf;
XdbeSwapInfo swapinfo;
cairo_surface_t *surface_bg,
*surface_fg;
};
hexagram_window *hexagram_window_new_x11(const char *display,
int width,
int height) {
hexagram_window *window;
int major, minor;
if ((window = malloc(sizeof(*window))) == NULL) {
goto error_malloc_window;
}
window->width = width;
window->height = height;
/*
* Connect to the X display
*/
if ((window->display = XOpenDisplay(display)) == NULL) {
goto error_x_open_display;
}
window->screen = DefaultScreen(window->display);
window->root = DefaultRootWindow(window->display);
/*
* Create the X window
*/
if ((window->win = XCreateSimpleWindow(window->display,
window->root,
0, 0,
width, height, 0, 0, 0)) == 0) {
goto error_x_create_simple_window;
}
/*
* Create a back buffer, if the Xdbe extension is available. If not, render
* directly to the window, at the cost of flickering.
*/
if (XdbeQueryExtension(window->display, &major, &minor)) {
if ((window->buf = XdbeAllocateBackBufferName(window->display,
window->win,
XdbeBackground)) == 0) {
goto error_x_dbe_allocate_back_buffer_name;
}
window->swapinfo.swap_window = window->win;
window->swapinfo.swap_action = XdbeBackground;
} else {
window->buf = window->win;
}
if ((window->bg = XCreatePixmap(window->display,
window->win, width, height, 24)) == 0) {
goto error_x_create_pixmap_bg;
}
window->gc_values.foreground = 0x000000;
window->gc_values.background = 0xffffff;
window->gc_values.graphics_exposures = 0;
if ((window->gc = XCreateGC(window->display,
window->win,
HEXAGRAM_WINDOW_GC_FLAGS,
&window->gc_values)) == 0) {
goto error_x_create_gc;
}
if ((window->surface_bg = cairo_xlib_surface_create(window->display,
window->bg,
DefaultVisual(window->display,
window->screen),
width,
height)) == NULL) {
goto error_cairo_xlib_surface_create_bg;
}
cairo_xlib_surface_set_size(window->surface_bg,
width, height);
if ((window->surface_fg = cairo_xlib_surface_create(window->display,
window->buf,
DefaultVisual(window->display,
window->screen),
width,
height)) == NULL) {
goto error_cairo_xlib_surface_create_fg;
}
cairo_xlib_surface_set_size(window->surface_fg,
width,
height);
return window;
error_cairo_xlib_surface_create_fg:
cairo_surface_destroy(window->surface_bg);
error_cairo_xlib_surface_create_bg:
(void)XFreeGC(window->display, window->gc);
error_x_create_gc:
(void)XFreePixmap(window->display, window->bg);
error_x_create_pixmap_bg:
if (window->buf != window->win) {
(void)XdbeDeallocateBackBufferName(window->display, window->buf);
}
error_x_dbe_allocate_back_buffer_name:
(void)XDestroyWindow(window->display, window->win);
error_x_create_simple_window:
(void)XCloseDisplay(window->display);
error_x_open_display:
free(window);
error_malloc_window:
return NULL;
}
void hexagram_window_destroy(hexagram_window *window) {
cairo_surface_destroy(window->surface_fg);
cairo_surface_destroy(window->surface_bg);
(void)XFreeGC(window->display, window->gc);
(void)XFreePixmap(window->display, window->bg);
if (window->buf != window->win) {
(void)XdbeDeallocateBackBufferName(window->display, window->buf);
}
(void)XUnmapWindow(window->display, window->win);
(void)XDestroyWindow(window->display, window->win);
}
2019-05-28 00:58:18 -05:00
Display *hexagram_window_display(hexagram_window *window) {
return window->display;
}
2019-05-28 00:32:22 -05:00
int hexagram_window_display_fd(hexagram_window *window) {
return ConnectionNumber(window->display);
}
int hexagram_window_show(hexagram_window *window) {
if (XSelectInput(window->display, window->win,
ExposureMask | ButtonPressMask | KeyPressMask) == 0) {
goto error_x;
}
if (XMapWindow(window->display, window->win) == 0) {
goto error_x;
}
return 0;
error_x:
return -1;
}
2019-05-28 00:36:07 -05:00
int hexagram_window_refresh_bg(hexagram_window *window) {
return XCopyArea(window->display,
window->bg,
window->buf,
window->gc,
0, 0,
window->width, window->height,
0, 0) == 0? -1: 1;
}
int hexagram_window_swap_buffer(hexagram_window *window) {
return XdbeSwapBuffers(window->display, &window->swapinfo, 1) == 0? -1: 1;
}
cairo_t *hexagram_window_create_bg_context(hexagram_window *window) {
return cairo_create(window->surface_bg);
}
cairo_t *hexagram_window_create_fg_context(hexagram_window *window) {
return cairo_create(window->surface_fg);
}