diff --git a/utils/chvideomode.1 b/utils/chvideomode.1 index dd844976..bf1b3ec5 100644 --- a/utils/chvideomode.1 +++ b/utils/chvideomode.1 @@ -20,19 +20,21 @@ .Op Fl \-height Ns "=" Ns Ar height .Op Fl \-min-height Ns "=" Ns Ar min-height .Op Fl \-max-height Ns "=" Ns Ar max-height -.Op Ar command ... +.Op Ar videomode .Sh DESCRIPTION .Nm changes the video mode by displaying an interactive menu containing a list of available modes, with an additional entry for entering a custom mode (if supported by the driver). -If the mode change succeeds and -.Ar command -is specified, -.Ar command -is executed. If the mode change fails, the menu is redisplayed until cancellation or a successful mode change. +If the +.Ar videomode +argument is specified in the +.Ar width Ns x Ns Ar height Ns x Ns Ar bits-per-pixel +format per +.Xr videomode 5 , +then the video mode is immediately set non-interactively. .Pp By default, .Nm @@ -142,17 +144,9 @@ inclusive. .Nm exits with an exit status of 10 if the menu is quit, 11 if no modes are available, 12 if no modes are available after filtering, 13 if the terminal has -no associated video devices, 127 if -.Ar command -failed to run, or 1 on any other error. -If +no associated video devices, or 1 on any other error. .Nm -changes the video mode successfully, -.Nm -exits with the exit status of -.Ar command -if specified, -or 0 otherwise. +exits 0 if the video mode is successfully changed. .Sh SEE ALSO .Xr chkblayout 1 , .Xr dispmsg_issue 2 , diff --git a/utils/chvideomode.c b/utils/chvideomode.c index 2ab89a7e..965e58ab 100644 --- a/utils/chvideomode.c +++ b/utils/chvideomode.c @@ -299,6 +299,17 @@ int main(int argc, char* argv[]) compact_arguments(&argc, &argv); + unsigned int xres = 0; + unsigned int yres = 0; + unsigned int bpp = 0; + if ( 2 <= argc ) + { + if ( 2 < argc ) + error(1, 0, "Unexpected extra operand"); + if ( sscanf(argv[1], "%ux%ux%u", &xres, &yres, &bpp) != 3 ) + error(1, 0, "Invalid video mode: %s", argv[1]); + } + int tty_fd = open("/dev/tty", O_RDWR); if ( tty_fd < 0 ) error(1, errno, "/dev/tty"); @@ -349,6 +360,34 @@ retry_pick_mode: decided = false; first_render = true; memset(&render_at, 0, sizeof(render_at)); + if ( 2 <= argc ) + { + bool found_other = true; + size_t other_selection = 0; + for ( size_t i = 0; i < num_modes; i++ ) + { + if ( modes[i].view_xres == xres && + modes[i].view_yres == yres && + modes[i].fb_format == bpp ) + { + selection = i; + decided = true; + break; + } + if ( modes[i].control & DISPMSG_CONTROL_OTHER_RESOLUTIONS ) + { + found_other = true; + other_selection = i; + } + } + if ( !decided ) + { + if ( found_other ) + selection = other_selection; + else + error(1, 0, "No such available resolution: %s", argv[1]); + } + } while ( !decided ) { fflush(stdout); @@ -495,10 +534,10 @@ retry_pick_mode: struct dispmsg_crtc_mode mode = modes[selection]; if ( mode.control & DISPMSG_CONTROL_OTHER_RESOLUTIONS ) { - uintmax_t req_bpp; - uintmax_t req_width; - uintmax_t req_height; - while ( true ) + uintmax_t req_bpp = bpp; + uintmax_t req_width = xres; + uintmax_t req_height = yres; + while ( argc < 2 ) { printf("Enter video mode [BPP x WIDTH x HEIGHT]: "); fflush(stdout); @@ -527,11 +566,5 @@ retry_pick_mode: goto retry_pick_mode; } - if ( 1 < argc ) - { - execvp(argv[1], argv + 1); - error(127, errno, "`%s'", argv[1]); - } - return 0; }