/** Check whether the needed X extensions are present on the * server-side (all the data have been previously pre-fetched in the * extension cache). Then send requests to check their version by * sending QueryVersion requests which is compulsory because the * client MUST negotiate the version of the extension before * executing extension requests */ void display_init_extensions(void) { globalconf.extensions.composite = xcb_get_extension_data(globalconf.connection, &xcb_composite_id); globalconf.extensions.xfixes = xcb_get_extension_data(globalconf.connection, &xcb_xfixes_id); globalconf.extensions.damage = xcb_get_extension_data(globalconf.connection, &xcb_damage_id); globalconf.extensions.randr = xcb_get_extension_data(globalconf.connection, &xcb_randr_id); if(!globalconf.extensions.composite || !globalconf.extensions.composite->present) fatal("No Composite extension"); debug("Composite: major_opcode=%ju", (uintmax_t) globalconf.extensions.composite->major_opcode); if(!globalconf.extensions.xfixes || !globalconf.extensions.xfixes->present) fatal("No XFixes extension"); debug("XFixes: major_opcode=%ju", (uintmax_t) globalconf.extensions.xfixes->major_opcode); if(!globalconf.extensions.damage || !globalconf.extensions.damage->present) fatal("No Damage extension"); debug("Damage: major_opcode=%ju", (uintmax_t) globalconf.extensions.damage->major_opcode); _init_extensions_cookies.composite = xcb_composite_query_version_unchecked(globalconf.connection, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION); _init_extensions_cookies.damage = xcb_damage_query_version_unchecked(globalconf.connection, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION); _init_extensions_cookies.xfixes = xcb_xfixes_query_version_unchecked(globalconf.connection, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION); if(globalconf.extensions.randr && globalconf.extensions.randr->present) _init_extensions_cookies.randr = xcb_randr_query_version(globalconf.connection, XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION); else globalconf.extensions.randr = NULL; }
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; }
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; }
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; }
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 */ }
/* 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; }
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; }
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; }
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); }