mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Detect whether the terminal has a display and a keyboard layout.
A new ioctl TIOCGDISPLAYS allow detecting which displays the terminal has associated. The ability to set a keyboard layout can be detected with tcgetblob kblayout. Improve the user-space multi-monitor support while here. The kernel now sets TERM rather than init(8). This is a compatible ABI change riding on the previous commit's bump.
This commit is contained in:
parent
db7182ddc3
commit
6ef5a5cee3
12 changed files with 179 additions and 46 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -29,6 +29,7 @@ struct dispd_framebuffer
|
|||
int bpp;
|
||||
int width;
|
||||
int height;
|
||||
uint64_t fb_location;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2013, 2014, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -17,9 +17,10 @@
|
|||
* Handles session management.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/display.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <error.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -34,9 +35,6 @@
|
|||
|
||||
#include "session.h"
|
||||
|
||||
static const uint64_t ONE_AND_ONLY_DEVICE = 0;
|
||||
static const uint64_t ONE_AND_ONLY_CONNECTOR = 0;
|
||||
|
||||
struct dispd_session* global_session = NULL;
|
||||
|
||||
bool dispd__session_initialize(int* argc, char*** argv)
|
||||
|
@ -48,8 +46,21 @@ bool dispd__session_initialize(int* argc, char*** argv)
|
|||
if ( !global_session )
|
||||
return false;
|
||||
memset(global_session, 0, sizeof(*global_session));
|
||||
global_session->device = ONE_AND_ONLY_DEVICE;
|
||||
global_session->connector = ONE_AND_ONLY_CONNECTOR;
|
||||
int tty_fd = open("/dev/tty", O_RDWR);
|
||||
if ( tty_fd < 0 )
|
||||
return free(global_session), false;
|
||||
struct tiocgdisplay display;
|
||||
struct tiocgdisplays gdisplays;
|
||||
memset(&gdisplays, 0, sizeof(gdisplays));
|
||||
gdisplays.count = 1;
|
||||
gdisplays.displays = &display;
|
||||
bool fail = ioctl(tty_fd, TIOCGDISPLAYS, &gdisplays) < 0 ||
|
||||
gdisplays.count == 0;
|
||||
close(tty_fd);
|
||||
if ( fail )
|
||||
return free(global_session), false;
|
||||
global_session->device = display.device;
|
||||
global_session->connector = display.connector;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2013, 2014, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -17,8 +17,8 @@
|
|||
* Handles windows.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/display.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <ioleast.h>
|
||||
|
@ -102,6 +102,7 @@ struct dispd_framebuffer* dispd_begin_render(struct dispd_window* window)
|
|||
fb->pitch = fb->width * fb->bpp / 8;
|
||||
fb->datasize = fb->pitch * fb->height;
|
||||
fb->data = (uint8_t*) request_buffer(window, fb->datasize);
|
||||
fb->fb_location = msg.mode.fb_location;
|
||||
if ( !fb->data ) { free(fb); return NULL; }
|
||||
return fb;
|
||||
}
|
||||
|
@ -113,7 +114,7 @@ bool dispd_finish_render(struct dispd_framebuffer* fb)
|
|||
struct dispmsg_write_memory msg;
|
||||
msg.msgid = DISPMSG_WRITE_MEMORY;
|
||||
msg.device = window->session->device;
|
||||
msg.offset = 0;
|
||||
msg.offset = fb->fb_location;
|
||||
msg.size = fb->datasize;
|
||||
msg.src = fb->data;
|
||||
if ( dispmsg_issue(&msg, sizeof(msg)) == 0 )
|
||||
|
|
36
init/init.c
36
init/init.c
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/display.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -429,6 +430,14 @@ static void set_hostname(void)
|
|||
|
||||
static void set_kblayout(void)
|
||||
{
|
||||
int tty_fd = open("/dev/tty", O_RDWR);
|
||||
if ( !tty_fd )
|
||||
return warning("unable to set keyboard layout: /dev/tty: %m");
|
||||
bool unsupported = tcgetblob(tty_fd, "kblayout", NULL, 0) < 0 &&
|
||||
(errno == ENOTTY || errno == ENOENT);
|
||||
close(tty_fd);
|
||||
if ( unsupported )
|
||||
return;
|
||||
FILE* fp = fopen("/etc/kblayout", "r");
|
||||
if ( !fp && errno == ENOENT )
|
||||
return;
|
||||
|
@ -440,7 +449,11 @@ static void set_kblayout(void)
|
|||
return warning("unable to set keyboard layout: /etc/kblayout: %m");
|
||||
pid_t child_pid = fork();
|
||||
if ( child_pid < 0 )
|
||||
return warning("unable to set keyboard layout: fork: %m");
|
||||
{
|
||||
free(kblayout);
|
||||
warning("unable to set keyboard layout: fork: %m");
|
||||
return;
|
||||
}
|
||||
if ( !child_pid )
|
||||
{
|
||||
execlp("chkblayout", "chkblayout", "--", kblayout, (const char*) NULL);
|
||||
|
@ -454,6 +467,19 @@ static void set_kblayout(void)
|
|||
|
||||
static void set_videomode(void)
|
||||
{
|
||||
int tty_fd = open("/dev/tty", O_RDWR);
|
||||
if ( !tty_fd )
|
||||
return warning("unable to set video mode: /dev/tty: %m");
|
||||
struct tiocgdisplay display;
|
||||
struct tiocgdisplays gdisplays;
|
||||
memset(&gdisplays, 0, sizeof(gdisplays));
|
||||
gdisplays.count = 1;
|
||||
gdisplays.displays = &display;
|
||||
bool unsupported = ioctl(tty_fd, TIOCGDISPLAYS, &gdisplays) < 0 ||
|
||||
gdisplays.count == 0;
|
||||
close(tty_fd);
|
||||
if ( unsupported )
|
||||
return;
|
||||
FILE* fp = fopen("/etc/videomode", "r");
|
||||
if ( !fp && errno == ENOENT )
|
||||
return;
|
||||
|
@ -476,8 +502,8 @@ static void set_videomode(void)
|
|||
struct dispmsg_get_crtc_mode get_mode;
|
||||
memset(&get_mode, 0, sizeof(get_mode));
|
||||
get_mode.msgid = DISPMSG_GET_CRTC_MODE;
|
||||
get_mode.device = 0;
|
||||
get_mode.connector = 0;
|
||||
get_mode.device = display.device;
|
||||
get_mode.connector = display.connector;
|
||||
// Don't set the resolution if it's already correct.
|
||||
if ( dispmsg_issue(&get_mode, sizeof(get_mode)) == 0 )
|
||||
{
|
||||
|
@ -530,10 +556,6 @@ static void init_early(void)
|
|||
// Set up the PATH variable.
|
||||
if ( setenv("PATH", "/bin:/sbin", 1) < 0 )
|
||||
fatal("setenv: %m");
|
||||
|
||||
// Set the terminal type.
|
||||
if ( setenv("TERM", "sortix", 1) < 0 )
|
||||
fatal("setenv: %m");
|
||||
}
|
||||
|
||||
static bool is_chain_init_mountpoint(const struct mountpoint* mountpoint)
|
||||
|
|
|
@ -161,6 +161,18 @@ struct dispmsg_read_memory
|
|||
uint8_t* dst; // in, *out
|
||||
};
|
||||
|
||||
struct tiocgdisplay
|
||||
{
|
||||
uint64_t device;
|
||||
uint64_t connector;
|
||||
};
|
||||
|
||||
struct tiocgdisplays
|
||||
{
|
||||
size_t count; // in, out
|
||||
struct tiocgdisplay* displays; // in, *out
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -38,5 +38,6 @@
|
|||
#define TIOCGPTLCK __IOCTL(5, __IOCTL_TYPE_PTR)
|
||||
#define TIOCGNAME __IOCTL(6, __IOCTL_TYPE_PTR)
|
||||
#define TIOCGPTN __IOCTL(7, __IOCTL_TYPE_PTR)
|
||||
#define TIOCGDISPLAYS __IOCTL(8, __IOCTL_TYPE_PTR)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -719,8 +719,8 @@ static void InitThread(void* /*user*/)
|
|||
|
||||
Log::PrintF("\r\e[m\e[J");
|
||||
|
||||
int envc = 0;
|
||||
const char* envp[] = { NULL };
|
||||
int envc = 1;
|
||||
const char* envp[] = { "TERM=sortix", NULL };
|
||||
struct thread_registers regs;
|
||||
assert((((uintptr_t) ®s) & (alignof(regs)-1)) == 0);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <sortix/display.h>
|
||||
#include <sortix/fcntl.h>
|
||||
#include <sortix/ioctl.h>
|
||||
#include <sortix/keycodes.h>
|
||||
|
@ -332,6 +333,27 @@ int LogTerminal::ioctl(ioctx_t* ctx, int cmd, uintptr_t arg)
|
|||
return -1;
|
||||
return 0;
|
||||
}
|
||||
else if ( cmd == TIOCGDISPLAYS )
|
||||
{
|
||||
struct tiocgdisplays* input = (struct tiocgdisplays*) arg;
|
||||
struct tiocgdisplays gdisplays;
|
||||
if ( !ctx->copy_from_src(&gdisplays, input, sizeof(gdisplays)) )
|
||||
return -1;
|
||||
if ( 0 < gdisplays.count )
|
||||
{
|
||||
struct tiocgdisplay display;
|
||||
memset(&display, 0, sizeof(display));
|
||||
display.device = 0;
|
||||
display.connector = 0;
|
||||
if ( !ctx->copy_to_dest(gdisplays.displays, &display,
|
||||
sizeof(display)) )
|
||||
return -1;
|
||||
}
|
||||
gdisplays.count = 1;
|
||||
if ( !ctx->copy_to_dest(input, &gdisplays, sizeof(gdisplays)) )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
lock.Reset();
|
||||
return TTY::ioctl(ctx, cmd, arg);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <sys/display.h>
|
||||
#include <sys/display.h>
|
||||
#include <sys/kernelinfo.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/termmode.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -106,17 +107,21 @@ struct glogin
|
|||
bool pointer_working;
|
||||
struct termios old_tio;
|
||||
bool has_old_tio;
|
||||
uint64_t device;
|
||||
uint64_t connector;
|
||||
};
|
||||
|
||||
static struct glogin state;
|
||||
|
||||
static bool get_graphical_mode(struct dispmsg_crtc_mode* mode)
|
||||
static bool get_graphical_mode(uint64_t device,
|
||||
uint64_t connector,
|
||||
struct dispmsg_crtc_mode* mode)
|
||||
{
|
||||
struct dispmsg_get_crtc_mode msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msgid = DISPMSG_GET_CRTC_MODE;
|
||||
msg.device = 0; // TODO: Multi-screen support!
|
||||
msg.connector = 0; // TODO: Multi-screen support!
|
||||
msg.device = device;
|
||||
msg.connector = connector;
|
||||
if ( dispmsg_issue(&msg, sizeof(msg)) != 0 )
|
||||
{
|
||||
warn("dispmsg_issue: DISPMSG_GET_CRTC_MODE");
|
||||
|
@ -496,8 +501,8 @@ static bool screen_capture(struct glogin* state, struct framebuffer* fb)
|
|||
struct dispmsg_write_memory msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msgid = DISPMSG_READ_MEMORY;
|
||||
msg.device = 0; // TODO: Multi-screen support!
|
||||
msg.offset = 0; // TODO: mode.fb_location!
|
||||
msg.device = state->device;
|
||||
msg.offset = state->mode.fb_location;
|
||||
msg.size = fb->xres * fb->yres * sizeof(fb->buffer[0]);
|
||||
msg.src = (uint8_t*) fb->buffer;
|
||||
if ( dispmsg_issue(&msg, sizeof(msg)) != 0 )
|
||||
|
@ -510,7 +515,7 @@ static bool screen_capture(struct glogin* state, struct framebuffer* fb)
|
|||
|
||||
static bool begin_render(struct glogin* state, struct framebuffer* fb)
|
||||
{
|
||||
if ( !get_graphical_mode(&state->mode) )
|
||||
if ( !get_graphical_mode(state->device, state->connector, &state->mode) )
|
||||
return false;
|
||||
fb->xres = state->mode.view_xres;
|
||||
fb->yres = state->mode.view_yres;
|
||||
|
@ -530,8 +535,8 @@ static bool finish_render(struct glogin* state, struct framebuffer* fb)
|
|||
struct dispmsg_write_memory msg;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msgid = DISPMSG_WRITE_MEMORY;
|
||||
msg.device = 0; // TODO: Multi-screen support!
|
||||
msg.offset = 0; // TODO: mode.fb_location!
|
||||
msg.device = state->device;
|
||||
msg.offset = state->mode.fb_location;
|
||||
msg.size = sizeof(uint32_t) * fb->xres * fb->yres;
|
||||
msg.src = (uint8_t*) fb->buffer;
|
||||
if ( dispmsg_issue(&msg, sizeof(msg)) != 0 )
|
||||
|
@ -730,8 +735,19 @@ bool glogin_init(struct glogin* state)
|
|||
{
|
||||
memset(state, 0, sizeof(*state));
|
||||
state->fd_mouse = -1;
|
||||
|
||||
if ( !get_graphical_mode(&state->mode) )
|
||||
struct tiocgdisplay display;
|
||||
struct tiocgdisplays gdisplays;
|
||||
memset(&gdisplays, 0, sizeof(gdisplays));
|
||||
gdisplays.count = 1;
|
||||
gdisplays.displays = &display;
|
||||
if ( ioctl(1, TIOCGDISPLAYS, &gdisplays) < 0 || gdisplays.count == 0 )
|
||||
{
|
||||
glogin_destroy(state);
|
||||
return false;
|
||||
}
|
||||
state->device = display.device;
|
||||
state->connector = display.connector;
|
||||
if ( !get_graphical_mode(state->device, state->connector, &state->mode) )
|
||||
{
|
||||
warn("dispmsg_issue");
|
||||
glogin_destroy(state);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/display.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/kernelinfo.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -37,6 +38,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Sortix libc doesn't have its own proper <limits.h> at this time.
|
||||
|
@ -472,7 +474,8 @@ int main(void)
|
|||
|
||||
install_configurationf("upgrade.conf", "a", "src = yes\n");
|
||||
|
||||
while ( true )
|
||||
bool kblayout_setable = 0 <= tcgetblob(0, "kblayout", NULL, 0);
|
||||
while ( kblayout_setable )
|
||||
{
|
||||
// TODO: Detect the name of the current keyboard layout.
|
||||
prompt(input, sizeof(input),
|
||||
|
@ -510,25 +513,36 @@ int main(void)
|
|||
if ( execute(argv, "f") == 0 )
|
||||
break;
|
||||
}
|
||||
if ( !input[0] || !strcmp(input, "default") )
|
||||
text("/etc/kblayout will not be created (default).\n");
|
||||
else
|
||||
if ( kblayout_setable )
|
||||
{
|
||||
textf("/etc/kblayout will be set to \"%s\".\n", input);
|
||||
mode_t old_umask = getumask();
|
||||
umask(022);
|
||||
install_configurationf("kblayout", "w", "%s\n", input);
|
||||
umask(old_umask);
|
||||
if ( !input[0] || !strcmp(input, "default") )
|
||||
text("/etc/kblayout will not be created (default).\n");
|
||||
else
|
||||
{
|
||||
textf("/etc/kblayout will be set to \"%s\".\n", input);
|
||||
mode_t old_umask = getumask();
|
||||
umask(022);
|
||||
install_configurationf("kblayout", "w", "%s\n", input);
|
||||
umask(old_umask);
|
||||
}
|
||||
text("\n");
|
||||
}
|
||||
text("\n");
|
||||
|
||||
struct tiocgdisplay display;
|
||||
struct tiocgdisplays gdisplays;
|
||||
memset(&gdisplays, 0, sizeof(gdisplays));
|
||||
gdisplays.count = 1;
|
||||
gdisplays.displays = &display;
|
||||
struct dispmsg_get_driver_name dgdn = { 0 };
|
||||
dgdn.msgid = DISPMSG_GET_DRIVER_NAME;
|
||||
dgdn.device = 0;
|
||||
dgdn.driver_index = 0;
|
||||
dgdn.name.byte_size = 0;
|
||||
dgdn.name.str = NULL;
|
||||
if ( dispmsg_issue(&dgdn, sizeof(dgdn)) == 0 || errno != ENODEV )
|
||||
if ( ioctl(1, TIOCGDISPLAYS, &gdisplays) == 0 &&
|
||||
1 < gdisplays.count &&
|
||||
(dgdn.device = display.device, true) &&
|
||||
(dispmsg_issue(&dgdn, sizeof(dgdn)) == 0 || errno != ENODEV) )
|
||||
{
|
||||
while ( true )
|
||||
{
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/display.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
|
@ -32,6 +33,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -379,7 +381,8 @@ int main(void)
|
|||
prompt(input, sizeof(input), "Ready?", ready);
|
||||
text("\n");
|
||||
|
||||
while ( true )
|
||||
bool kblayout_setable = 0 <= tcgetblob(0, "kblayout", NULL, 0);
|
||||
while ( kblayout_setable )
|
||||
{
|
||||
// TODO: Detect the name of the current keyboard layout.
|
||||
prompt(input, sizeof(input),
|
||||
|
@ -417,15 +420,24 @@ int main(void)
|
|||
if ( execute(argv, "f") == 0 )
|
||||
break;
|
||||
}
|
||||
text("\n");
|
||||
if ( kblayout_setable )
|
||||
text("\n");
|
||||
|
||||
struct tiocgdisplay display;
|
||||
struct tiocgdisplays gdisplays;
|
||||
memset(&gdisplays, 0, sizeof(gdisplays));
|
||||
gdisplays.count = 1;
|
||||
gdisplays.displays = &display;
|
||||
struct dispmsg_get_driver_name dgdn = { 0 };
|
||||
dgdn.msgid = DISPMSG_GET_DRIVER_NAME;
|
||||
dgdn.device = 0;
|
||||
dgdn.driver_index = 0;
|
||||
dgdn.name.byte_size = 0;
|
||||
dgdn.name.str = NULL;
|
||||
if ( dispmsg_issue(&dgdn, sizeof(dgdn)) == 0 || errno != ENODEV )
|
||||
if ( ioctl(1, TIOCGDISPLAYS, &gdisplays) == 0 &&
|
||||
1 < gdisplays.count &&
|
||||
(dgdn.device = display.device, true) &&
|
||||
(dispmsg_issue(&dgdn, sizeof(dgdn)) == 0 || errno != ENODEV) )
|
||||
{
|
||||
while ( true )
|
||||
{
|
||||
|
@ -439,8 +451,8 @@ int main(void)
|
|||
continue;
|
||||
break;
|
||||
}
|
||||
text("\n");
|
||||
}
|
||||
text("\n");
|
||||
|
||||
struct release new_release;
|
||||
if ( !os_release_load(&new_release, "/etc/sortix-release",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2013, 2014 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2012, 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -18,12 +18,14 @@
|
|||
*/
|
||||
|
||||
#include <sys/display.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/keycodes.h>
|
||||
#include <sys/termmode.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -34,6 +36,9 @@
|
|||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static uint64_t device;
|
||||
static uint64_t connector;
|
||||
|
||||
bool SetCurrentMode(struct dispmsg_crtc_mode mode)
|
||||
{
|
||||
struct dispmsg_set_crtc_mode msg;
|
||||
|
@ -324,6 +329,22 @@ int main(int argc, char* argv[])
|
|||
|
||||
compact_arguments(&argc, &argv);
|
||||
|
||||
int tty_fd = open("/dev/tty", O_RDWR);
|
||||
if ( tty_fd < 0 )
|
||||
error(1, errno, "/dev/tty");
|
||||
struct tiocgdisplay display;
|
||||
struct tiocgdisplays gdisplays;
|
||||
memset(&gdisplays, 0, sizeof(gdisplays));
|
||||
gdisplays.count = 1;
|
||||
gdisplays.displays = &display;
|
||||
if ( ioctl(1, TIOCGDISPLAYS, &gdisplays) < 0 || gdisplays.count == 0 )
|
||||
{
|
||||
fprintf(stderr, "No video devices are associated with this terminal.\n");
|
||||
exit(13);
|
||||
}
|
||||
device = display.device;
|
||||
connector = display.connector;
|
||||
|
||||
size_t num_modes = 0;
|
||||
struct dispmsg_crtc_mode* modes = GetAvailableModes(&num_modes);
|
||||
if ( !modes )
|
||||
|
|
Loading…
Add table
Reference in a new issue