This change adds the display(1) graphical user interface and desktop environment with basic windowing support and the graphical terminal(1) emulator along with integrations in chkblayout(1), chvideomode(1), sysinstall(8), sysupgrade(8), as well as the games and ports. Adopt the Aurora procedural wallpaper in display(1) and login(8). Remove the obsolete dispd. Juhani contributed keyboard and video mode APIs to the display protocol and other miscellaneous changes. dzwdz contributed the initial functioning window buttons, improved title bar, window tiling, and minor bug fixes Co-authored-by: Juhani Krekelä <juhani@krekelä.fi> Co-authored-by: dzwdz <kg67199@gmail.com>
151 lines
3.8 KiB
C
151 lines
3.8 KiB
C
/*
|
|
* Copyright (c) 2014 Jonas 'Sortie' Termansen.
|
|
* Copyright (c) 2023 Juhani 'nortti' Krekelä.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* chkblayout.c
|
|
* Changes the current keyboard layout.
|
|
*/
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <display.h>
|
|
#include <err.h>
|
|
#include <errno.h>
|
|
#include <error.h>
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
#include <ioleast.h>
|
|
#include <locale.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <termios.h>
|
|
|
|
#define CHKBLAYOUT_ID 0
|
|
|
|
static bool chkblayout_ack_received = false;
|
|
static int chkblayout_error;
|
|
|
|
static void on_ack(void* ctx, uint32_t id, int32_t error)
|
|
{
|
|
(void) ctx;
|
|
if ( id != CHKBLAYOUT_ID )
|
|
return;
|
|
chkblayout_error = error;
|
|
chkblayout_ack_received = true;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
bool list = false;
|
|
|
|
setlocale(LC_ALL, "");
|
|
|
|
const struct option longopts[] =
|
|
{
|
|
{"list", no_argument, NULL, 'l'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
const char* opts = "l";
|
|
int opt;
|
|
while ( (opt = getopt_long(argc, argv, opts, longopts, NULL)) != -1 )
|
|
{
|
|
switch ( opt )
|
|
{
|
|
case 'l': list = true; break;
|
|
default: return 1;
|
|
}
|
|
}
|
|
|
|
if ( list )
|
|
{
|
|
if ( 0 < argc - optind )
|
|
errx(1, "unexpected extra operand");
|
|
execlp("ls", "ls", "/share/kblayout", (const char*) NULL);
|
|
err(127, "ls");
|
|
}
|
|
|
|
const char* tty_path = "/dev/tty";
|
|
int tty_fd = open(tty_path, O_WRONLY);
|
|
if ( tty_fd < 0 )
|
|
err(1, "%s", tty_path);
|
|
if ( !isatty(tty_fd) )
|
|
err(1, "%s", tty_path);
|
|
|
|
if ( argc - optind == 0 )
|
|
errx(1, "expected new keyboard layout");
|
|
if ( 1 < argc - optind )
|
|
errx(1, "unexpected extra operand");
|
|
|
|
const char* kblayout_path = argv[optind];
|
|
if ( !strchr(kblayout_path, '/') )
|
|
{
|
|
char* new_kblayout_path;
|
|
if ( asprintf(&new_kblayout_path, "/share/kblayout/%s", kblayout_path) < 0 )
|
|
err(1, "asprintf");
|
|
kblayout_path = new_kblayout_path;
|
|
}
|
|
int kblayout_fd = open(kblayout_path, O_RDONLY);
|
|
if ( kblayout_fd < 0 )
|
|
err(1, "%s", kblayout_path);
|
|
|
|
struct stat kblayout_st;
|
|
if ( fstat(kblayout_fd, &kblayout_st) < 0 )
|
|
err(1, "stat: %s", kblayout_path);
|
|
|
|
if ( (size_t) kblayout_st.st_size != (uintmax_t) kblayout_st.st_size )
|
|
error(1, EFBIG, "%s", kblayout_path);
|
|
|
|
size_t kblayout_size = (size_t) kblayout_st.st_size;
|
|
unsigned char* kblayout = (unsigned char*) malloc(kblayout_size);
|
|
if ( !kblayout )
|
|
err(1, "malloc");
|
|
if ( readall(kblayout_fd, kblayout, kblayout_size) != kblayout_size )
|
|
err(1, "read: %s", kblayout_path);
|
|
close(kblayout_fd);
|
|
|
|
if ( getenv("DISPLAY_SOCKET") )
|
|
{
|
|
struct display_connection* connection = display_connect_default();
|
|
if ( !connection )
|
|
err(1, "Could not connect to display server");
|
|
|
|
display_chkblayout(connection, CHKBLAYOUT_ID, kblayout, kblayout_size);
|
|
|
|
struct display_event_handlers handlers = {0};
|
|
handlers.ack_handler = on_ack;
|
|
while ( !chkblayout_ack_received )
|
|
display_wait_event(connection, &handlers);
|
|
|
|
if ( chkblayout_error )
|
|
{
|
|
errno = chkblayout_error;
|
|
err(1, "tcsetblob: kblayout: %s", kblayout_path);
|
|
}
|
|
|
|
display_disconnect(connection);
|
|
}
|
|
else if ( tcsetblob(tty_fd, "kblayout", kblayout, kblayout_size) < 0 )
|
|
err(1, "tcsetblob: kblayout: %s", kblayout_path);
|
|
|
|
free(kblayout);
|
|
|
|
close(tty_fd);
|
|
|
|
return 0;
|
|
}
|