예제 #1
0
int
randr_init(randr_state_t *state)
{
	/* Initialize state. */
	state->screen_num = -1;
	state->crtc_num = NULL;

	state->crtc_num_count = 0;
	state->crtc_count = 0;
	state->crtcs = NULL;

	state->preserve = 0;

	xcb_generic_error_t *error;

	/* Open X server connection */
	state->conn = xcb_connect(NULL, &state->preferred_screen);

	/* Query RandR version */
	xcb_randr_query_version_cookie_t ver_cookie =
		xcb_randr_query_version(state->conn, RANDR_VERSION_MAJOR,
					RANDR_VERSION_MINOR);
	xcb_randr_query_version_reply_t *ver_reply =
		xcb_randr_query_version_reply(state->conn, ver_cookie, &error);

	/* TODO What does it mean when both error and ver_reply is NULL?
	   Apparently, we have to check both to avoid seg faults. */
	if (error || ver_reply == NULL) {
		int ec = (error != 0) ? error->error_code : -1;
		fprintf(stderr, _("`%s' returned error %d\n"),
			"RANDR Query Version", ec);
		xcb_disconnect(state->conn);
		return -1;
	}

	if (ver_reply->major_version != RANDR_VERSION_MAJOR ||
	    ver_reply->minor_version < RANDR_VERSION_MINOR) {
		fprintf(stderr, _("Unsupported RANDR version (%u.%u)\n"),
			ver_reply->major_version, ver_reply->minor_version);
		free(ver_reply);
		xcb_disconnect(state->conn);
		return -1;
	}

	free(ver_reply);

	return 0;
}
예제 #2
0
void
_ecore_x_randr_init_finalize(void)
{
#ifdef ECORE_XCB_RANDR
   xcb_randr_query_version_reply_t *reply;

   reply = xcb_randr_query_version_reply(_ecore_xcb_conn,
                                         _ecore_xcb_randr_init_cookie, NULL);

   if (reply)
     {
        if ((reply->major_version >= 1) &&
            (reply->minor_version >= 1))
          _randr_available = 1;
        free(reply);
     }
#endif /* ECORE_XCB_RANDR */
}
예제 #3
0
bool ScreenManager::configureRandR(xcb_connection_t *conn)
{
    const xcb_query_extension_reply_t *ext = xcb_get_extension_data(conn, &xcb_randr_id);
    if (!ext->present) {
        return false;
    }
    xcb_randr_query_version_reply_t *ver =
        xcb_randr_query_version_reply(
            conn, xcb_randr_query_version(conn, 1, 1), 0);
    if (!ver) {
        return false;
    }
    _randrBase = ext->first_event;
    xcb_randr_select_input(conn, _rootWindow,
        XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
       XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
       XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
       XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY);
    xcb_flush(conn);
    return true;
}
예제 #4
0
int x11_find_all_outputs(char*** out_outputs, size_t* out_outputs_count)
{
  xcb_generic_error_t* error = NULL;
  xcb_randr_query_version_cookie_t version_cookie;
  xcb_randr_query_version_reply_t* version_reply = NULL;
  const xcb_setup_t* setup;
  xcb_screen_iterator_t iter;
  xcb_screen_t* screen;
  xcb_randr_get_screen_resources_current_cookie_t screen_cookie;
  xcb_randr_get_output_info_cookie_t output_cookie;
  xcb_randr_output_t* outputs = NULL;
  
  *out_outputs_count = 0;
  *out_outputs = NULL;
  
  connection = xcb_connect(NULL, NULL);
  if (connection == NULL)
    goto pfail;
  
  version_cookie = xcb_randr_query_version(connection, RANDR_VERSION_MAJOR, RANDR_VERSION_MINOR);
  version_reply = xcb_randr_query_version_reply(connection, version_cookie, &error);
  
  if ((error != NULL) || (version_reply == NULL))
    {
      if ((error == NULL) && (version_reply == NULL))
	connection = NULL;
      goto pfail;
    }
  
  if ((version_reply->major_version != RANDR_VERSION_MAJOR) ||
      (version_reply->minor_version < RANDR_VERSION_MINOR))
    {
      fprintf(stderr, "%s: wrong RandR version\n", argv0);
      goto fail;
    }
  
  free(version_reply), version_reply = NULL;
  
  setup = xcb_get_setup(connection);
  if (setup == NULL)
    goto pfail;
  
  iter = xcb_setup_roots_iterator(setup);
  
  for (; iter.rem > 0; xcb_screen_next(&iter))
    {
      size_t i, n;
      
      screen = iter.data;
      if (screen == NULL)
	abort();
      
      screen_cookie = xcb_randr_get_screen_resources_current(connection, screen->root);
      screen_reply = xcb_randr_get_screen_resources_current_reply(connection, screen_cookie, &error);
      if (error != NULL)
	goto pfail;
      
      outputs = xcb_randr_get_screen_resources_current_outputs(screen_reply);
      if (outputs == NULL)
	goto pfail;
      
      for (i = 0, n = (size_t)(screen_reply->num_outputs); i < n; i++)
	{
	  uint8_t* name;
	  uint16_t length;
	  char* namez;
	  char** old;
	  
	  output_cookie = xcb_randr_get_output_info(connection, outputs[i], screen_reply->config_timestamp);
	  output_reply = xcb_randr_get_output_info_reply(connection, output_cookie, &error);
	  if (error != NULL)
	    goto pfail;
	  
	  if (output_reply->connection != XCB_RANDR_CONNECTION_CONNECTED)
	    goto next_output;
	  
	  name = xcb_randr_get_output_info_name(output_reply);
	  length = output_reply->name_len;
	  if (name == NULL)
	    goto pfail;
	  
	  *out_outputs = realloc(old = *out_outputs, (*out_outputs_count + 1) * sizeof(char*));
	  if (*out_outputs == NULL)
	    {
	      *out_outputs = old;
	      goto pfail;
	    }
	  
	  namez = malloc(((size_t)length + 1) * sizeof(char));
	  if (namez == NULL)
	    goto pfail;
	  namez[length] = '\0';
	  while (length--)
	    namez[length] = (char)(name[length]);
	  
	  (*out_outputs)[(*out_outputs_count)++] = namez;
	  
	next_output:
	  free(output_reply), output_reply = NULL;
	}
      
      free(screen_reply), screen_reply = NULL;
    }
  
  xcb_disconnect(connection);
  return 0;
  
 pfail:
  perror(argv0);
 fail:
  free(version_reply);
  free(screen_reply);
  free(output_reply);
  if (connection != NULL)
    xcb_disconnect(connection);
  return -1;
}
예제 #5
0
int x11_initialise_animation(int coarse_fine, double duration, double degrees, const char* output)
{
  xcb_generic_error_t* error = NULL;
  xcb_randr_query_version_cookie_t version_cookie;
  xcb_randr_query_version_reply_t* version_reply = NULL;
  const xcb_setup_t* setup;
  xcb_screen_iterator_t iter;
  xcb_screen_t* screen;
  xcb_randr_get_screen_resources_current_cookie_t screen_cookie;
  xcb_randr_get_output_info_cookie_t output_cookie;
  xcb_randr_crtc_t* crtcs = NULL;
  xcb_randr_output_t* outputs = NULL;
  int found_output = 0;
  size_t i, n;
  xcb_randr_get_crtc_transform_cookie_t transform_cookie;
  xcb_randr_get_crtc_transform_reply_t* transform_reply = NULL;
  
  fine = coarse_fine ? (coarse_fine == 1) : 1;
  
  connection = NULL;
  screen_reply = NULL;
  output_reply = NULL;
  
  connection = xcb_connect(NULL, NULL);
  if (connection == NULL)
    goto pfail;
  
  version_cookie = xcb_randr_query_version(connection, RANDR_VERSION_MAJOR, RANDR_VERSION_MINOR);
  version_reply = xcb_randr_query_version_reply(connection, version_cookie, &error);
  
  if ((error != NULL) || (version_reply == NULL))
    {
      if ((error == NULL) && (version_reply == NULL))
	connection = NULL;
      goto pfail;
    }
  
  if ((version_reply->major_version != RANDR_VERSION_MAJOR) ||
      (version_reply->minor_version < RANDR_VERSION_MINOR))
    {
      fprintf(stderr, "%s: wrong RandR version\n", argv0);
      goto fail;
    }
  
  free(version_reply), version_reply = NULL;
  
  setup = xcb_get_setup(connection);
  if (setup == NULL)
    goto pfail;
  
  iter = xcb_setup_roots_iterator(setup);
  
  for (; (iter.rem > 0) && !found_output; xcb_screen_next(&iter))
    {
      screen = iter.data;
      if (screen == NULL)
	abort();
      
      screen_cookie = xcb_randr_get_screen_resources_current(connection, screen->root);
      screen_reply = xcb_randr_get_screen_resources_current_reply(connection, screen_cookie, &error);
      if (error != NULL)
	goto pfail;
      
      crtcs = xcb_randr_get_screen_resources_current_crtcs(screen_reply);
      outputs = xcb_randr_get_screen_resources_current_outputs(screen_reply);
      if (outputs == NULL)
	goto pfail;
      
      for (i = 0, n = (size_t)(screen_reply->num_outputs); (i < n) && !found_output; i++)
	{
	  uint8_t* name;
	  uint16_t length;
	  char* namez = NULL;
	  uint16_t j;
	  
	  output_cookie = xcb_randr_get_output_info(connection, outputs[i], screen_reply->config_timestamp);
	  output_reply = xcb_randr_get_output_info_reply(connection, output_cookie, &error);
	  if (error != NULL)
	    goto pfail;
	  
	  if (output_reply->connection != XCB_RANDR_CONNECTION_CONNECTED)
	    goto next_output;
	  
	  name = xcb_randr_get_output_info_name(output_reply);
	  length = output_reply->name_len;
	  if (name == NULL)
	    goto pfail;
	  
	  namez = malloc(((size_t)length + 1) * sizeof(char));
	  if (namez == NULL)
	    goto pfail;
	  namez[length] = '\0';
	  while (length--)
	    namez[length] = (char)(name[length]);
	  
	  if (strcmp(namez, output))
	      goto next_output;
	  found_output = 1;
	  free(namez), namez = NULL;
	  
	  for (j = 0; j < screen_reply->num_crtcs; j++)
	    if (crtcs[j] == output_reply->crtc)
	      break;
	  if (j == screen_reply->num_crtcs)
	    {
	      fprintf(stderr, "%s: could not find CRTC associated with output: %s\n", argv0, output);
	      goto fail;
	    }
	  crtc = crtcs[j];
	  
	  goto exit_search_loop;
	  
	next_output:
	  free(namez);
	  free(output_reply), output_reply = NULL;
	}
      
      free(screen_reply), screen_reply = NULL;
    }
 exit_search_loop:
  
  if (!found_output)
    {
      fprintf(stderr, "%s: could not find output: %s\n", argv0, output);
      goto fail;
    }
  
  transform_cookie = xcb_randr_get_crtc_transform(connection, crtc);
  transform_reply = xcb_randr_get_crtc_transform_reply(connection, transform_cookie, &error);
  if (error != NULL)
    goto pfail;
  
  original_transform = transform_reply->pending_transform;
  free(transform_reply);
  
  return 0;
  
 pfail:
  perror(argv0);
 fail:
  free(version_reply);
  free(screen_reply);
  free(output_reply);
  free(transform_reply);
  if (connection != NULL)
    xcb_disconnect(connection);
  return -1;
  
  return (void)duration, (void)degrees, -1; /* TODO */
}
예제 #6
0
파일: panoramix.c 프로젝트: Mettbrot/vlc
/* Get the number of outputs */
static unsigned CountMonitors( vlc_object_t *obj )
{
    char *psz_display = var_InheritString( obj, "x11-display" );
    int snum;
    xcb_connection_t *conn = xcb_connect( psz_display, &snum );
    free( psz_display );
    if( xcb_connection_has_error( conn ) )
        return 0;

    const xcb_setup_t *setup = xcb_get_setup( conn );
    xcb_screen_t *scr = NULL;
    for( xcb_screen_iterator_t i = xcb_setup_roots_iterator( setup );
         i.rem > 0; xcb_screen_next( &i ) )
    {
         if( snum == 0 )
         {
             scr = i.data;
             break;
         }
         snum--;
    }

    unsigned n = 0;
    if( scr == NULL )
        goto error;

    xcb_randr_query_version_reply_t *v =
        xcb_randr_query_version_reply( conn,
            xcb_randr_query_version( conn, 1, 2 ), NULL );
    if( v == NULL )
        goto error;
    msg_Dbg( obj, "using X RandR extension v%"PRIu32".%"PRIu32,
             v->major_version, v->minor_version );
    free( v );

    xcb_randr_get_screen_resources_reply_t *r =
        xcb_randr_get_screen_resources_reply( conn,
            xcb_randr_get_screen_resources( conn, scr->root ), NULL );
    if( r == NULL )
        goto error;

    const xcb_randr_output_t *outputs =
        xcb_randr_get_screen_resources_outputs( r );
    for( unsigned i = 0; i < r->num_outputs; i++ )
    {
        xcb_randr_get_output_info_reply_t *output =
            xcb_randr_get_output_info_reply( conn,
                xcb_randr_get_output_info( conn, outputs[i], 0 ), NULL );
        if( output == NULL )
            continue;
        /* FIXME: do not count cloned outputs multiple times */
        /* XXX: what to do with UNKNOWN state connections? */
        n += output->connection == XCB_RANDR_CONNECTION_CONNECTED;
        free( output );
    }
    free( r );
    msg_Dbg( obj, "X randr has %u outputs", n );

error:
    xcb_disconnect( conn );
    return n;
}
예제 #7
0
std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
{
    std::vector<VideoMode> modes;

    // Open a connection with the X server
    xcb_connection_t* connection = OpenConnection();

    // Retrieve the default screen
    xcb_screen_t* screen = XCBDefaultScreen(connection);

    ScopedXcbPtr<xcb_generic_error_t> error(NULL);

    const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id);

    if (!randrExt || !randrExt->present)
    {
        // Randr extension is not supported: we cannot get the video modes
        err() << "Failed to use the RandR extension while trying to get the supported video modes" << std::endl;

        // Close the connection with the X server
        CloseConnection(connection);

        return modes;
    }

    // Load RandR and check its version
    ScopedXcbPtr<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply(
        connection,
        xcb_randr_query_version(
            connection,
            1,
            1
        ),
        &error
    ));

    if (error)
    {
        err() << "Failed to load the RandR extension while trying to get the supported video modes" << std::endl;

        // Close the connection with the X server
        CloseConnection(connection);

        return modes;
    }

    // Get the current configuration
    ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply(
        connection,
        xcb_randr_get_screen_info(
            connection,
            screen->root
        ),
        &error
    ));

    if (error)
    {
        // Failed to get the screen configuration
        err() << "Failed to retrieve the screen configuration while trying to get the supported video modes" << std::endl;

        // Close the connection with the X server
        CloseConnection(connection);

        return modes;
    }

    // Get the available screen sizes
    xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
    if (sizes && (config->nSizes > 0))
    {
        // Get the list of supported depths
        xcb_depth_iterator_t iter = xcb_screen_allowed_depths_iterator(screen);
        // Combine depths and sizes to fill the array of supported modes
        for (; iter.rem; xcb_depth_next(&iter))
        {
            for (int j = 0; j < config->nSizes; ++j)
            {
                // Convert to VideoMode
                VideoMode mode(sizes[j].width, sizes[j].height, iter.data->depth);

                if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
                    config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
                    std::swap(mode.width, mode.height);

                // Add it only if it is not already in the array
                if (std::find(modes.begin(), modes.end(), mode) == modes.end())
                    modes.push_back(mode);
            }
        }
    }

    // Close the connection with the X server
    CloseConnection(connection);

    return modes;
}
예제 #8
0
VideoMode VideoModeImpl::getDesktopMode()
{
    VideoMode desktopMode;

    // Open a connection with the X server
    xcb_connection_t* connection = OpenConnection();

    // Retrieve the default screen
    xcb_screen_t* screen = XCBDefaultScreen(connection);

    ScopedXcbPtr<xcb_generic_error_t> error(NULL);

    // Check if the RandR extension is present
    const xcb_query_extension_reply_t* randrExt = xcb_get_extension_data(connection, &xcb_randr_id);

    if (!randrExt || !randrExt->present)
    {
        // Randr extension is not supported: we cannot get the video modes
        err() << "Failed to use the RandR extension while trying to get the desktop video mode" << std::endl;

        // Close the connection with the X server
        CloseConnection(connection);

        return desktopMode;
    }

    // Load RandR and check its version
    ScopedXcbPtr<xcb_randr_query_version_reply_t> randrVersion(xcb_randr_query_version_reply(
        connection,
        xcb_randr_query_version(
            connection,
            1,
            1
        ),
        &error
    ));

    if (error)
    {
        err() << "Failed to load the RandR extension while trying to get the desktop video mode" << std::endl;

        // Close the connection with the X server
        CloseConnection(connection);

        return desktopMode;
    }

    // Get the current configuration
    ScopedXcbPtr<xcb_randr_get_screen_info_reply_t> config(xcb_randr_get_screen_info_reply(
        connection,
        xcb_randr_get_screen_info(
            connection,
            screen->root
        ),
        &error
    ));

    if (error)
    {
        // Failed to get the screen configuration
        err() << "Failed to retrieve the screen configuration while trying to get the desktop video mode" << std::endl;

        // Close the connection with the X server
        CloseConnection(connection);

        return desktopMode;
    }

    // Get the current video mode
    xcb_randr_mode_t currentMode = config->sizeID;

    // Get the available screen sizes
    int nbSizes = xcb_randr_get_screen_info_sizes_length(config.get());
    xcb_randr_screen_size_t* sizes = xcb_randr_get_screen_info_sizes(config.get());
    if (sizes && (nbSizes > 0))
    {
        desktopMode = VideoMode(sizes[currentMode].width, sizes[currentMode].height, screen->root_depth);

        if (config->rotation == XCB_RANDR_ROTATION_ROTATE_90 ||
            config->rotation == XCB_RANDR_ROTATION_ROTATE_270)
            std::swap(desktopMode.width, desktopMode.height);
    }
    else
    {
        err() << "Failed to retrieve any screen sizes while trying to get the desktop video mode" << std::endl;
    }

    // Close the connection with the X server
    CloseConnection(connection);

    return desktopMode;
}
예제 #9
0
int main() {

	uint8_t xrandr;
	struct pollfd poll_fd;
	fd_set set;
	int fd;
	int retval;
	int timeout;

	setlocale (LC_ALL, "");
//	bindtextdomain (PACKAGE, LOCALEDIR);
//	textdomain (PACKAGE);

	printf("TabletWM version 0.25\n");

	init_tabletwm();

	uint32_t v[]={XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY|XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT};
	xcb_change_window_attributes(conn,scr->root,XCB_CW_EVENT_MASK,v);
	support_capture_key(XCB_MOD_MASK_CONTROL,23); // Ctrl+TAB
	support_capture_key(XCB_MOD_MASK_1,23); // Alt+TAB
	support_capture_key(XCB_MOD_MASK_1,70); // Alt+F4
	support_capture_key(XCB_MOD_MASK_ANY,135); // MENU key (between the right WINDOWS key and the right Ctrl key)
	support_capture_key(XCB_MOD_MASK_ANY,124); // POWER key
	//xcb_grab_key(conn,0,scr->root,XCB_MOD_MASK_ANY,XCB_GRAB_ANY,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC);

#ifdef DEBUG
	support_capture_key(XCB_MOD_MASK_1,71); // Alt+F5 for VALGRIND tests
#endif

	/* detect changes in screen size with xrandr */
	xcb_randr_query_version_reply_t *r=xcb_randr_query_version_reply(conn,xcb_randr_query_version(conn,1,1),0);
	if (r) {
		xcb_randr_select_input(conn,scr->root,XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);

		const xcb_query_extension_reply_t *r2=xcb_get_extension_data(conn,&xcb_randr_id);
		xrandr=r2->first_event;
	}
	free(r);

	xcb_flush(conn);
	xcb_generic_event_t *e;
	
	keep_running=1;
	
	support_launch_manager();
	fd = xcb_get_file_descriptor(conn);
	while(keep_running) {
		poll_fd.fd=fd;
		poll_fd.events=POLLIN;
		poll_fd.revents=0;
		if (key_win.possition!=0) {
			retval = poll(&poll_fd,1,2000); // refresh every two seconds if the bar is visible
		} else {
			retval = poll(&poll_fd,1,-1); // just wait for an event when the bar is not visible
		}
		if (retval==0) {
			menuwin_expose(NULL); // each 10 seconds of inactivity, refresh the user bar to keep the clock and indicators updated
			continue;
		}
		while(e=xcb_poll_for_event(conn)) {
			uint8_t r=e->response_type&~0x80;
		
			if (r>=xrandr) {
				printf("XRandR\n");
				switch(r-xrandr) {
					case(XCB_RANDR_SCREEN_CHANGE_NOTIFY):
						action_xrandr_screen_change_notify(e);
					break;
					default:
						printf("XRandR unknown: %d\n",r-xrandr);
					break;
				}
			} else {
				switch(r) {
					case(XCB_KEY_RELEASE):
						action_key(e);
					break;
					case (XCB_CREATE_NOTIFY):
						//xcb_create_notify_event_t *ee=(xcb_create_notify_event_t *)e;
					break;
					case(XCB_UNMAP_NOTIFY):
						action_unmap_notify(e);
					break;
					case(XCB_DESTROY_NOTIFY):
						action_destroy_notify(e);
					break;
					case(XCB_MAP_REQUEST):
						action_map_request(e);
					break;
					case(XCB_MAP_NOTIFY):
					case(XCB_MAPPING_NOTIFY):
						support_send_dock_up(NULL,NULL); // ensure that the dock is always on top
					break;
					case(XCB_CONFIGURE_NOTIFY):
						action_configure_notify(e);
					break;
					case(XCB_CONFIGURE_REQUEST):
						action_configure_request(e);
					break;
					case(XCB_CIRCULATE_REQUEST):
						//xcb_circulate_request_event_t *ee=(xcb_circulate_request_event_t *)e;
					break;
					case(XCB_EXPOSE):
						action_expose(e);
					break;
					case(XCB_ENTER_NOTIFY):
						action_mouse_enter(e);
					break;
					case(XCB_LEAVE_NOTIFY):
						action_mouse_leave(e);
					break;
					case(XCB_BUTTON_RELEASE):
						action_mouse_click(e);
					break;
					case(0): {
						xcb_generic_error_t *ee=(xcb_generic_error_t *)e;
						printf("error event type %d\n",ee->error_code);
					}
					break;
					default:
						printf("unhandled event type %d\n",e->response_type);
					break;
				}
			}
			free(e);
		}
	}
	destroy_tabletwm();
	xcb_disconnect(conn);
	return(0);
}
예제 #10
0
파일: display.c 프로젝트: mitrandir77/unagi
/** Get the  replies of the QueryVersion requests  previously sent and
 * check if their version actually matched the versions needed
 *
 * \see display_init_extensions
 */
