/*
* Copyright © 2015 Uli Schlachter <psychon@znc.in>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*
* find_visual() is adapted from draw_find_visual() from the Awesome
* window manager (http://awesome.naquadah.org).
*/
#include <xcb/xcb.h>
#include <cairo-xcb.h>
#include <stdio.h>
#include <stdlib.h>
static xcb_visualtype_t *find_visual(xcb_connection_t *c, xcb_visualid_t visual)
{
xcb_screen_iterator_t screen_iter = xcb_setup_roots_iterator(xcb_get_setup(c));
for (; screen_iter.rem; xcb_screen_next(&screen_iter)) {
xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(screen_iter.data);
for (; depth_iter.rem; xcb_depth_next(&depth_iter)) {
xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
for (; visual_iter.rem; xcb_visualtype_next(&visual_iter))
if (visual == visual_iter.data->visual_id)
return visual_iter.data;
}
}
return NULL;
}
int main()
{
xcb_connection_t *c;
xcb_screen_t *screen;
xcb_window_t window;
uint32_t mask[2];
xcb_visualtype_t *visual;
xcb_generic_event_t *event;
cairo_surface_t *surface;
cairo_t *cr;
c = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(c)) {
fprintf(stderr, "Could not connect to X11 server");
return 1;
}
mask[0] = 1;
mask[1] = XCB_EVENT_MASK_EXPOSURE;
screen = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
window = xcb_generate_id(c);
xcb_create_window(c, XCB_COPY_FROM_PARENT, window, screen->root,
20, 20, 150, 150, 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
mask);
xcb_map_window(c, window);
visual = find_visual(c, screen->root_visual);
if (visual == NULL) {
fprintf(stderr, "Some weird internal error...?!");
xcb_disconnect(c);
return 1;
}
surface = cairo_xcb_surface_create(c, window, visual, 150, 150);
cr = cairo_create(surface);
xcb_flush(c);
while ((event = xcb_wait_for_event(c))) {
switch (event->response_type & ~0x80) {
case XCB_EXPOSE:
/* Avoid extra redraws by checking if this is
* the last expose event in the sequence
*/
if (((xcb_expose_event_t *) event)->count != 0)
break;
cairo_set_source_rgb(cr, 0, 1, 0);
cairo_paint(cr);
cairo_set_source_rgb(cr, 1, 0, 0);
cairo_move_to(cr, 0, 0);
cairo_line_to(cr, 150, 0);
cairo_line_to(cr, 150, 150);
cairo_close_path(cr);
cairo_fill(cr);
cairo_set_source_rgb(cr, 0, 0, 1);
cairo_set_line_width(cr, 20);
cairo_move_to(cr, 0, 150);
cairo_line_to(cr, 150, 0);
cairo_stroke(cr);
cairo_surface_flush(surface);
break;
}
free(event);
xcb_flush(c);
}
cairo_surface_finish(surface);
cairo_surface_destroy(surface);
xcb_disconnect(c);
return 0;
}