int main(int argc, char **argv) {
    uint32_t width = test_width - 2 * INSET_X;
    uint32_t height = test_height - 2 * INSET_Y;
    int snum;
    xcb_void_cookie_t check_cookie;
    xcb_window_t w;
    xcb_gcontext_t gc;
    xcb_pixmap_t pix;
    xcb_connection_t *c = xcb_connect(0, &snum);
    xcb_screen_t *s = xcb_aux_get_screen(c, snum);
    xcb_alloc_named_color_cookie_t bg_cookie =
	xcb_alloc_named_color(c, s->default_colormap,
			      strlen("white"), "white");
    xcb_alloc_named_color_cookie_t fg_cookie =
	xcb_alloc_named_color(c, s->default_colormap,
			      strlen("black"), "black");
    xcb_alloc_named_color_reply_t *bg_reply =
	xcb_alloc_named_color_reply(c, bg_cookie, 0);
    xcb_alloc_named_color_reply_t *fg_reply =
	xcb_alloc_named_color_reply(c, fg_cookie, 0);
    uint32_t fg, bg;
    xcb_image_t *image, *native_image, *subimage;
    uint32_t mask = 0;
    xcb_params_gc_t gcv;

    assert(bg_reply && fg_reply);
    bg = bg_reply->pixel;
    fg = fg_reply->pixel;
    free(bg_reply);
    free(fg_reply);
    w = make_window(c, s, bg, fg, width, height);
    gc = xcb_generate_id(c);
    check_cookie = xcb_create_gc_checked(c, gc, w, 0, 0);
    assert(!xcb_request_check(c, check_cookie));
    image = xcb_image_create_from_bitmap_data((uint8_t *)test_bits,
					      test_width, test_height);
    native_image = xcb_image_native(c, image, 1);
    assert(native_image);
    if (native_image != image)
	xcb_image_destroy(image);
    subimage = xcb_image_subimage(native_image, INSET_X, INSET_Y,
				  width, height,
				  0, 0, 0);
    assert(subimage);
    xcb_image_destroy(native_image);
    subimage->format = XCB_IMAGE_FORMAT_XY_BITMAP;
    pix = xcb_generate_id(c);
    xcb_create_pixmap(c, s->root_depth, pix, w,
		      subimage->width, subimage->height);
    gc = xcb_generate_id(c);
    XCB_AUX_ADD_PARAM(&mask, &gcv, foreground, fg);
    XCB_AUX_ADD_PARAM(&mask, &gcv, background, bg);
    xcb_aux_create_gc(c, gc, pix, mask, &gcv);
    xcb_image_put(c, pix, gc, subimage, 0, 0, 0);
    process_events(c, gc, w, pix, width, height);
    xcb_disconnect(c);
    return 1;
}
Beispiel #2
0
void
x_client_icon::update_default_icon(void)
{
  xcb_free_pixmap(m_c(), m_default_icon);
  m_default_icon = XCB_NONE;

  const uint32_t width = default_application_icon.width;
  const uint32_t height = default_application_icon.width;

  m_icon_geometry.first = width;
  m_icon_geometry.second = height;

  m_default_icon = xcb_generate_id(m_c());
  xcb_create_pixmap(
      m_c(), 32, m_default_icon, m_c.root_window(), width, height);

  xcb_image_t * image = xcb_image_create_native(
      m_c(), width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 32, NULL, 0, NULL);

  image->data = (uint8_t *)default_application_icon.pixel_data;;

  xcb_gcontext_t gc = xcb_generate_id(m_c());
  xcb_create_gc(m_c(), gc, m_default_icon, 0, NULL);

  xcb_image_put(m_c(), m_default_icon, gc, image, 0, 0, 0);

  xcb_image_destroy(image);
  xcb_free_gc(m_c(), gc);
}
Beispiel #3
0
void krad_x11_disable_capture(krad_x11_t *x11) {
  xcb_shm_detach (x11->connection, x11->shminfo.shmseg);
  xcb_image_destroy (x11->img);
  shmdt (x11->shminfo.shmaddr);
  shmctl (x11->shminfo.shmid, IPC_RMID, 0);
  x11->capture_enabled = 0;
}
void
xcwm_image_destroy(xcwm_image_t * image)
{

    xcb_image_destroy(image->image);
    free(image);
}
Beispiel #5
0
void QXcbShmImage::destroy()
{
    Q_XCB_CALL(xcb_shm_detach(xcb_connection(), m_shm_info.shmseg));
    xcb_image_destroy(m_xcb_image);
    shmdt(m_shm_info.shmaddr);
    shmctl(m_shm_info.shmid, IPC_RMID, 0);
    if (m_gc)
        Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
}
Beispiel #6
0
void
x_client_icon::update_net_wm_icon(void)
{
  xcb_free_pixmap(m_c(), m_net_wm_icon);
  m_net_wm_icon = XCB_NONE;

  xcb_generic_error_t * error;
  xcb_get_property_cookie_t c =
    xcb_ewmh_get_wm_icon(m_c.ewmh(), m_x_client.window());

  xcb_ewmh_get_wm_icon_reply_t wm_icon;
  std::memset(&wm_icon, 0, sizeof(xcb_ewmh_get_wm_icon_reply_t));
  xcb_ewmh_get_wm_icon_reply(m_c.ewmh(), c, &wm_icon, &error);

  if (error) {
    std::free(error);

  } else if (0 < xcb_ewmh_get_wm_icon_length(&wm_icon)) {

    uint32_t width = 0;
    uint32_t height = 0;
    uint32_t * data = NULL;

    xcb_ewmh_wm_icon_iterator_t iter = xcb_ewmh_get_wm_icon_iterator(&wm_icon);
    for (; iter.rem; xcb_ewmh_get_wm_icon_next(&iter)) {
      if (iter.width > width) {
        width = iter.width;
        height = iter.height;
        data = iter.data;
      }
    }

    m_icon_geometry.first = width;
    m_icon_geometry.second = height;

    m_net_wm_icon = xcb_generate_id(m_c());
    xcb_create_pixmap(
        m_c(), 32, m_net_wm_icon, m_c.root_window(), width, height);

    xcb_image_t * image = xcb_image_create_native(
        m_c(), width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 32, NULL, 0, NULL);

    image->data = (uint8_t *)data;

    alpha_transform(image->data, width, height);

    xcb_gcontext_t gc = xcb_generate_id(m_c());
    xcb_create_gc(m_c(), gc, m_net_wm_icon, 0, NULL);

    xcb_image_put(m_c(), m_net_wm_icon, gc, image, 0, 0, 0);

    xcb_image_destroy(image);
    xcb_free_gc(m_c(), gc);

    xcb_ewmh_get_wm_icon_reply_wipe(&wm_icon);
  }
}
Beispiel #7
0
void ZLEwlViewWidget::resize(int w, int h) {
	if(w == this->w && h == this->h)
		return;

	this->w = w;
	this->h = h;

	xcb_shm_detach(connection, shminfo.shmseg);
	shmdt(im->data);
	xcb_image_destroy(im);

	xcb_shm_query_version_reply_t *rep_shm;

	rep_shm = xcb_shm_query_version_reply (connection,
			xcb_shm_query_version (connection),
			NULL);
	if(rep_shm) {
		xcb_image_format_t format;
		int shmctl_status;

		if (rep_shm->shared_pixmaps &&
				(rep_shm->major_version > 1 || rep_shm->minor_version > 0))
			format = (xcb_image_format_t)rep_shm->pixmap_format;
		else
			format = (xcb_image_format_t)0;

		uint8_t depth = xcb_aux_get_depth (connection, screen);
		im = xcb_image_create_native (connection, w, h,
				format, depth, NULL, ~0, NULL);
		assert(im);

		shminfo.shmid = shmget (IPC_PRIVATE,
				im->stride*im->height,
				IPC_CREAT | 0777);
		assert(shminfo.shmid != -1);
		shminfo.shmaddr = (uint8_t*)shmat (shminfo.shmid, 0, 0);
		assert(shminfo.shmaddr);
		im->data = shminfo.shmaddr;

		shminfo.shmseg = xcb_generate_id (connection);
		xcb_shm_attach (connection, shminfo.shmseg,
				shminfo.shmid, 0);
		shmctl_status = shmctl(shminfo.shmid, IPC_RMID, 0);
		assert(shmctl_status != -1);
		free (rep_shm);
	}
}
Beispiel #8
0
void QXcbShmImage::destroy()
{
    const int segmentSize = m_xcb_image ? (m_xcb_image->stride * m_xcb_image->height) : 0;
    if (segmentSize && m_shm_info.shmaddr)
        Q_XCB_CALL(xcb_shm_detach(xcb_connection(), m_shm_info.shmseg));

    xcb_image_destroy(m_xcb_image);

    if (segmentSize) {
        if (m_shm_info.shmaddr) {
            shmdt(m_shm_info.shmaddr);
            shmctl(m_shm_info.shmid, IPC_RMID, 0);
        } else {
            free(m_xcb_image->data);
        }
    }

    if (m_gc)
        Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
}
Beispiel #9
0
internal void
hhxcb_resize_backbuffer(hhxcb_context *context, hhxcb_offscreen_buffer *buffer, int width, int height)
{
    // xcb_image owns the referenced data, so will clean it up without an explicit free()
    if (buffer->xcb_image)
    {
        xcb_image_destroy(buffer->xcb_image);
    }

    if (buffer->xcb_pixmap_id)
    {
        xcb_free_pixmap(context->connection, buffer->xcb_pixmap_id);
    }

    if (buffer->xcb_gcontext_id)
    {
        xcb_free_gc(context->connection, buffer->xcb_gcontext_id);
    }

    buffer->width = width;
    buffer->height = height;
    buffer->bytes_per_pixel = context->fmt->bits_per_pixel / 8;
    buffer->pitch = buffer->bytes_per_pixel * width;

    buffer->xcb_image = hhxcb_create_image(width, height, context->fmt,
            context->setup);
    buffer->memory = buffer->xcb_image->data;

    buffer->xcb_pixmap_id = xcb_generate_id(context->connection);
    xcb_create_pixmap(context->connection, context->fmt->depth,
            buffer->xcb_pixmap_id, context->window, width, height);

    buffer->xcb_gcontext_id = xcb_generate_id (context->connection);
    xcb_create_gc (context->connection, buffer->xcb_gcontext_id,
            buffer->xcb_pixmap_id, 0, 0);
}
Beispiel #10
0
xcb_image_t *
xcb_image_native (xcb_connection_t *  c,
		  xcb_image_t *       image,
		  int                 convert)
{
  xcb_image_t *        tmp_image = 0;
  const xcb_setup_t *  setup = xcb_get_setup(c);
  xcb_format_t *       fmt = 0;
  xcb_image_format_t   ef = effective_format(image->format, image->bpp);
  uint8_t              bpp = 1;

  if (image->depth > 1 || ef == XCB_IMAGE_FORMAT_Z_PIXMAP) {
      fmt = find_format_by_depth(setup, image->depth);
      /* XXX For now, we don't do depth conversions, even
	 for xy-pixmaps */
      if (!fmt)
	  return 0;
      bpp = fmt->bits_per_pixel;
  }
  switch (ef) {
  case XCB_IMAGE_FORMAT_XY_PIXMAP:
      if (setup->bitmap_format_scanline_unit != image->unit ||
	  setup->bitmap_format_scanline_pad != image->scanline_pad ||
	  setup->image_byte_order != image->byte_order ||
	  setup->bitmap_format_bit_order != image->bit_order ||
	  bpp != image->bpp) {
	  if (!convert)
	      return 0;
	  tmp_image =
	      xcb_image_create(image->width, image->height, image->format,
			       setup->bitmap_format_scanline_pad,
			       image->depth, bpp,
			       setup->bitmap_format_scanline_unit,
			       setup->image_byte_order,
			       setup->bitmap_format_bit_order,
			       0, 0, 0);
	  if (!tmp_image)
	      return 0;
      }
      break;
  case XCB_IMAGE_FORMAT_Z_PIXMAP:
      if (fmt->scanline_pad != image->scanline_pad ||
	  setup->image_byte_order != image->byte_order ||
	  bpp != image->bpp) {
	  if (!convert)
	      return 0;
	  tmp_image =
	      xcb_image_create(image->width, image->height, image->format,
			       fmt->scanline_pad,
			       image->depth, bpp, 0,
			       setup->image_byte_order,
			       XCB_IMAGE_ORDER_MSB_FIRST,
			       0, 0, 0);
	  if (!tmp_image)
	      return 0;
      }
      break;
  default:
      assert(0);
  }
  if (tmp_image) {
      if (!xcb_image_convert(image, tmp_image)) {
	  xcb_image_destroy(tmp_image);
	  return 0;
      }
      image = tmp_image;
  }
  return image;
}
Beispiel #11
0
void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &source)
{
    Q_XCB_NOOP(connection());
    if (m_gc_window != window) {
        if (m_gc)
            Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));

        m_gc = xcb_generate_id(xcb_connection());
        Q_XCB_CALL(xcb_create_gc(xcb_connection(), m_gc, window, 0, 0));

        m_gc_window = window;
    }

    Q_XCB_NOOP(connection());
    if (m_shm_info.shmaddr) {
        xcb_image_shm_put(xcb_connection(),
                          window,
                          m_gc,
                          m_xcb_image,
                          m_shm_info,
                          source.x(),
                          source.y(),
                          target.x(),
                          target.y(),
                          source.width(),
                          source.height(),
                          false);
    } else {
        // If we upload the whole image in a single chunk, the result might be
        // larger than the server's maximum request size and stuff breaks.
        // To work around that, we upload the image in chunks where each chunk
        // is small enough for a single request.
        int src_x = source.x();
        int src_y = source.y();
        int target_x = target.x();
        int target_y = target.y();
        int width = source.width();
        int height = source.height();

        // We must make sure that each request is not larger than max_req_size.
        // Each request takes req_size + m_xcb_image->stride * height bytes.
        uint32_t max_req_size = xcb_get_maximum_request_length(xcb_connection());
        uint32_t req_size = sizeof(xcb_put_image_request_t);
        int rows_per_put = (max_req_size - req_size) / m_xcb_image->stride;

        // This assert could trigger if a single row has more pixels than fit in
        // a single PutImage request. However, max_req_size is guaranteed to be
        // at least 16384 bytes. That should be enough for quite large images.
        Q_ASSERT(rows_per_put > 0);

        while (height > 0) {
            int rows = std::min(height, rows_per_put);

            xcb_image_t *subimage = xcb_image_subimage(m_xcb_image, src_x, src_y, width, rows,
                                                       0, 0, 0);
            xcb_image_put(xcb_connection(),
                          window,
                          m_gc,
                          subimage,
                          target_x,
                          target_y,
                          0);

            xcb_image_destroy(subimage);

            src_y += rows;
            target_y += rows;
            height -= rows;
        }
    }
    Q_XCB_NOOP(connection());

    m_dirty = m_dirty | source;

    xcb_flush(xcb_connection());
    Q_XCB_NOOP(connection());
}
Beispiel #12
0
void krad_x11_enable_capture (krad_x11_t *x11, uint32_t window_id) {

  xcb_get_geometry_reply_t *geo;
  xcb_query_tree_reply_t *tree;
  xcb_translate_coordinates_cookie_t translateCookie;
  xcb_translate_coordinates_reply_t *trans;

  geo = xcb_get_geometry_reply (x11->connection,
        xcb_get_geometry (x11->connection, window_id), NULL);
  if (geo == NULL) {
    window_id = 0;
  } else {
    tree = xcb_query_tree_reply (x11->connection,
                                 xcb_query_tree (x11->connection, window_id), NULL);
    if (tree == NULL) {
      window_id = 0;
      free (geo);
    } else {

      translateCookie = xcb_translate_coordinates (x11->connection,
                                                  window_id,
                                                  x11->screen->root,
                                                  geo->x, geo->y);

      trans = xcb_translate_coordinates_reply (x11->connection,
                                               translateCookie,
                                               NULL);    

      if (trans == NULL) {
        window_id = 0;
        free (tree);
        free (geo);
      } else {
        x11->width = geo->width;
        x11->height = geo->height;
        x11->x = trans->dst_x - geo->x;
        x11->y = trans->dst_y - geo->y;
        free (trans);
        free (tree);
        free (geo);
      }
    }
  }

  if (window_id == 0) {
    x11->width = x11->screen_width;
    x11->height = x11->screen_height;
    x11->window = x11->screen->root;
  }

  //printf ("capture width %d height %d x %d y %d\n",
  //       x11->width, x11->height, x11->x, x11->y);

  x11->img = xcb_image_create_native (x11->connection,
                                      x11->width, x11->height,
                                      XCB_IMAGE_FORMAT_Z_PIXMAP,
                                      x11->screen_bit_depth, 0, ~0, 0);
  if (!x11->img) {
    exit (15);
  }
  
  x11->stride = x11->img->stride;

  x11->shminfo.shmid = shmget (IPC_PRIVATE,
                               x11->img->stride * x11->img->height,
                               (IPC_CREAT | 0666));

  if (x11->shminfo.shmid == (uint32_t)-1) {
    xcb_image_destroy (x11->img);
    failfast ("shminfo fail");
  }

  x11->shminfo.shmaddr = shmat (x11->shminfo.shmid, 0, 0);
  x11->img->data = x11->shminfo.shmaddr;

  if (x11->img->data == (uint8_t *)-1) {
    xcb_image_destroy (x11->img);
    failfast ("xcb image fail");
  }

  x11->shminfo.shmseg = xcb_generate_id (x11->connection);
  xcb_shm_attach (x11->connection, x11->shminfo.shmseg, x11->shminfo.shmid, 0);
  x11->capture_enabled = 1;
}
Beispiel #13
0
void sni_cleanup_xcb_image(void *data) {
    xcb_image_destroy(static_cast<xcb_image_t*>(data));
}
Beispiel #14
0
int main(int arg, char **argv)
{
	srand(time(NULL));
	xcb_connection_t *connection = xcb_connect(NULL, NULL);

	xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;

	xcb_colormap_t colormap = screen->default_colormap;

	xcb_drawable_t window = xcb_generate_id(connection);
	uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
	uint32_t values[] = {screen->black_pixel, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS};
	xcb_create_window(connection,
			/*screen->root_depth,*/
			24,
			window,
			screen->root,
			0, 0,
			WIDTH, HEIGHT,
			1,
			XCB_WINDOW_CLASS_INPUT_OUTPUT,
			screen->root_visual,
			mask, values);

	xcb_pixmap_t pixmap = xcb_generate_id(connection);
	xcb_create_pixmap(connection,
			24,
			pixmap,
			window,
			WIDTH, HEIGHT);

	uint8_t *img = malloc(WIDTH * HEIGHT * 4);

	uint8_t *limg = img;
	/*for (int y = 0; y < HEIGHT; y++)*/
	/*for (int x = 0; x < WIDTH; x++) {*/
	/**(limg++) = 128;*/
	/**(limg++) = 128;*/
	/**(limg++) = 128;*/
	/*limg++;*/
	/*}*/
	perlin(img, WIDTH, HEIGHT);

	xcb_image_t *image = xcb_image_create(WIDTH, HEIGHT,
			XCB_IMAGE_FORMAT_Z_PIXMAP,
			8, 24, 32,
			0,
			/*xcb_get_setup(connection)->image_byte_order,*/
			XCB_IMAGE_ORDER_MSB_FIRST,
			XCB_IMAGE_ORDER_LSB_FIRST,
			img,
			WIDTH * HEIGHT * 4,
			img);

	xcb_gcontext_t gc = xcb_generate_id(connection);
	xcb_create_gc(connection,
			gc,
			pixmap,
			0, NULL);

	xcb_image_put(connection, pixmap, gc, image, 0, 0, 0);

	xif_write(image, "test.xif");

	xcb_map_window(connection, window);
	xcb_flush(connection);

	xcb_generic_event_t *event;
	xcb_expose_event_t *expose;
	while ((event = xcb_wait_for_event(connection))) {
		switch (event->response_type & ~0x80) {
			case XCB_EXPOSE:
					expose = (xcb_expose_event_t *)event;
					xcb_copy_area(connection,
							pixmap,
							window,
							gc,
							expose->x, expose->y,
							expose->x, expose->y,
							expose->width, expose->height);
					xcb_flush(connection);
					break;
			case XCB_BUTTON_PRESS:
					goto end;
					break;
			default:
					break;
		}
		free(event);
	}
end:

	xcb_free_pixmap(connection, pixmap);
	xcb_disconnect(connection);

	xcb_image_destroy(image);

	return 0;
}
Beispiel #15
0
void
x_client_icon::update_wm_hints_icon(void)
{
  xcb_free_pixmap(m_c(), m_wm_hints_icon);
  m_wm_hints_icon = XCB_NONE;

  xcb_generic_error_t * error;

  xcb_get_property_cookie_t c =
    xcb_icccm_get_wm_hints(m_c(), m_x_client.window());
  xcb_get_property_reply_t * r = xcb_get_property_reply(m_c(), c, &error);

  if (error) {
    std::free(error);

  } else {
    xcb_icccm_wm_hints_t wm_hints;
    xcb_icccm_get_wm_hints_from_reply(&wm_hints, r);

    if (wm_hints.flags & XCB_ICCCM_WM_HINT_ICON_PIXMAP) {
      unsigned int width, height;

      {
        Window root;
        int x, y;
        unsigned int border_width, depth;
        XGetGeometry(m_c.dpy(), wm_hints.icon_pixmap, &root,
            &x, &y, &width, &height, &border_width, &depth);
        m_icon_geometry.first = width;
        m_icon_geometry.second = height;
      }

      xcb_image_t * icon_rgb = xcb_image_get(m_c(), wm_hints.icon_pixmap,
          0, 0, width, height, 0xffffffff, XCB_IMAGE_FORMAT_XY_PIXMAP);

      xcb_image_t * icon_mask;
      if (wm_hints.flags & XCB_ICCCM_WM_HINT_ICON_MASK) {
        icon_mask = xcb_image_get(m_c(), wm_hints.icon_mask,
            0, 0, width, height, 0xffffffff, XCB_IMAGE_FORMAT_XY_PIXMAP);

      } else {
        icon_mask = xcb_image_create_native(
            m_c(), width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 32, NULL, 0, NULL);
        std::memset(icon_mask->data, 0xff,
                    width * height * (icon_mask->bpp / icon_mask->stride));
      }

      xcb_image_t * icon_rgba = xcb_image_create_native(
          m_c(), width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 32, NULL, 0, NULL);

      for (std::size_t x = 0; x < width; ++x) {
        for (std::size_t y = 0; y < height; ++y) {
          uint32_t rgba = 0;

          if (xcb_image_get_pixel(icon_mask, x, y)) {
            uint32_t rgb = xcb_image_get_pixel(icon_rgb, x, y);
            uint8_t * s = (uint8_t *)&rgb;
            uint8_t * d = (uint8_t *)&rgba;

            d[0] = s[0];
            d[1] = s[1];
            d[2] = s[2];
            d[3] = 0xff;
          }

          xcb_image_put_pixel(icon_rgba, x, y, rgba);
        }
      }

      m_wm_hints_icon = xcb_generate_id(m_c());
      xcb_create_pixmap(
          m_c(), 32, m_wm_hints_icon, m_c.root_window(), width, height);

      xcb_gcontext_t gc = xcb_generate_id(m_c());
      xcb_create_gc(m_c(), gc, m_wm_hints_icon, 0, NULL);

      xcb_image_put(m_c(), m_wm_hints_icon, gc, icon_rgba, 0, 0, 0);

      xcb_image_destroy(icon_rgb);
      xcb_image_destroy(icon_mask);
      xcb_image_destroy(icon_rgba);
      xcb_free_gc(m_c(), gc);
    }
  }

  if (r) std::free(r);
}
Beispiel #16
0
int main(int argc, char *argv[]) {
    struct spwd *sp = getspnam(getenv("USER"));
    if (!sp) {
        fprintf(stderr, "Get password failed\n");
        return EXIT_FAILURE;
    }
    char *password = sp->sp_pwdp;

    // Parse command line parameters.
    struct arguments arguments = {
        .radius = 16,
        .iterations = 2,
    };
    argp_parse(&argp, argc, argv, 0, NULL, &arguments);

    // Connect to X11.
    xcb_connection_t *conn = xcb_connect(NULL, NULL);
    const xcb_setup_t *setup = xcb_get_setup(conn);
    xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
    xcb_screen_t *screen = iter.data;

    // Initialize keyboard stuff.
    Keyboard keyboard = {
        .conn = conn,
    };
    init_keyboard(&keyboard);

    // Take a screenshot and blur it.
    xcb_image_t *screenshot = take_screenshot(conn, screen);
    blur_image(screenshot, arguments.radius, arguments.iterations);

    // Create window.
    xcb_window_t window = create_window(conn, screen, screenshot);

    if (!grab_inputs(conn, screen)) {
        fprintf(stderr, "Failed to grab keyboard and pointer.\n");
        exit(EXIT_FAILURE);
    }

    xcb_map_window(conn, window);

    // Original screenshot image is not needed anymore because it's copied to the X server as pixmap.
    xcb_image_destroy(screenshot);

    xcb_flush(conn);

    // XXX: Max password length?
    char input[256] = { '\0' };
    char *cursor = &input[0];

    running = true;
    xcb_generic_event_t *event;
    while (running && (event = xcb_wait_for_event(conn))) {
        switch (event->response_type & ~0x80) {
            case XCB_EXPOSE:
                break;
            case XCB_KEY_PRESS:
                if (handle_key_press(&keyboard, ((xcb_key_press_event_t *)event)->detail, input, &cursor)) {
                    if (strcmp(crypt(input, password), password) == 0) {
                        running = false;
                    } else {
                        input[0] = '\0';
                        cursor = &input[0];
                    }
                }
                break;
            default:
                if (event->response_type == keyboard.first_xkb_event) {
                    process_keyboard_event(&keyboard, event);
                }
                break;
        }
        free(event);
    }

    free_keyboard(&keyboard);

    xcb_unmap_window(conn, window);
    xcb_destroy_window(conn, window);
    xcb_disconnect(conn);

    return EXIT_SUCCESS;
}