void
display_init_extensions_finalise(void)
{
  assert(_init_extensions_cookies.composite.sequence);

  xcb_composite_query_version_reply_t *composite_version_reply =
    xcb_composite_query_version_reply(globalconf.connection,
				      _init_extensions_cookies.composite,
				      NULL);

  /* Need NameWindowPixmap support introduced in version >= 0.2 */
  if(!composite_version_reply || composite_version_reply->minor_version < 2)
    {
      free(composite_version_reply);
      fatal("Need Composite extension 0.2 at least");
    }

  free(composite_version_reply);

  assert(_init_extensions_cookies.damage.sequence);

  xcb_damage_query_version_reply_t *damage_version_reply = 
    xcb_damage_query_version_reply(globalconf.connection,
				   _init_extensions_cookies.damage,
				   NULL);

  if(!damage_version_reply)
    fatal("Can't initialise Damage extension");

  free(damage_version_reply);

  assert(_init_extensions_cookies.xfixes.sequence);

  xcb_xfixes_query_version_reply_t *xfixes_version_reply =
    xcb_xfixes_query_version_reply(globalconf.connection,
				  _init_extensions_cookies.xfixes,
				  NULL);

  /* Need Region objects support introduced in version >= 2.0 */
  if(!xfixes_version_reply || xfixes_version_reply->major_version < 2)
    {
      free(xfixes_version_reply);
      fatal("Need XFixes extension 2.0 at least");
    }

  free(xfixes_version_reply);

  /* Need refresh rates support introduced in version >= 1.1 */
  if(globalconf.extensions.randr)
    {
      assert(_init_extensions_cookies.randr.sequence);

      xcb_randr_query_version_reply_t *randr_version_reply =
        xcb_randr_query_version_reply(globalconf.connection,
                                      _init_extensions_cookies.randr,
                                      NULL);

      if(!randr_version_reply || randr_version_reply->major_version < 1 ||
         randr_version_reply->minor_version < 1)
        globalconf.extensions.randr = NULL;

      free(randr_version_reply);
    }
}