diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2013-10-23 15:11:21 +0200 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2013-10-23 15:11:21 +0200 |
commit | 695c855da33c3ef40bdd6e5bce7a6a78875a7af8 (patch) | |
tree | 04490fb6d01a6f941e61c234246da3ea2370175d | |
parent | cdd87983a0b8e026917b167a601d594ded29427d (diff) |
wlterm: remove
Remove all wlterm sources. I never intended to maintain it longer than any
major terminal-emulator needs to get ported over to wayland. Hence, remove
it. It was buggy, anyway.
If anyone is interested, a GTK+ based wlterm is available on:
http://cgit.freedesktop.org/~dvdhrm/wlterm
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 39 | ||||
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | configure.ac | 67 | ||||
-rw-r--r-- | src/wlt_main.c | 474 | ||||
-rw-r--r-- | src/wlt_main.h | 96 | ||||
-rw-r--r-- | src/wlt_terminal.c | 808 | ||||
-rw-r--r-- | src/wlt_terminal.h | 52 | ||||
-rw-r--r-- | src/wlt_theme.c | 633 | ||||
-rw-r--r-- | src/wlt_theme.h | 41 | ||||
-rw-r--r-- | src/wlt_toolkit.c | 1940 | ||||
-rw-r--r-- | src/wlt_toolkit.h | 203 |
12 files changed, 0 insertions, 4355 deletions
@@ -41,7 +41,6 @@ docs/reference/*.stamp docs/reference/version.xml docs/reference/*/ uvtd -wlterm docs/man/*.1 docs/man/*.3 docs/man/*.5 diff --git a/Makefile.am b/Makefile.am index 0aeacff..7eddd69 100644 --- a/Makefile.am +++ b/Makefile.am @@ -686,45 +686,6 @@ kmscon_LDADD += $(FUSE_LIBS) endif # -# Wayland Terminal -# - -if BUILD_ENABLE_WLTERM -bin_PROGRAMS += wlterm -endif - -wlterm_SOURCES = \ - src/wlt_main.h \ - src/wlt_main.c \ - src/wlt_toolkit.h \ - src/wlt_toolkit.c \ - src/wlt_theme.h \ - src/wlt_theme.c \ - src/wlt_terminal.h \ - src/wlt_terminal.c \ - src/conf.h \ - src/conf.c \ - src/pty.h \ - src/pty.c \ - src/font.h \ - src/font.c \ - src/font_8x16.c \ - src/font_pango.c -wlterm_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - $(WAYLAND_CFLAGS) \ - $(PANGO_CFLAGS) \ - $(XKBCOMMON_CFLAGS) -wlterm_LDADD = \ - $(WAYLAND_LIBS) \ - $(PANGO_LIBS) \ - $(XKBCOMMON_LIBS) \ - libeloop.la \ - libtsm.la \ - libshl.la \ - -lpthread - -# # uvtd # @@ -93,7 +93,6 @@ Released tarballs can be found at: dependency-checks fail, they are disabled by default unless explicitly enabled on the command line: --enable-kmscon: Build kmscon application [default: on] - --enable-wlterm: Build wlterm Wayland terminal [default: off] --enable-eloop: Build eloop event loop library [default: off] --enable-tsm: Build TSM terminal state-machine library [default: off] --enable-uterm: Build uterm library [default: off] diff --git a/configure.ac b/configure.ac index b5d9513..393f52b 100644 --- a/configure.ac +++ b/configure.ac @@ -60,11 +60,6 @@ PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon], AC_SUBST(XKBCOMMON_CFLAGS) AC_SUBST(XKBCOMMON_LIBS) -PKG_CHECK_MODULES([WAYLAND], [wayland-client wayland-server wayland-cursor], - [have_wayland=yes], [have_wayland=no]) -AC_SUBST(WAYLAND_CFLAGS) -AC_SUBST(WAYLAND_LIBS) - PKG_CHECK_MODULES([SYSTEMD], [libsystemd-daemon libsystemd-login], [have_systemd=yes], [have_systemd=no]) AC_SUBST(SYSTEMD_CFLAGS) @@ -202,18 +197,6 @@ elif test "x$enable_kmscon" = "x" ; then fi AC_MSG_RESULT([$enable_kmscon]) -# wlterm -AC_MSG_CHECKING([whether user wants wlterm]) -AC_ARG_ENABLE([wlterm], - [AS_HELP_STRING([--enable-wlterm], - [build wlterm])]) -if test "x$enable_all" = "xyes" ; then - enable_wlterm="yes" -elif test "x$enable_wlterm" = "x" ; then - enable_wlterm="no (default)" -fi -AC_MSG_RESULT([$enable_wlterm]) - # uvtd AC_MSG_CHECKING([whether user wants uvtd]) AC_ARG_ENABLE([uvtd], @@ -838,40 +821,6 @@ else kmscon_missing="enable-kmscon" fi -# wlterm -wlterm_avail=no -wlterm_missing="" -if test ! "x$enable_wlterm" = "xno" ; then - wlterm_avail=yes - if test "x$tsm_avail" = "xno" ; then - wlterm_avail=no - wlterm_missing="$tsm_missing,$wlterm_missing" - fi - - if test "x$eloop_avail" = "xno" ; then - wlterm_avail=no - wlterm_missing="$eloop_missing,$wlterm_missing" - fi - - if test "x$font_pango_avail" = "xno" ; then - wlterm_avail=no - wlterm_missing="$font_pango_missing,$wlterm_missing" - fi - - if test "x$have_wayland" = "xno" ; then - wlterm_avail=no - wlterm_missing="libwayland,$wlterm_missing" - fi - - if test "x$wlterm_avail" = "xno" ; then - if test "x$enable_wlterm" = "xyes" ; then - AC_ERROR([missing for wlterm: $wlterm_missing]) - fi - fi -else - wlterm_missing="enable-wlterm" -fi - # uvtd uvtd_avail=no uvtd_missing="" @@ -914,17 +863,6 @@ if test "x$uvtd_avail" = "xyes" ; then fi fi -# wlterm -wlterm_enabled=no -if test "x$wlterm_avail" = "xyes" ; then - if test "x${enable_wlterm% *}" = "xyes" ; then - wlterm_enabled=yes - enable_eloop=yes - enable_tsm=yes - enable_font_pango=yes - fi -fi - # kmscon kmscon_enabled=no if test "x$kmscon_avail" = "xyes" ; then @@ -1293,10 +1231,6 @@ AM_CONDITIONAL([BUILD_ENABLE_SESSION_CDEV], AM_CONDITIONAL([BUILD_ENABLE_KMSCON], [test "x$kmscon_enabled" = "xyes"]) -# wlterm -AM_CONDITIONAL([BUILD_ENABLE_WLTERM], - [test "x$wlterm_enabled" = "xyes"]) - # uvtd AM_CONDITIONAL([BUILD_ENABLE_UVTD], [test "x$uvtd_enabled" = "xyes"]) @@ -1384,7 +1318,6 @@ AC_MSG_NOTICE([Build configuration: Applications and Libraries: kmscon: $kmscon_enabled ($kmscon_avail: $kmscon_missing) - wlterm: $wlterm_enabled ($wlterm_avail: $wlterm_missing) uvtd: $uvtd_enabled ($uvtd_avail: $uvtd_missing) uterm: $uterm_enabled ($uterm_avail: $uterm_missing) tsm: $tsm_enabled ($tsm_avail: $tsm_missing) diff --git a/src/wlt_main.c b/src/wlt_main.c deleted file mode 100644 index f3caa58..0000000 --- a/src/wlt_main.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * wlt - Wayland Terminal - * - * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Wayland Terminal main application - */ - -#include <errno.h> -#include <paths.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/signalfd.h> -#include <wayland-client.h> -#include "conf.h" -#include "eloop.h" -#include "font.h" -#include "shl_dlist.h" -#include "shl_log.h" -#include "shl_misc.h" -#include "wlt_main.h" -#include "wlt_terminal.h" -#include "wlt_theme.h" -#include "wlt_toolkit.h" - -#define LOG_SUBSYSTEM "wlt" - -struct wlt_app { - struct ev_eloop *eloop; - struct wlt_display *disp; - struct wlt_window *wnd; -}; - -/* TODO: The font layer depends on kmscon modules. However, the WLT applications - * doesn't use them. Therefore, we provide dummy kmscon_module_* helpers here - * which satisfy the dependencies and allow us to link to font.so. */ - -void kmscon_module_ref(struct kmscon_module *m) -{ -} - -void kmscon_module_unref(struct kmscon_module *m) -{ -} - -static void sig_generic(struct ev_eloop *eloop, struct signalfd_siginfo *info, - void *data) -{ - struct wlt_app *app = data; - - ev_eloop_exit(app->eloop); - log_info("terminating due to caught signal %d", info->ssi_signo); -} - -static void window_close(struct wlt_window *wnd, void *data) -{ - struct wlt_app *app = data; - - log_info("closing window"); - ev_eloop_exit(app->eloop); -} - -static void terminal_close(struct wlt_terminal *term, unsigned int event, - void *data) -{ - struct wlt_app *app = data; - - if (event == WLT_TERMINAL_HUP) { - log_info("closing pty"); - ev_eloop_exit(app->eloop); - } -} - -static int window_init(struct wlt_app *app) -{ - int ret; - struct wlt_theme *theme; - struct wlt_terminal *term; - - ret = wlt_display_create_window(app->disp, &app->wnd, - 600, 400, app); - if (ret) { - log_error("cannot create wayland window"); - return ret; - } - wlt_window_set_close_cb(app->wnd, window_close); - - ret = wlt_theme_new(&theme, app->wnd); - if (ret) { - log_error("cannot create theme"); - return ret; - } - - ret = wlt_terminal_new(&term, app->wnd); - if (ret) { - log_error("cannot create terminal"); - return ret; - } - - ret = wlt_terminal_open(term, terminal_close, app); - if (ret) { - log_error("cannot open terminal"); - return ret; - } - - return 0; -} - -static void display_event(struct wlt_display *disp, unsigned int event, - void *data) -{ - struct wlt_app *app = data; - int ret; - - switch (event) { - case WLT_DISPLAY_READY: - log_info("wayland display initialized"); - ret = window_init(app); - if (ret) - ev_eloop_exit(app->eloop); - break; - case WLT_DISPLAY_HUP: - log_info("wayland display connection lost"); - ev_eloop_exit(app->eloop); - break; - } -} - -static void destroy_app(struct wlt_app *app) -{ - wlt_window_unref(app->wnd); - wlt_display_unregister_cb(app->disp, display_event, app); - wlt_display_unref(app->disp); - ev_eloop_unregister_signal_cb(app->eloop, SIGINT, sig_generic, app); - ev_eloop_unregister_signal_cb(app->eloop, SIGTERM, sig_generic, app); - ev_eloop_unref(app->eloop); -} - -static int setup_app(struct wlt_app *app) -{ - int ret; - - ret = ev_eloop_new(&app->eloop, log_llog, NULL); - if (ret) - goto err_app; - - ret = ev_eloop_register_signal_cb(app->eloop, SIGTERM, - sig_generic, app); - if (ret) - goto err_app; - - ret = ev_eloop_register_signal_cb(app->eloop, SIGINT, - sig_generic, app); - if (ret) - goto err_app; - - ret = wlt_display_new(&app->disp, app->eloop); - if (ret) - goto err_app; - - ret = wlt_display_register_cb(app->disp, display_event, app); - if (ret) - goto err_app; - - return 0; - -err_app: - destroy_app(app); - return ret; -} - -struct wlt_conf_t wlt_conf; -#define WLT_CONF_FROM_FIELD(_mem, _name) \ - shl_offsetof((_mem), struct wlt_conf_t, _name) - -static void print_help() -{ - /* - * Usage/Help information - * This should be scaled to a maximum of 80 characters per line: - * - * 80 char line: - * | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | - * "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" - * 80 char line starting with tab: - * |10| 20 | 30 | 40 | 50 | 60 | 70 | 80 | - * "\t901234567890123456789012345678901234567890123456789012345678901234567890\n" - */ - fprintf(stderr, - "Usage:\n" - "\t%1$s [options]\n" - "\t%1$s -h [options]\n" - "\t%1$s -l [options] -- /bin/sh [sh-arguments]\n" - "\n" - "You can prefix boolean options with \"no-\" to negate it. If an argument is\n" - "given multiple times, only the last argument matters if not otherwise stated.\n" - "\n" - "General Options:\n" - "\t-h, --help [off] Print this help and exit\n" - "\t-v, --verbose [off] Print verbose messages\n" - "\t --debug [off] Enable debug mode\n" - "\t --silent [off] Suppress notices and warnings\n" - "\n" - "Terminal Options:\n" - "\t-l, --login [/bin/sh]\n" - "\t Start the given login process instead\n" - "\t of the default process; all arguments\n" - "\t following '--' will be be parsed as\n" - "\t argv to this process. No more options\n" - "\t after '--' will be parsed so use it at\n" - "\t the end of the argument string\n" - "\t-t, --term <TERM> [xterm-256color]\n" - "\t Value of the TERM environment variable\n" - "\t for the child process\n" - "\t --palette <name> [default]\n" - "\t Select the used color palette\n" - "\t --sb-size <num> [1000]\n" - "\t Size of the scrollback-buffer in lines\n" - "\n" - "Keyboard Shortcuts and Grabs:\n" - "\t --grab-scroll-up <grab> [<Shift>Up]\n" - "\t Shortcut to scroll up\n" - "\t --grab-scroll-down <grab> [<Shift>Down]\n" - "\t Shortcut to scroll down\n" - "\t --grab-page-up <grab> [<Shift>Prior]\n" - "\t Shortcut to scroll page up\n" - "\t --grab-page-down <grab> [<Shift>Next]\n" - "\t Shortcut to scroll page down\n" - "\t --grab-fullscreen <grab> [F11]\n" - "\t Shortcut to toggle fullscreen mode\n" - "\t --grab-zoom-in <grab> [<Ctrl>plus]\n" - "\t Shortcut to increase font size\n" - "\t --grab-zoom-out <grab> [<Ctrl>minus]\n" - "\t Shortcut to decrease font size\n" - "\t --grab-copy <grab> [<Logo>c]\n" - "\t Copy selected text\n" - "\t --grab-paste <grab> [<Logo>v]\n" - "\t Paste selection buffer\n" - "\n" - "Font Options:\n" - "\t --font-engine <engine> [pango]\n" - "\t Font engine\n" - "\t --font-size <points> [15]\n" - "\t Font size in points\n" - "\t --font-name <name> [monospace]\n" - "\t Font name\n" - "\t --font-dpi <dpi> [96]\n" - "\t Force DPI value for all fonts\n" - "\n" - "Input Options:\n" - "\t --xkb-repeat-delay <msecs> [250]\n" - "\t Initial delay for key-repeat in ms\n" - "\t --xkb-repeat-rate <msecs> [50]\n" - "\t Delay between two key-repeats in ms\n", - "wlterm"); - /* - * 80 char line: - * | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | - * "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" - * 80 char line starting with tab: - * |10| 20 | 30 | 40 | 50 | 60 | 70 | 80 | - * "\t901234567890123456789012345678901234567890123456789012345678901234567890\n" - */ -} - -static int aftercheck_debug(struct conf_option *opt, int argc, char **argv, - int idx) -{ - struct wlt_conf_t *conf = WLT_CONF_FROM_FIELD(opt->mem, debug); - - /* --debug implies --verbose */ - if (conf->debug) - conf->verbose = true; - - return 0; -} - -static int aftercheck_help(struct conf_option *opt, int argc, char **argv, - int idx) -{ - struct wlt_conf_t *conf = WLT_CONF_FROM_FIELD(opt->mem, help); - - /* exit after printing --help information */ - if (conf->help) { - print_help(); - conf->exit = true; - } - - return 0; -} - -static char *def_argv[] = { NULL, "-i", NULL }; - -static int aftercheck_login(struct conf_option *opt, int argc, char **argv, - int idx) -{ - struct wlt_conf_t *conf = WLT_CONF_FROM_FIELD(opt->mem, login); - int ret; - - if (!argv) - return 0; - - /* parse "--login [...] -- args" arguments */ - if (argv && conf->login) { - if (idx >= argc) { - fprintf(stderr, "Arguments for --login missing\n"); - return -EFAULT; - } - - conf->argv = &argv[idx]; - ret = argc - idx; - } else if (!conf->argv) { - def_argv[0] = getenv("SHELL") ? : _PATH_BSHELL; - conf->argv = def_argv; - ret = 0; - } else { - ret = 0; - } - - return ret; -} - -static int copy_login(struct conf_option *opt, const struct conf_option *src) -{ - struct wlt_conf_t *conf = WLT_CONF_FROM_FIELD(opt->mem, login); - struct wlt_conf_t *s = WLT_CONF_FROM_FIELD(src->mem, login); - int ret; - char **t; - - ret = shl_dup_array(&t, s->argv); - if (ret) - return ret; - - free(conf->argv); - conf->argv = t; - - return 0; -} - -static struct conf_grab def_grab_scroll_up = - CONF_SINGLE_GRAB(SHL_SHIFT_MASK, XKB_KEY_Up); - -static struct conf_grab def_grab_scroll_down = - CONF_SINGLE_GRAB(SHL_SHIFT_MASK, XKB_KEY_Down); - -static struct conf_grab def_grab_page_up = - CONF_SINGLE_GRAB(SHL_SHIFT_MASK, XKB_KEY_Prior); - -static struct conf_grab def_grab_page_down = - CONF_SINGLE_GRAB(SHL_SHIFT_MASK, XKB_KEY_Next); - -static struct conf_grab def_grab_fullscreen = - CONF_SINGLE_GRAB(0, XKB_KEY_F11); - -static struct conf_grab def_grab_zoom_in = - CONF_SINGLE_GRAB(SHL_CONTROL_MASK, XKB_KEY_plus); - -static struct conf_grab def_grab_zoom_out = - CONF_SINGLE_GRAB(SHL_CONTROL_MASK, XKB_KEY_minus); - -static struct conf_grab def_grab_copy = - CONF_SINGLE_GRAB(SHL_LOGO_MASK, XKB_KEY_c); - -static struct conf_grab def_grab_paste = - CONF_SINGLE_GRAB(SHL_LOGO_MASK, XKB_KEY_v); - -struct conf_option options[] = { - CONF_OPTION_BOOL_FULL('h', "help", aftercheck_help, NULL, NULL, &wlt_conf.help, false), - CONF_OPTION_BOOL('v', "verbose", &wlt_conf.verbose, false), - CONF_OPTION_BOOL_FULL(0, "debug", aftercheck_debug, NULL, NULL, &wlt_conf.debug, false), - CONF_OPTION_BOOL(0, "silent", &wlt_conf.silent, false), - - CONF_OPTION_BOOL_FULL('l', "login", aftercheck_login, copy_login, NULL, &wlt_conf.login, false), - CONF_OPTION_STRING('t', "term", &wlt_conf.term, "xterm-256color"), - CONF_OPTION_STRING(0, "palette", &wlt_conf.palette, NULL), - CONF_OPTION_UINT(0, "sb-size", &wlt_conf.sb_size, 1000), - - CONF_OPTION_GRAB(0, "grab-scroll-up", &wlt_conf.grab_scroll_up, &def_grab_scroll_up), - CONF_OPTION_GRAB(0, "grab-scroll-down", &wlt_conf.grab_scroll_down, &def_grab_scroll_down), - CONF_OPTION_GRAB(0, "grab-page-up", &wlt_conf.grab_page_up, &def_grab_page_up), - CONF_OPTION_GRAB(0, "grab-page-down", &wlt_conf.grab_page_down, &def_grab_page_down), - CONF_OPTION_GRAB(0, "grab-fullscreen", &wlt_conf.grab_fullscreen, &def_grab_fullscreen), - CONF_OPTION_GRAB(0, "grab-zoom-in", &wlt_conf.grab_zoom_in, &def_grab_zoom_in), - CONF_OPTION_GRAB(0, "grab-zoom-out", &wlt_conf.grab_zoom_out, &def_grab_zoom_out), - CONF_OPTION_GRAB(0, "grab-copy", &wlt_conf.grab_copy, &def_grab_copy), - CONF_OPTION_GRAB(0, "grab-paste", &wlt_conf.grab_paste, &def_grab_paste), - - CONF_OPTION_STRING(0, "font-engine", &wlt_conf.font_engine, "pango"), - CONF_OPTION_UINT(0, "font-size", &wlt_conf.font_size, 12), - CONF_OPTION_STRING(0, "font-name", &wlt_conf.font_name, "monospace"), - CONF_OPTION_UINT(0, "font-dpi", &wlt_conf.font_ppi, 96), - - CONF_OPTION_UINT(0, "xkb-repeat-delay", &wlt_conf.xkb_repeat_delay, 250), - CONF_OPTION_UINT(0, "xkb-repeat-rate", &wlt_conf.xkb_repeat_rate, 50), -}; - -int main(int argc, char **argv) -{ - int ret; - struct wlt_app app; - struct conf_ctx *conf; - - ret = conf_ctx_new(&conf, options, sizeof(options) / sizeof(*options), - &wlt_conf); - if (ret) - goto err_out; - - ret = conf_ctx_parse_argv(conf, argc, argv); - if (ret) - goto err_conf; - - if (wlt_conf.exit) { - conf_ctx_free(conf); - return EXIT_SUCCESS; - } - - if (!wlt_conf.debug && !wlt_conf.verbose && wlt_conf.silent) - log_set_config(&LOG_CONFIG_WARNING(0, 0, 0, 0)); - else - log_set_config(&LOG_CONFIG_INFO(wlt_conf.debug, - wlt_conf.verbose)); - - log_print_init("wlterm"); - - kmscon_font_register(&kmscon_font_8x16_ops); - kmscon_font_register(&kmscon_font_pango_ops); - - memset(&app, 0, sizeof(app)); - ret = setup_app(&app); - if (ret) - goto err_unload; - - ev_eloop_run(app.eloop, -1); - - destroy_app(&app); - kmscon_font_unregister(kmscon_font_pango_ops.name); - kmscon_font_unregister(kmscon_font_8x16_ops.name); - conf_ctx_free(conf); - log_info("exiting"); - - return EXIT_SUCCESS; - -err_unload: - kmscon_font_unregister(kmscon_font_pango_ops.name); - kmscon_font_unregister(kmscon_font_8x16_ops.name); -err_conf: - conf_ctx_free(conf); -err_out: - log_err("cannot initialize wlterm, errno %d: %s", ret, strerror(-ret)); - return -ret; -} diff --git a/src/wlt_main.h b/src/wlt_main.h deleted file mode 100644 index e450658..0000000 --- a/src/wlt_main.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * wlt - Main Header - * - * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Wayland Terminal global information and state - */ - -#ifndef WLT_MAIN_H -#define WLT_MAIN_H - -#include <stdbool.h> -#include <stdlib.h> -#include "conf.h" - -struct wlt_conf_t { - /* show help/usage information */ - bool help; - /* exit application after parsing options */ - bool exit; - /* enable debug messages */ - bool debug; - /* enable verbose info messages */ - bool verbose; - /* disable notices and warnings */ - bool silent; - - /* custom login process */ - bool login; - /* argv for login process */ - char **argv; - /* TERM value */ - char *term; - /* color palette */ - char *palette; - /* terminal scroll-back buffer size */ - unsigned int sb_size; - - /* scroll-up grab */ - struct conf_grab *grab_scroll_up; - /* scroll-down grab */ - struct conf_grab *grab_scroll_down; - /* page-up grab */ - struct conf_grab *grab_page_up; - /* page-down grab */ - struct conf_grab *grab_page_down; - /* fullscreen grab */ - struct conf_grab *grab_fullscreen; - /* font-zoom-in grab */ - struct conf_grab *grab_zoom_in; - /* font-zoom-out grab */ - struct conf_grab *grab_zoom_out; - /* copy grab */ - struct conf_grab *grab_copy; - /* paste grab */ - struct conf_grab *grab_paste; - - /* font engine */ - char *font_engine; - /* font size */ - unsigned int font_size; - /* font name */ - char *font_name; - /* font ppi (overrides per monitor PPI) */ - unsigned int font_ppi; - - /* xkb key repeat delay */ - unsigned int xkb_repeat_delay; - /* xkb key repeat rate */ - unsigned int xkb_repeat_rate; -}; - -extern struct wlt_conf_t wlt_conf; - -#endif /* WLT_MAIN_H */ diff --git a/src/wlt_terminal.c b/src/wlt_terminal.c deleted file mode 100644 index f90f574..0000000 --- a/src/wlt_terminal.c +++ /dev/null @@ -1,808 +0,0 @@ -/* - * wlt - Terminals - * - * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Wayland Terminal console helpers - */ - -#include <errno.h> -#include <linux/input.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <wayland-client.h> -#include <xkbcommon/xkbcommon.h> -#include "conf.h" -#include "eloop.h" -#include "font.h" -#include "pty.h" -#include "shl_log.h" -#include "shl_misc.h" -#include "tsm_unicode.h" -#include "tsm_screen.h" -#include "tsm_vte.h" -#include "uterm_video.h" -#include "wlt_main.h" -#include "wlt_terminal.h" -#include "wlt_toolkit.h" - -#define LOG_SUBSYSTEM "wlt_terminal" - -struct wlt_terminal { - struct ev_eloop *eloop; - struct wlt_window *wnd; - struct wlt_display *disp; - struct wlt_widget *widget; - struct wlt_shm_buffer buffer; - struct wlt_rect alloc; - - struct tsm_screen *scr; - struct tsm_vte *vte; - struct kmscon_pty *pty; - struct ev_fd *pty_fd; - bool pty_open; - - struct kmscon_font_attr font_attr; - struct kmscon_font *font_normal; - unsigned int cols; - unsigned int rows; - - wlt_terminal_cb cb; - void *data; - - int pointer_x; - int pointer_y; - bool in_selection; - bool selection_started; - int sel_start_x; - int sel_start_y; - - int paste_fd; - struct ev_fd *paste; - struct wl_data_source *copy; - char *copy_buf; - int copy_len; -}; - -static int draw_cell(struct tsm_screen *scr, - uint32_t id, const uint32_t *ch, size_t len, - unsigned int chwidth, - unsigned int posx, unsigned int posy, - const struct tsm_screen_attr *attr, void *data) -{ - struct wlt_terminal *term = data; - const struct kmscon_glyph *glyph; - int ret; - unsigned int x, y, tmp, width, height, i, r, g, b; - uint8_t *dst, *src; - const struct uterm_video_buffer *buf; - unsigned int fr, fg, fb, br, bg, bb; - uint32_t val; - - if (!chwidth) - return 0; - - if (!len) - ret = kmscon_font_render_empty(term->font_normal, &glyph); - else - ret = kmscon_font_render(term->font_normal, id, ch, len, - &glyph); - - if (ret) { - ret = kmscon_font_render_inval(term->font_normal, &glyph); - if (ret) - return ret; - } - - buf = &glyph->buf; - x = posx * term->font_normal->attr.width; - y = posy * term->font_normal->attr.height; - - if (attr->inverse) { - fr = attr->br; - fg = attr->bg; - fb = attr->bb; - br = attr->fr; - bg = attr->fg; - bb = attr->fb; - } else { - fr = attr->fr; - fg = attr->fg; - fb = attr->fb; - br = attr->br; - bg = attr->bg; - bb = attr->bb; - } - - tmp = x + buf->width; - if (tmp < x || x >= term->buffer.width) - return 0; - if (tmp > term->buffer.width) - width = term->buffer.width - x; - else - width = buf->width; - - tmp = y + buf->height; - if (tmp < y || y >= term->buffer.height) - return 0; - if (tmp > term->buffer.height) - height = term->buffer.height - y; - else - height = buf->height; - - dst = term->buffer.data; - dst = &dst[y * term->buffer.stride + x * 4]; - src = buf->data; - - /* Division by 256 instead of 255 increases - * speed by like 20% on slower machines. - * Downside is, full white is 254/254/254 - * instead of 255/255/255. */ - while (height--) { - for (i = 0; i < width; ++i) { - if (src[i] == 0) { - r = br; - g = bg; - b = bb; - } else if (src[i] == 255) { - r = fr; - g = fg; - b = fb; - } else { - r = fr * src[i] + - br * (255 - src[i]); - r /= 256; - g = fg * src[i] + - bg * (255 - src[i]); - g /= 256; - b = fb * src[i] + - bb * (255 - src[i]); - b /= 256; - } - val = (0xff << 24) | (r << 16) | (g << 8) | b; - ((uint32_t*)dst)[i] = val; - } - dst += term->buffer.stride; - src += buf->stride; - } - - return 0; -} - -static void draw_background(struct wlt_terminal *term) -{ - uint8_t *dst; - uint32_t *line; - unsigned int i, j, w, h; - - /* when maximized, we might have a right and bottom border. So draw - * a black background for everything beyond grid-size. - * TODO: we should catch the color from tsm_screen instead of using - * black background by default. */ - w = term->buffer.width; - w /= term->font_normal->attr.width; - w *= term->font_normal->attr.width; - - h = term->buffer.height; - h /= term->font_normal->attr.height; - h *= term->font_normal->attr.height; - - dst = term->buffer.data; - for (i = 0; i < term->buffer.height; ++i) { - line = (uint32_t*)dst; - if (i >= h) - j = 0; - else - j = w; - for ( ; j < term->buffer.width; ++j) - line[j] = 0xff << 24; - dst += term->buffer.stride; - } -} - -static void widget_redraw(struct wlt_widget *widget, unsigned int flags, - void *data) -{ - struct wlt_terminal *term = data; - - draw_background(term); - tsm_screen_draw(term->scr, NULL, draw_cell, NULL, term); -} - -static void widget_resize(struct wlt_widget *widget, unsigned int flags, - struct wlt_rect *alloc, void *data) -{ - struct wlt_terminal *term = data; - int ret; - - wlt_window_get_buffer(term->wnd, alloc, &term->buffer); - memcpy(&term->alloc, alloc, sizeof(*alloc)); - - /* don't allow children */ - alloc->width = 0; - alloc->height = 0; - - term->cols = term->buffer.width / term->font_normal->attr.width; - if (term->cols < 1) - term->cols = 1; - term->rows = term->buffer.height / term->font_normal->attr.height; - if (term->rows < 1) - term->rows = 1; - - ret = tsm_screen_resize(term->scr, term->cols, term->rows); - if (ret) - log_error("cannot resize TSM screen: %d", ret); - kmscon_pty_resize(term->pty, term->cols, term->rows); -} - -static void widget_prepare_resize(struct wlt_widget *widget, - unsigned int flags, - unsigned int width, unsigned int height, - unsigned int *min_width, - unsigned int *min_height, - unsigned int *new_width, - unsigned int *new_height, - void *data) -{ - struct wlt_terminal *term = data; - unsigned int w, h; - - /* We are a catch-all handler. That is, we use all space that is - * available. We must be called _last_, which is guaranteed by - * registering the widget as last widget. - * All previous handlers put their size constraints into the arguments - * and we need to make sure to not break them. - * Every redraw-handler is guaranteed to work for every size, but still, - * we should try to avoid invalid-sizes to not generate artifacts. */ - - if (flags & WLT_WINDOW_MAXIMIZED || - flags & WLT_WINDOW_FULLSCREEN) { - /* if maximized, always use requested size */ - *new_width = width; - *new_height = height; - } else { - /* In normal mode, we want the console to "snap" to grid-sizes. - * That is, resizing is in steps instead of smooth. To guarantee - * that, we use the font-width/height and try to make the - * console as big as possible to fit the needed size. - * However, we also must make sure the minimal size is always - * guaranteed. */ - - if (*new_width >= width) { - *new_width += term->font_normal->attr.width; - } else { - w = width - *new_width; - w /= term->font_normal->attr.width; - if (!w) - w = 1; - w *= term->font_normal->attr.width; - *new_width += w; - } - - if (*new_width < *min_width) { - w = *min_width - *new_width; - w /= term->font_normal->attr.width; - w += 1; - w *= term->font_normal->attr.width; - *new_width += w; - } - - if (*new_height >= height) { - *new_height += term->font_normal->attr.height; - } else { - h = height - *new_height; - h /= term->font_normal->attr.height; - if (!h) - h = 1; - h *= term->font_normal->attr.height; - *new_height += h; - } - - if (*new_height < *min_height) { - h = *min_height - *new_height; - h /= term->font_normal->attr.height; - h += 1; - h *= term->font_normal->attr.height; - *new_height += h; - } - } -} - -static void paste_event(struct ev_fd *fd, int mask, void *data) -{ - struct wlt_terminal *term = data; - char buf[4096]; - int ret; - - if (mask & EV_READABLE) { - ret = read(term->paste_fd, buf, sizeof(buf)); - if (ret == 0) { - goto err_close; - } else if (ret < 0) { - if (errno == EAGAIN) - return; - log_error("error on paste-fd (%d): %m", errno); - goto err_close; - } - - kmscon_pty_write(term->pty, buf, ret); - return; - } - - if (mask & EV_ERR) { - log_error("error on paste FD"); - goto err_close; - } - - if (mask & EV_HUP) - goto err_close; - - return; - -err_close: - close(term->paste_fd); - ev_eloop_rm_fd(term->paste); - term->paste = NULL; -} - -static void copy_target(void *data, struct wl_data_source *w_source, - const char *target) -{ -} - -static void copy_send(void *data, struct wl_data_source *w_source, - const char *mime, int32_t fd) -{ - struct wlt_terminal *term = data; - int ret; - - /* TODO: make this non-blocking */ - ret = write(fd, term->copy_buf, term->copy_len); - if (ret != term->copy_len) - log_warning("cannot write whole selection: %d/%d", ret, - term->copy_len); - close(fd); -} - -static void copy_cancelled(void *data, struct wl_data_source *w_source) -{ - struct wlt_terminal *term = data; - - wl_data_source_destroy(w_source); - if (term->copy == w_source) - term->copy = NULL; -} - -static const struct wl_data_source_listener copy_listener = { - .target = copy_target, - .send = copy_send, - .cancelled = copy_cancelled, -}; - -static bool widget_key(struct wlt_widget *widget, unsigned int mask, - uint32_t sym, uint32_t ascii, uint32_t state, - bool handled, void *data) -{ - struct wlt_terminal *term = data; - uint32_t ucs4; - struct kmscon_font *font; - int ret; - - if (handled || state != WL_KEYBOARD_KEY_STATE_PRESSED) - return false; - - ucs4 = xkb_keysym_to_utf32(sym) ? : TSM_VTE_INVALID; - - if (conf_grab_matches(wlt_conf.grab_scroll_up, - mask, 1, &sym)) { - tsm_screen_sb_up(term->scr, 1); - wlt_window_schedule_redraw(term->wnd); - return true; - } - if (conf_grab_matches(wlt_conf.grab_scroll_down, - mask, 1, &sym)) { - tsm_screen_sb_down(term->scr, 1); - wlt_window_schedule_redraw(term->wnd); - return true; - } - if (conf_grab_matches(wlt_conf.grab_page_up, - mask, 1, &sym)) { - tsm_screen_sb_page_up(term->scr, 1); - wlt_window_schedule_redraw(term->wnd); - return true; - } - if (conf_grab_matches(wlt_conf.grab_page_down, - mask, 1, &sym)) { - tsm_screen_sb_page_down(term->scr, 1); - wlt_window_schedule_redraw(term->wnd); - return true; - } - - if (conf_grab_matches(wlt_conf.grab_zoom_in, - mask, 1, &sym)) { - if (term->font_attr.points + 1 < term->font_attr.points) - return true; - - ++term->font_attr.points; - ret = kmscon_font_find(&font, &term->font_attr, - wlt_conf.font_engine); - if (ret) { - --term->font_attr.points; - log_error("cannot create font"); - } else { - kmscon_font_unref(term->font_normal); - term->font_normal = font; - wlt_window_schedule_redraw(term->wnd); - } - return true; - } - if (conf_grab_matches(wlt_conf.grab_zoom_out, - mask, 1, &sym)) { - if (term->font_attr.points - 1 < 1) - return true; - - --term->font_attr.points; - ret = kmscon_font_find(&font, &term->font_attr, - wlt_conf.font_engine); - if (ret) { - ++term->font_attr.points; - log_error("cannot create font"); - } else { - kmscon_font_unref(term->font_normal); - term->font_normal = font; - wlt_window_schedule_redraw(term->wnd); - } - return true; - } - - if (conf_grab_matches(wlt_conf.grab_paste, - mask, 1, &sym)) { - if (term->paste) { - log_debug("cannot paste selection, previous paste still in progress"); - return true; - } - - ret = wlt_display_get_selection_fd(term->disp, - "text/plain;charset=utf-8"); - if (ret == -ENOENT) { - log_debug("no selection to paste"); - return true; - } else if (ret == -EAGAIN) { - log_debug("unknown mime-time for pasting selection"); - return true; - } else if (ret < 0) { - log_error("cannot paste selection: %d", ret); - return true; - } - - term->paste_fd = ret; - ret = ev_eloop_new_fd(term->eloop, &term->paste, ret, - EV_READABLE, paste_event, term); - if (ret) { - close(ret); - log_error("cannot create eloop fd: %d", ret); - return true; - } - - return true; - } - - if (conf_grab_matches(wlt_conf.grab_copy, - mask, 1, &sym)) { - if (term->copy) { - wl_data_source_destroy(term->copy); - free(term->copy_buf); - term->copy = NULL; - } - - ret = wlt_display_new_data_source(term->disp, &term->copy); - if (ret) { - log_error("cannot create data source"); - return true; - } - - term->copy_len = tsm_screen_selection_copy(term->scr, - &term->copy_buf); - if (term->copy_len < 0) { - if (term->copy_len != -ENOENT) - log_error("cannot copy TSM selection: %d", - term->copy_len); - wl_data_source_destroy(term->copy); - term->copy = NULL; - return true; - } - - wl_data_source_offer(term->copy, "text/plain;charset=utf-8"); - wl_data_source_add_listener(term->copy, ©_listener, term); - wlt_display_set_selection(term->disp, term->copy); - - return true; - } - - if (tsm_vte_handle_keyboard(term->vte, sym, ascii, mask, ucs4)) { - tsm_screen_sb_reset(term->scr); - wlt_window_schedule_redraw(term->wnd); - return true; - } - - return false; -} - -static void pointer_motion(struct wlt_widget *widget, - unsigned int x, unsigned int y, void *data) -{ - struct wlt_terminal *term = data; - unsigned int posx, posy; - - if (!wlt_rect_contains(&term->alloc, x, y)) { - term->pointer_x = -1; - term->pointer_y = -1; - return; - } else if (term->pointer_x == x - term->alloc.x && - term->pointer_y == y - term->alloc.y) { - return; - } else { - term->pointer_x = x - term->alloc.x; - term->pointer_y = y - term->alloc.y; - } - - if (term->in_selection) { - if (!term->selection_started) { - term->selection_started = true; - posx = term->sel_start_x / term->font_normal->attr.width; - posy = term->sel_start_y / term->font_normal->attr.height; - - tsm_screen_selection_start(term->scr, posx, posy); - } else { - posx = term->pointer_x / term->font_normal->attr.width; - posy = term->pointer_y / term->font_normal->attr.height; - - tsm_screen_selection_target(term->scr, posx, posy); - } - - wlt_window_schedule_redraw(term->wnd); - } -} - -static void pointer_enter(struct wlt_widget *widget, - unsigned int x, unsigned int y, void *data) -{ - struct wlt_terminal *term = data; - - pointer_motion(widget, x, y, term); -} - -static void pointer_leave(struct wlt_widget *widget, void *data) -{ - struct wlt_terminal *term = data; - - term->pointer_x = -1; - term->pointer_y = -1; -} - -static void pointer_button(struct wlt_widget *widget, - uint32_t button, uint32_t state, void *data) -{ - struct wlt_terminal *term = data; - - if (button != BTN_LEFT) - return; - - if (state == WL_POINTER_BUTTON_STATE_PRESSED) { - if (!term->in_selection && - term->pointer_x >= 0 && term->pointer_y >= 0) { - term->in_selection = true; - term->selection_started = false; - - term->sel_start_x = term->pointer_x; - term->sel_start_y = term->pointer_y; - } - } else { - if (term->pointer_x == term->sel_start_x && - term->pointer_y == term->sel_start_y) { - tsm_screen_selection_reset(term->scr); - wlt_window_schedule_redraw(term->wnd); - } - - term->in_selection = false; - } -} - -static void vte_event(struct tsm_vte *vte, const char *u8, size_t len, - void *data) -{ - struct wlt_terminal *term = data; - - kmscon_pty_write(term->pty, u8, len); -} - -static void pty_input(struct kmscon_pty *pty, const char *u8, size_t len, - void *data) -{ - struct wlt_terminal *term = data; - - if (!len) { - term->pty_open = false; - if (term->cb) - term->cb(term, WLT_TERMINAL_HUP, term->data); - } else { - tsm_vte_input(term->vte, u8, len); - wlt_window_schedule_redraw(term->wnd); - } -} - -static void pty_event(struct ev_fd *fd, int mask, void *data) -{ - struct wlt_terminal *term = data; - - kmscon_pty_dispatch(term->pty); -} - -static void widget_destroy(struct wlt_widget *widget, void *data) -{ - struct wlt_terminal *term = data; - - if (term->paste) { - ev_eloop_rm_fd(term->paste); - close(term->paste_fd); - } - tsm_vte_unref(term->vte); - tsm_screen_unref(term->scr); - free(term); -} - -int wlt_terminal_new(struct wlt_terminal **out, struct wlt_window *wnd) -{ - struct wlt_terminal *term; - int ret; - - if (!out || !wnd) - return -EINVAL; - - term = malloc(sizeof(*term)); - if (!term) - return -ENOMEM; - memset(term, 0, sizeof(*term)); - term->wnd = wnd; - term->disp = wlt_window_get_display(wnd); - term->eloop = wlt_window_get_eloop(wnd); - term->cols = 80; - term->rows = 24; - - term->font_attr.ppi = wlt_conf.font_ppi; - term->font_attr.points = wlt_conf.font_size; - term->font_attr.bold = false; - term->font_attr.italic = false; - term->font_attr.width = 0; - term->font_attr.height = 0; - strncpy(term->font_attr.name, wlt_conf.font_name, - KMSCON_FONT_MAX_NAME - 1); - term->font_attr.name[KMSCON_FONT_MAX_NAME - 1] = 0; - - ret = kmscon_font_find(&term->font_normal, &term->font_attr, - wlt_conf.font_engine); - if (ret) { - log_error("cannot create font"); - goto err_free; - } - - ret = tsm_screen_new(&term->scr, log_llog, NULL); - if (ret) { - log_error("cannot create tsm-screen object"); - goto err_font; - } - tsm_screen_set_max_sb(term->scr, wlt_conf.sb_size); - - ret = tsm_vte_new(&term->vte, term->scr, vte_event, term, log_llog, - NULL); - if (ret) { - log_error("cannot create tsm-vte object"); - goto err_scr; - } - tsm_vte_set_palette(term->vte, wlt_conf.palette); - - ret = kmscon_pty_new(&term->pty, pty_input, term); - if (ret) { - log_error("cannot create pty object"); - goto err_vte; - } - kmscon_pty_set_term(term->pty, "xterm-256color"); - - ret = kmscon_pty_set_term(term->pty, wlt_conf.term); - if (ret) - goto err_pty; - - ret = kmscon_pty_set_argv(term->pty, wlt_conf.argv); - if (ret) - goto err_pty; - - ret = ev_eloop_new_fd(term->eloop, &term->pty_fd, - kmscon_pty_get_fd(term->pty), - EV_READABLE, pty_event, term); - if (ret) - goto err_pty; - - ret = wlt_window_create_widget(wnd, &term->widget, term); - if (ret) { - log_error("cannot create terminal widget"); - goto err_pty_fd; - } - - wlt_widget_set_destroy_cb(term->widget, widget_destroy); - wlt_widget_set_redraw_cb(term->widget, widget_redraw); - wlt_widget_set_resize_cb(term->widget, widget_prepare_resize, - widget_resize); - wlt_widget_set_keyboard_cb(term->widget, widget_key); - wlt_widget_set_pointer_cb(term->widget, pointer_enter, pointer_leave, - pointer_motion, pointer_button); - *out = term; - return 0; - -err_pty_fd: - ev_eloop_rm_fd(term->pty_fd); -err_pty: - kmscon_pty_unref(term->pty); -err_vte: - tsm_vte_unref(term->vte); -err_scr: - tsm_screen_unref(term->scr); -err_font: - kmscon_font_unref(term->font_normal); -err_free: - free(term); - return ret; -} - -void wlt_terminal_destroy(struct wlt_terminal *term) -{ - if (!term) - return; - - wlt_widget_destroy(term->widget); -} - -int wlt_terminal_open(struct wlt_terminal *term, wlt_terminal_cb cb, - void *data) -{ - int ret; - - if (!term) - return -EINVAL; - - if (term->pty_open) - return -EALREADY; - - term->cb = cb; - term->data = data; - - kmscon_pty_close(term->pty); - ret = kmscon_pty_open(term->pty, term->cols, term->rows); - if (ret) - return ret; - - term->pty_open = true; - return 0; -} diff --git a/src/wlt_terminal.h b/src/wlt_terminal.h deleted file mode 100644 index 0016414..0000000 --- a/src/wlt_terminal.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * wlt - Terminals - * - * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Wayland Terminal console helpers - */ - -#ifndef WLT_TERMINAL_H -#define WLT_TERMINAL_H - -#include <stdlib.h> -#include "wlt_toolkit.h" - -struct wlt_terminal; - -enum wlt_terminal_event_type { - WLT_TERMINAL_HUP, -}; - -typedef void (*wlt_terminal_cb) (struct wlt_terminal *term, - unsigned int event, - void *data); - -int wlt_terminal_new(struct wlt_terminal **out, struct wlt_window *wnd); -void wlt_terminal_destroy(struct wlt_terminal *term); - -int wlt_terminal_open(struct wlt_terminal *term, wlt_terminal_cb cb, - void *data); - -#endif /* WLT_TERMINAL_H */ diff --git a/src/wlt_theme.c b/src/wlt_theme.c deleted file mode 100644 index 863746a..0000000 --- a/src/wlt_theme.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * wlt - Theme Helper - * - * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Wayland Terminal theme/decoration drawing helper - */ - -#include <errno.h> -#include <linux/input.h> -#include <stdlib.h> -#include <string.h> -#include <wayland-client.h> -#include "shl_log.h" -#include "shl_misc.h" -#include "wlt_main.h" -#include "wlt_theme.h" -#include "wlt_toolkit.h" - -#define LOG_SUBSYSTEM "wlt_theme" - -enum theme_location { - LOC_NOWHERE, - LOC_SOMEWHERE, - LOC_RESIZE_TOP, - LOC_RESIZE_BOTTOM, - LOC_RESIZE_LEFT, - LOC_RESIZE_RIGHT, - LOC_RESIZE_TOP_LEFT, - LOC_RESIZE_TOP_RIGHT, - LOC_RESIZE_BOTTOM_LEFT, - LOC_RESIZE_BOTTOM_RIGHT, - LOC_CONTROL, - LOC_MINIMIZE, - LOC_MAXIMIZE, - LOC_CLOSE, -}; - -struct wlt_theme { - struct wlt_window *wnd; - struct wlt_widget *widget; - struct wlt_shm_buffer buffer; - struct wlt_rect alloc; - unsigned int control_height; - unsigned int frame_width; - unsigned int resize_margin; - unsigned int button_size; - unsigned int button_padding; - unsigned int button_margin; - - unsigned int pointer_x; - unsigned int pointer_y; - unsigned int pointer_loc; - bool pointer_pressed; - unsigned int pointer_grabbed; -}; - -static void draw_control(struct wlt_theme *theme) -{ - uint8_t *dst; - uint32_t *line, backcol; - unsigned int i, j; - unsigned int b1off, b2off, b3off; - - /* background */ - if (theme->pointer_loc == LOC_NOWHERE) - backcol = (0x60 << 24) | (0xaa << 16) | - (0xaa << 8) | 0xaa; - else - backcol = (0x20 << 24) | (0xee << 16) | - (0xee << 8) | 0xee; - dst = theme->buffer.data; - for (i = 0; i < theme->control_height; ++i) { - line = (uint32_t*)dst; - for (j = 0; j < theme->buffer.width; ++j) { - if (i == 0 || i == theme->control_height - 1 || - j == 0 || j == theme->buffer.width - 1) - line[j] = 0xff << 24; - else - line[j] = backcol; - } - dst += theme->buffer.stride; - } - - /* buttons */ - b1off = theme->buffer.width - theme->button_margin - theme->button_size; - b2off = b1off - theme->button_padding - theme->button_size; - b3off = b2off - theme->button_padding - theme->button_size; - dst = theme->buffer.data + theme->buffer.stride * theme->button_margin; - for (i = 0; i < theme->button_size; ++i) { - line = (uint32_t*)dst; - for (j = 0; j < theme->buffer.width; ++j) { - if (j >= b1off && - j < b1off + theme->button_size) { - if (i == 0 || - i == theme->button_size - 1 || - j == b1off || - j == b1off + theme->button_size - 1) - line[j] = 0xff << 24; - else if (theme->pointer_loc == LOC_CLOSE && - theme->pointer_pressed && - theme->pointer_grabbed == LOC_CLOSE) - line[j] = (0xff << 24) | 0x1f1f1f1f; - else if (theme->pointer_loc == LOC_CLOSE && - !theme->pointer_pressed) - line[j] = 0xffffffff; - else - line[j] = (0xff << 24) | 0x33333333; - } else if (j >= b2off && - j < b2off + theme->button_size) { - if (i == 0 || - i == theme->button_size - 1 || - j == b2off || - j == b2off + theme->button_size - 1) - line[j] = 0xff << 24; - else if (theme->pointer_loc == LOC_MAXIMIZE && - theme->pointer_pressed && - theme->pointer_grabbed == LOC_MAXIMIZE) - line[j] = (0xff << 24) | 0x1f1f1f1f; - else if (theme->pointer_loc == LOC_MAXIMIZE && - !theme->pointer_pressed) - line[j] = 0xffffffff; - else - line[j] = (0xff << 24) | 0x66666666; - } else if (j >= b3off && - j < b3off + theme->button_size) { - if (i == 0 || - i == theme->button_size - 1 || - j == b3off || - j == b3off + theme->button_size - 1) - line[j] = 0xff << 24; - else if (theme->pointer_loc == LOC_MINIMIZE && - theme->pointer_pressed && - theme->pointer_grabbed == LOC_MINIMIZE) - line[j] = (0xff << 24) | 0x1f1f1f1f; - else if (theme->pointer_loc == LOC_MINIMIZE && - !theme->pointer_pressed) - line[j] = 0xffffffff; - else - line[j] = (0xff << 24) | 0xaaaaaaaa; - } - } - dst += theme->buffer.stride; - } -} - -static void draw_frame(struct wlt_theme *theme) -{ - uint8_t *dst; - uint32_t *line, col; - unsigned int i, j, height; - - col = (0x60 << 24) | (0xaa << 16) | (0xaa << 8) | 0xaa; - - /* top frame */ - dst = theme->buffer.data + theme->buffer.stride * - theme->control_height; - for (i = 0; i < theme->frame_width; ++i) { - line = (uint32_t*)dst; - for (j = 0; j < theme->buffer.width; ++j) { - if (!j || j + 1 == theme->buffer.width) - line[j] = 0xff << 24; - else - line[j] = col; - } - dst += theme->buffer.stride; - } - - /* bottom frame */ - dst = theme->buffer.data + theme->buffer.stride * - (theme->buffer.height - theme->frame_width); - for (i = 0; i < theme->frame_width; ++i) { - line = (uint32_t*)dst; - for (j = 0; j < theme->buffer.width; ++j) { - if (!j || j + 1 == theme->buffer.width - || i + 1 == theme->frame_width) - line[j] = 0xff << 24; - else - line[j] = col; - } - dst += theme->buffer.stride; - } - - /* left frame */ - dst = theme->buffer.data + theme->buffer.stride * - (theme->control_height + theme->frame_width); - height = theme->buffer.height - theme->control_height - - theme->frame_width * 2; - for (i = 0; i < height; ++i) { - line = (uint32_t*)dst; - for (j = 0; j < theme->frame_width; ++j) - line[j] = j ? col : (0xff << 24); - dst += theme->buffer.stride; - } - - /* right frame */ - dst = theme->buffer.data + theme->buffer.stride * - (theme->control_height + theme->frame_width); - height = theme->buffer.height - theme->control_height - - theme->frame_width * 2; - for (i = 0; i < height; ++i) { - line = (uint32_t*)dst; - line += theme->buffer.width - theme->frame_width; - for (j = 0; j < theme->frame_width; ++j) { - if (j + 1 == theme->frame_width) - line[j] = 0xff << 24; - else - line[j] = col; - } - dst += theme->buffer.stride; - } -} - -static void widget_draw_fallback(struct wlt_theme *theme) -{ - uint8_t *dst; - uint32_t *line; - unsigned int i, j; - - dst = theme->buffer.data; - for (i = 0; i < theme->buffer.height; ++i) { - line = (uint32_t*)dst; - for (j = 0; j < theme->buffer.width; ++j) { - line[j] = 0xff << 24; - } - dst += theme->buffer.stride; - } -} - -static void widget_redraw(struct wlt_widget *widget, unsigned int flags, - void *data) -{ - struct wlt_theme *theme = data; - unsigned int width, height; - - if (flags & WLT_WINDOW_FULLSCREEN) - return; - - width = theme->buffer.width; - height = theme->buffer.height; - if (width < 2 || - width < 2 * theme->frame_width || - width < 2 * theme->button_margin + 2 * theme->button_padding + - 3 * theme->button_size) { - widget_draw_fallback(theme); - } else if (height < theme->control_height + 2 * theme->frame_width) { - widget_draw_fallback(theme); - } else { - draw_frame(theme); - draw_control(theme); - } -} - -static void widget_prepare_resize(struct wlt_widget *widget, - unsigned int flags, - unsigned int width, unsigned int height, - unsigned int *min_width, - unsigned int *min_height, - unsigned int *new_width, - unsigned int *new_height, - void *data) -{ - struct wlt_theme *theme = data; - unsigned int minw, minh; - - if (flags & WLT_WINDOW_FULLSCREEN) - return; - - /* set minimal size */ - minw = 2 * theme->button_margin + 2 * theme->button_padding + - 3 * theme->button_size + *new_width; - minh = theme->button_size + 2 * theme->button_padding + - 2 * theme->frame_width + *new_height; - if (*min_width < minw) - *min_width = minw; - if (*min_height < minh) - *min_height = minh; - - /* set margin size */ - minw = 2 * theme->frame_width; - minh = theme->control_height + 2 * theme->frame_width; - - *new_width += minw; - *new_height += minh; -} - -static void widget_resize(struct wlt_widget *widget, unsigned int flags, - struct wlt_rect *alloc, void *data) -{ - struct wlt_theme *theme = data; - unsigned int nwidth, nheight; - - wlt_window_get_buffer(theme->wnd, alloc, &theme->buffer); - memcpy(&theme->alloc, alloc, sizeof(*alloc)); - - if (flags & WLT_WINDOW_FULLSCREEN) - return; - - alloc->x = theme->frame_width; - alloc->y = theme->control_height + theme->frame_width; - nwidth = alloc->width - 2 * theme->frame_width; - nheight = alloc->height; - nheight -= (theme->control_height + 2 * theme->frame_width); - - if (nwidth > alloc->width || nheight > alloc->height) { - alloc->width = 0; - alloc->height = 0; - } else { - alloc->width = nwidth; - alloc->height = nheight; - } -} - -static unsigned int get_pointer_location(struct wlt_theme *theme) -{ - unsigned int m = theme->resize_margin; - unsigned int b1off, b2off, b3off; - - if (theme->pointer_y < m) { - if (theme->pointer_x < m) - return LOC_RESIZE_TOP_LEFT; - else if (theme->pointer_x >= theme->buffer.width - m) - return LOC_RESIZE_TOP_RIGHT; - else - return LOC_RESIZE_TOP; - } - - if (theme->pointer_y >= theme->buffer.height - m) { - if (theme->pointer_x < m) - return LOC_RESIZE_BOTTOM_LEFT; - else if (theme->pointer_x >= theme->buffer.width - m) - return LOC_RESIZE_BOTTOM_RIGHT; - else - return LOC_RESIZE_BOTTOM; - } - - if (theme->pointer_x < m) - return LOC_RESIZE_LEFT; - - if (theme->pointer_x >= theme->buffer.width - m) - return LOC_RESIZE_RIGHT; - - if (theme->pointer_y < theme->control_height) { - b1off = theme->buffer.width - theme->button_margin - - theme->button_size; - b2off = b1off - theme->button_padding - theme->button_size; - b3off = b2off - theme->button_padding - theme->button_size; - - if (theme->pointer_y >= theme->button_margin && - theme->pointer_y < theme->control_height - - theme->button_margin) { - if (theme->pointer_x >= b1off && - theme->pointer_x < b1off + theme->button_size) - return LOC_CLOSE; - if (theme->pointer_x >= b2off && - theme->pointer_x < b2off + theme->button_size) - return LOC_MAXIMIZE; - if (theme->pointer_x >= b3off && - theme->pointer_x < b3off + theme->button_size) - return LOC_MINIMIZE; - } - - return LOC_CONTROL; - } - - return LOC_SOMEWHERE; -} - -static void set_pointer_location(struct wlt_theme *theme, unsigned int loc) -{ - if (theme->pointer_loc == loc) - return; - - theme->pointer_loc = loc; - if (loc == LOC_NOWHERE) { - theme->pointer_x = -1; - theme->pointer_y = -1; - } - - wlt_window_schedule_redraw(theme->wnd); -} - -static void widget_pointer_motion(struct wlt_widget *widget, - unsigned int x, unsigned int y, void *data) -{ - struct wlt_theme *theme = data; - - if (!wlt_rect_contains(&theme->alloc, x, y)) { - set_pointer_location(theme, LOC_NOWHERE); - return; - } else { - theme->pointer_x = x - theme->alloc.x; - theme->pointer_y = y - theme->alloc.y; - set_pointer_location(theme, get_pointer_location(theme)); - } - - switch (theme->pointer_loc) { - case LOC_RESIZE_LEFT: - wlt_window_set_cursor(theme->wnd, WLT_CURSOR_LEFT); - break; - case LOC_RESIZE_RIGHT: - wlt_window_set_cursor(theme->wnd, WLT_CURSOR_RIGHT); - break; - case LOC_RESIZE_TOP: - wlt_window_set_cursor(theme->wnd, WLT_CURSOR_TOP); - break; - case LOC_RESIZE_BOTTOM: - wlt_window_set_cursor(theme->wnd, WLT_CURSOR_BOTTOM); - break; - case LOC_RESIZE_TOP_LEFT: - wlt_window_set_cursor(theme->wnd, WLT_CURSOR_TOP_LEFT); - break; - case LOC_RESIZE_TOP_RIGHT: - wlt_window_set_cursor(theme->wnd, WLT_CURSOR_TOP_RIGHT); - break; - case LOC_RESIZE_BOTTOM_LEFT: - wlt_window_set_cursor(theme->wnd, - WLT_CURSOR_BOTTOM_LEFT); - break; - case LOC_RESIZE_BOTTOM_RIGHT: - wlt_window_set_cursor(theme->wnd, - WLT_CURSOR_BOTTOM_RIGHT); - break; - default: - wlt_window_set_cursor(theme->wnd, WLT_CURSOR_LEFT_PTR); - } -} - -static void widget_pointer_enter(struct wlt_widget *widget, - unsigned int x, unsigned int y, void *data) -{ - struct wlt_theme *theme = data; - - widget_pointer_motion(widget, x, y, theme); -} - -static void widget_pointer_leave(struct wlt_widget *widget, void *data) -{ - struct wlt_theme *theme = data; - - if (theme->pointer_pressed) { - theme->pointer_pressed = false; - wlt_window_schedule_redraw(theme->wnd); - } - - set_pointer_location(theme, LOC_NOWHERE); -} - -static void button_action(struct wlt_theme *theme) -{ - if (theme->pointer_grabbed != theme->pointer_loc) - return; - - switch (theme->pointer_loc) { - case LOC_CLOSE: - wlt_window_close(theme->wnd); - break; - case LOC_MAXIMIZE: - wlt_window_toggle_maximize(theme->wnd); - break; - case LOC_MINIMIZE: - break; - } -} - -static void widget_pointer_button(struct wlt_widget *widget, - uint32_t button, uint32_t state, void *data) -{ - struct wlt_theme *theme = data; - - if (button != BTN_LEFT) - return; - - if (state != WL_POINTER_BUTTON_STATE_PRESSED) { - if (theme->pointer_pressed) { - button_action(theme); - theme->pointer_pressed = false; - theme->pointer_grabbed = LOC_NOWHERE; - wlt_window_schedule_redraw(theme->wnd); - } - return; - } - - if (!theme->pointer_pressed) { - theme->pointer_pressed = true; - theme->pointer_grabbed = theme->pointer_loc; - wlt_window_schedule_redraw(theme->wnd); - } - - /* prevent resize/move during fullscreen/maximized */ - if (wlt_window_is_maximized(theme->wnd) || - wlt_window_is_fullscreen(theme->wnd)) - return; - - switch (theme->pointer_loc) { - case LOC_RESIZE_LEFT: - wlt_window_resize(theme->wnd, WL_SHELL_SURFACE_RESIZE_LEFT); - break; - case LOC_RESIZE_RIGHT: - wlt_window_resize(theme->wnd, WL_SHELL_SURFACE_RESIZE_RIGHT); - break; - case LOC_RESIZE_TOP: - wlt_window_resize(theme->wnd, - WL_SHELL_SURFACE_RESIZE_TOP); - break; - case LOC_RESIZE_BOTTOM: - wlt_window_resize(theme->wnd, - WL_SHELL_SURFACE_RESIZE_BOTTOM); - break; - case LOC_RESIZE_TOP_LEFT: - wlt_window_resize(theme->wnd, - WL_SHELL_SURFACE_RESIZE_TOP_LEFT); - break; - case LOC_RESIZE_TOP_RIGHT: - wlt_window_resize(theme->wnd, - WL_SHELL_SURFACE_RESIZE_TOP_RIGHT); - break; - case LOC_RESIZE_BOTTOM_LEFT: - wlt_window_resize(theme->wnd, - WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT); - break; - case LOC_RESIZE_BOTTOM_RIGHT: - wlt_window_resize(theme->wnd, - WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT); - break; - case LOC_CONTROL: - wlt_window_move(theme->wnd); - break; - } -} - -static bool widget_key(struct wlt_widget *widget, unsigned int mask, - uint32_t sym, uint32_t ascii, uint32_t state, - bool handled, void *data) -{ - struct wlt_theme *theme = data; - - if (handled || state != WL_KEYBOARD_KEY_STATE_PRESSED) - return false; - - if (conf_grab_matches(wlt_conf.grab_fullscreen, - mask, 1, &sym)) { - wlt_window_toggle_fullscreen(theme->wnd); - return true; - } - - return false; -} - - -static void widget_destroy(struct wlt_widget *widget, void *data) -{ - struct wlt_theme *theme = data; - - log_debug("destroy theme"); - - free(theme); -} - -int wlt_theme_new(struct wlt_theme **out, struct wlt_window *wnd) -{ - struct wlt_theme *theme; - int ret; - - if (!out || !wnd) - return -EINVAL; - - log_debug("create new theme"); - - theme = malloc(sizeof(*theme)); - if (!theme) - return -ENOMEM; - memset(theme, 0, sizeof(*theme)); - theme->wnd = wnd; - theme->control_height = 25; - theme->frame_width = 5; - theme->resize_margin = 5; - theme->button_size = 15; - theme->button_padding = 3; - theme->button_margin = 5; - theme->pointer_grabbed = LOC_NOWHERE; - set_pointer_location(theme, LOC_NOWHERE); - - ret = wlt_window_create_widget(wnd, &theme->widget, theme); - if (ret) { - log_error("cannot create widget"); - goto err_free; - } - - wlt_widget_set_destroy_cb(theme->widget, widget_destroy); - wlt_widget_set_redraw_cb(theme->widget, widget_redraw); - wlt_widget_set_resize_cb(theme->widget, widget_prepare_resize, - widget_resize); - wlt_widget_set_pointer_cb(theme->widget, widget_pointer_enter, - widget_pointer_leave, widget_pointer_motion, - widget_pointer_button); - wlt_widget_set_keyboard_cb(theme->widget, widget_key); - *out = theme; - return 0; - -err_free: - free(theme); - return ret; -} - -void wlt_theme_destroy(struct wlt_theme *theme) -{ - if (!theme) - return; - - wlt_widget_destroy(theme->widget); -} diff --git a/src/wlt_theme.h b/src/wlt_theme.h deleted file mode 100644 index bcca4c1..0000000 --- a/src/wlt_theme.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * wlt - Theme Helper - * - * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Wayland Terminal theme/decoration drawing helper - */ - -#ifndef WLT_THEME_H -#define WLT_THEME_H - -#include <stdlib.h> -#include "wlt_toolkit.h" - -struct wlt_theme; - -int wlt_theme_new(struct wlt_theme **out, struct wlt_window *wnd); -void wlt_theme_destroy(struct wlt_theme *theme); - -#endif /* WLT_THEME_H */ diff --git a/src/wlt_toolkit.c b/src/wlt_toolkit.c deleted file mode 100644 index ef036dd..0000000 --- a/src/wlt_toolkit.c +++ /dev/null @@ -1,1940 +0,0 @@ -/* - * wlt - Toolkit Helper - * - * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Wayland Terminal toolkit helpers - */ - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> -#include <unistd.h> -#include <wayland-client.h> -#include <wayland-cursor.h> -#include <xkbcommon/xkbcommon.h> -#include "eloop.h" -#include "shl_array.h" -#include "shl_dlist.h" -#include "shl_hook.h" -#include "shl_log.h" -#include "shl_misc.h" -#include "tsm_vte.h" -#include "wlt_main.h" -#include "wlt_toolkit.h" - -#define LOG_SUBSYSTEM "wlt_toolkit" - -struct wlt_pool { - struct wl_shm_pool *w_pool; - size_t size; - uint8_t *data; -}; - -enum { - STATE_INIT = 0, - STATE_RUNNING, - STATE_HUP, -}; - -struct data_offer { - unsigned long ref; - struct wl_data_offer *w_offer; - struct wlt_display *disp; - struct shl_array *types; -}; - -struct wlt_display { - unsigned long ref; - struct ev_eloop *eloop; - struct wl_display *dp; - struct ev_fd *dp_fd; - struct wl_global_listener *dp_listener; - struct shl_hook *listeners; - unsigned int state; - struct wl_registry *w_registry; - - struct shl_dlist window_list; - - struct wl_compositor *w_comp; - struct wl_seat *w_seat; - struct wl_shell *w_shell; - struct wl_shm *w_shm; - - uint32_t last_serial; - uint32_t pointer_enter_serial; - struct wl_pointer *w_pointer; - struct wlt_window *pointer_focus; - - uint32_t cursor_serial; - unsigned int current_cursor; - struct wl_surface *w_cursor_surface; - struct wl_cursor_theme *cursor_theme; - struct wl_cursor *cursors[WLT_CURSOR_NUM]; - - struct wl_keyboard *w_keyboard; - struct xkb_context *xkb_ctx; - struct xkb_keymap *xkb_keymap; - struct xkb_state *xkb_state; - struct wlt_window *keyboard_focus; - struct ev_timer *repeat_timer; - uint32_t repeat_sym; - uint32_t repeat_ascii; - - struct wl_data_device_manager *w_manager; - struct wl_data_device *w_data_dev; - struct data_offer *drag_offer; - struct data_offer *selection_offer; -}; - -struct wlt_window { - unsigned long ref; - struct shl_dlist list; - void *data; - wlt_window_close_cb close_cb; - bool close_pending; - struct wlt_display *disp; - struct wlt_pool *pool; - - struct wl_surface *w_surface; - struct wl_shell_surface *w_shell_surface; - struct wl_buffer *w_buffer; - - bool buffer_attached; - bool skip_damage; - bool need_resize; - bool need_frame; - bool idle_pending; - unsigned int new_width; - unsigned int new_height; - unsigned int saved_width; - unsigned int saved_height; - unsigned int resize_edges; - bool maximized; - bool fullscreen; - struct wlt_shm_buffer buffer; - struct wl_callback *w_frame; - - struct shl_dlist widget_list; -}; - -struct wlt_widget { - struct shl_dlist list; - struct wlt_window *wnd; - void *data; - wlt_widget_redraw_cb redraw_cb; - wlt_widget_destroy_cb destroy_cb; - wlt_widget_prepare_resize_cb prepare_resize_cb; - wlt_widget_resize_cb resize_cb; - wlt_widget_pointer_enter_cb pointer_enter_cb; - wlt_widget_pointer_leave_cb pointer_leave_cb; - wlt_widget_pointer_motion_cb pointer_motion_cb; - wlt_widget_pointer_button_cb pointer_button_cb; - wlt_widget_keyboard_cb keyboard_cb; -}; - -static int wlt_pool_new(struct wlt_pool **out, struct wlt_display *disp, - size_t size) -{ - static const char template[] = "/wlterm-shared-XXXXXX"; - struct wlt_pool *pool; - int fd, ret; - const char *path; - char *name; - - path = getenv("XDG_RUNTIME_DIR"); - if (!path) { - log_error("XDG_RUNTIME_DIR not set"); - return -EFAULT; - } - - pool = malloc(sizeof(*pool)); - if (!pool) - return -ENOMEM; - memset(pool, 0, sizeof(*pool)); - pool->size = size; - - name = malloc(strlen(path) + sizeof(template)); - if (!name) { - ret = -ENOMEM; - goto err_free; - } - strcpy(name, path); - strcat(name, template); - - fd = mkostemp(name, O_CLOEXEC); - if (fd < 0) { - log_error("cannot create temporary file %s via mkostemp() (%d): %m", - name, errno); - ret = -EFAULT; - free(name); - goto err_free; - } - - ret = unlink(name); - if (ret) - log_warning("cannot unlink temporary file %s (%d): %m", - name, errno); - free(name); - - ret = ftruncate(fd, size); - if (ret) { - log_error("cannot truncate temporary file to length %lu (%d): %m", - size, errno); - ret = -EFAULT; - goto err_close; - } - - pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, - fd, 0); - if (pool->data == MAP_FAILED) { - log_error("cannot mmap temporary file (%d): %m", errno); - ret = -EFAULT; - goto err_close; - } - - pool->w_pool = wl_shm_create_pool(disp->w_shm, fd, size); - if (!pool->w_pool) { - log_error("cannot create wayland shm pool object"); - ret = -EFAULT; - goto err_map; - } - - close(fd); - *out = pool; - return 0; - -err_map: - munmap(pool->data, size); -err_close: - close(fd); -err_free: - free(pool); - return ret; -} - -static void wlt_pool_free(struct wlt_pool *pool) -{ - munmap(pool->data, pool->size); - wl_shm_pool_destroy(pool->w_pool); - free(pool); -} - -/* - * These cursor-names are based on: - * https://bugs.kde.org/attachment.cgi?id=67313 - */ - -static char *(*cursors[])[] = { - [WLT_CURSOR_NONE] = &(char*[]) { - NULL, - }, - [WLT_CURSOR_TOP] = &(char*[]) { - "top_side", - "n-resize", - NULL, - }, - [WLT_CURSOR_BOTTOM] = &(char*[]) { - "bottom_side", - "s-resize", - NULL, - }, - [WLT_CURSOR_LEFT] = &(char*[]) { - "left_side", - "w-resize", - NULL, - }, - [WLT_CURSOR_RIGHT] = &(char*[]) { - "right_side", - "e-resize", - NULL, - }, - [WLT_CURSOR_TOP_LEFT] = &(char*[]) { - "top_left_corner", - "nw-resize", - NULL, - }, - [WLT_CURSOR_TOP_RIGHT] = &(char*[]) { - "top_right_corner", - "ne-resize", - NULL, - }, - [WLT_CURSOR_BOTTOM_LEFT] = &(char*[]) { - "bottom_left_corner", - "sw-resize", - NULL, - }, - [WLT_CURSOR_BOTTOM_RIGHT] = &(char*[]) { - "bottom_right_corner", - "se-resize", - NULL, - }, - [WLT_CURSOR_DRAGGING] = &(char*[]) { - "grabbing", - "closedhand", - "208530c400c041818281048008011002", - NULL, - }, - [WLT_CURSOR_LEFT_PTR] = &(char*[]) { - "left_ptr", - "default", - "top_left_arrow", - "left-arrow", - NULL, - }, - [WLT_CURSOR_IBEAM] = &(char*[]) { - "xterm", - "ibeam", - "text", - NULL, - }, -}; - -static int load_cursors(struct wlt_display *disp) -{ - unsigned int i, j; - size_t size = sizeof(cursors) / sizeof(*cursors); - struct wl_cursor *cursor; - - disp->w_cursor_surface = wl_compositor_create_surface(disp->w_comp); - - disp->cursor_theme = wl_cursor_theme_load(NULL, 32, disp->w_shm); - if (!disp->cursor_theme) { - log_warning("cannot load curdor theme"); - return -EFAULT; - } - - for (i = 0; i < WLT_CURSOR_NUM; ++i) { - cursor = NULL; - if (i < size && cursors[i]) { - for (j = 0; (*cursors[i])[j]; ++j) { - cursor = wl_cursor_theme_get_cursor( - disp->cursor_theme, - (*cursors[i])[j]); - if (cursor) - break; - } - } - - if (!cursor && i != WLT_CURSOR_NONE) - log_warning("cannot load cursor for ID %d", i); - - disp->cursors[i] = cursor; - } - - return 0; -} - -static void unload_cursors(struct wlt_display *disp) -{ - if (disp->cursor_theme) - wl_cursor_theme_destroy(disp->cursor_theme); - if (disp->w_cursor_surface) - wl_surface_destroy(disp->w_cursor_surface); -} - -static void set_cursor(struct wlt_display *disp, unsigned int cursor) -{ - bool force = false; - struct wl_cursor *cur; - struct wl_cursor_image *image; - struct wl_buffer *buffer; - - if (cursor >= WLT_CURSOR_NUM) - cursor = WLT_CURSOR_LEFT_PTR; - - if (disp->pointer_enter_serial > disp->cursor_serial) - force = true; - - if (!force && cursor == disp->current_cursor) - return; - - disp->current_cursor = cursor; - disp->cursor_serial = disp->pointer_enter_serial; - - cur = disp->cursors[cursor]; - if (!cur) { - wl_pointer_set_cursor(disp->w_pointer, - disp->pointer_enter_serial, - NULL, 0, 0); - return; - } - - image = cur->images[0]; - buffer = wl_cursor_image_get_buffer(image); - if (!buffer) { - log_error("cannot load buffer for cursor image"); - return; - } - - wl_pointer_set_cursor(disp->w_pointer, - disp->pointer_enter_serial, - disp->w_cursor_surface, - image->hotspot_x, image->hotspot_y); - wl_surface_attach(disp->w_cursor_surface, buffer, 0, 0); - wl_surface_damage(disp->w_cursor_surface, 0, 0, - image->width, image->height); - wl_surface_commit(disp->w_cursor_surface); -} - -static void dp_dispatch(struct wlt_display *disp, bool nonblock) -{ - int ret; - - errno = 0; - if (nonblock) { - ret = wl_display_dispatch_pending(disp->dp); - if (ret != -1) - ret = wl_display_flush(disp->dp); - } else { - ret = wl_display_dispatch(disp->dp); - } - - if (ret == -1) { - log_error("error during wayland dispatch (%d): %m", errno); - return; - } else if (errno == EAGAIN) { - ret = ev_fd_update(disp->dp_fd, EV_READABLE | EV_WRITEABLE); - if (ret) - log_warning("cannot update wayland-fd event-polling modes (%d)", - ret); - } else { - ret = ev_fd_update(disp->dp_fd, EV_READABLE); - if (ret) - log_warning("cannot update wayland-fd event-polling modes (%d)", - ret); - } -} - -static void dp_pre_event(struct ev_eloop *eloop, void *unused, void *data) -{ - struct wlt_display *disp = data; - - dp_dispatch(disp, true); -} - -static void dp_event(struct ev_fd *fd, int mask, void *data) -{ - struct wlt_display *disp = data; - - if (mask & (EV_HUP | EV_ERR)) { - log_warning("HUP/ERR on wayland socket"); - disp->state = STATE_HUP; - shl_hook_call(disp->listeners, disp, (void*)WLT_DISPLAY_HUP); - ev_eloop_rm_fd(disp->dp_fd); - disp->dp_fd = NULL; - return; - } - - if (mask & EV_READABLE) - dp_dispatch(disp, false); - else - dp_dispatch(disp, true); -} - -static void pointer_enter(void *data, struct wl_pointer *w_pointer, - uint32_t serial, struct wl_surface *w_surface, - wl_fixed_t x, wl_fixed_t y) -{ - struct wlt_display *disp = data; - struct shl_dlist *iter; - struct wlt_window *wnd; - struct wlt_widget *widget; - - if (!w_surface) - return; - - shl_dlist_for_each(iter, &disp->window_list) { - wnd = shl_dlist_entry(iter, struct wlt_window, list); - if (wnd->w_surface == w_surface) - break; - } - - if (iter == &disp->window_list) { - log_debug("unknown surface"); - return; - } - - disp->pointer_enter_serial = serial; - disp->last_serial = serial; - disp->pointer_focus = wnd; - shl_dlist_for_each(iter, &wnd->widget_list) { - widget = shl_dlist_entry(iter, struct wlt_widget, list); - if (widget->pointer_enter_cb) - widget->pointer_enter_cb(widget, x >> 8, y >> 8, - widget->data); - } -} - -static void pointer_leave(void *data, struct wl_pointer *w_pointer, - uint32_t serial, struct wl_surface *w_surface) -{ - struct wlt_display *disp = data; - struct shl_dlist *iter; - struct wlt_window *wnd; - struct wlt_widget *widget; - - wnd = disp->pointer_focus; - disp->pointer_focus = NULL; - disp->last_serial = serial; - - if (!wnd) - return; - - shl_dlist_for_each(iter, &wnd->widget_list) { - widget = shl_dlist_entry(iter, struct wlt_widget, list); - if (widget->pointer_leave_cb) - widget->pointer_leave_cb(widget, widget->data); - } -} - -static void pointer_motion(void *data, struct wl_pointer *w_pointer, - uint32_t time, wl_fixed_t x, wl_fixed_t y) -{ - struct wlt_display *disp = data; - struct shl_dlist *iter; - struct wlt_window *wnd; - struct wlt_widget *widget; - - wnd = disp->pointer_focus; - if (!wnd) - return; - - shl_dlist_for_each(iter, &wnd->widget_list) { - widget = shl_dlist_entry(iter, struct wlt_widget, list); - if (widget->pointer_motion_cb) - widget->pointer_motion_cb(widget, x >> 8, y >> 8, - widget->data); - } -} - -static void pointer_button(void *data, struct wl_pointer *w_pointer, - uint32_t serial, uint32_t time, uint32_t button, - uint32_t state) -{ - struct wlt_display *disp = data; - struct shl_dlist *iter; - struct wlt_window *wnd; - struct wlt_widget *widget; - - wnd = disp->pointer_focus; - disp->last_serial = serial; - - if (!wnd) - return; - - shl_dlist_for_each(iter, &wnd->widget_list) { - widget = shl_dlist_entry(iter, struct wlt_widget, list); - if (widget->pointer_button_cb) - widget->pointer_button_cb(widget, button, state, - widget->data); - } -} - -static void pointer_axis(void *data, struct wl_pointer *w_pointer, - uint32_t time, uint32_t axis, wl_fixed_t value) -{ -} - -static const struct wl_pointer_listener pointer_listener = { - .enter = pointer_enter, - .leave = pointer_leave, - .motion = pointer_motion, - .button = pointer_button, - .axis = pointer_axis, -}; - -static void keyboard_keymap(void *data, struct wl_keyboard *keyboard, - uint32_t format, int fd, uint32_t size) -{ - struct wlt_display *disp = data; - char *map; - - if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { - log_error("invalid keyboard format"); - close(fd); - return; - } - - map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (map == MAP_FAILED) { - log_error("cannot mmap keyboard keymap"); - close(fd); - return; - } - - disp->xkb_keymap = xkb_keymap_new_from_string(disp->xkb_ctx, map, - XKB_KEYMAP_FORMAT_TEXT_V1, - 0); - munmap(map, size); - close(fd); - - if (!disp->xkb_keymap) { - log_error("cannot create xkb keymap"); - return; - } - - disp->xkb_state = xkb_state_new(disp->xkb_keymap); - if (!disp->xkb_state) { - log_error("cannot create XKB state object"); - xkb_keymap_unref(disp->xkb_keymap); - disp->xkb_keymap = NULL; - return; - } -} - -static void keyboard_enter(void *data, struct wl_keyboard *keyboard, - uint32_t serial, struct wl_surface *w_surface, - struct wl_array *keys) -{ - struct wlt_display *disp = data; - struct shl_dlist *iter; - struct wlt_window *wnd; - - disp->last_serial = serial; - if (!disp->xkb_state) - return; - - if (!w_surface) - return; - - shl_dlist_for_each(iter, &disp->window_list) { - wnd = shl_dlist_entry(iter, struct wlt_window, list); - if (wnd->w_surface == w_surface) - break; - } - - if (iter == &disp->window_list) - return; - - disp->keyboard_focus = wnd; -} - -static void keyboard_leave(void *data, struct wl_keyboard *keyboard, - uint32_t serial, struct wl_surface *surface) -{ - struct wlt_display *disp = data; - - disp->last_serial = serial; - disp->keyboard_focus = NULL; - ev_timer_update(disp->repeat_timer, NULL); -} - -static void keyboard_key(void *data, struct wl_keyboard *keyboard, - uint32_t serial, uint32_t time, uint32_t key, - uint32_t state_w) -{ - struct wlt_display *disp = data; - struct wlt_window *wnd = disp->keyboard_focus; - uint32_t code, num_syms, ascii; - unsigned int mask; - enum wl_keyboard_key_state state = state_w; - const xkb_keysym_t *syms; - xkb_keysym_t sym; - struct shl_dlist *iter; - struct wlt_widget *widget; - struct itimerspec spec; - bool handled; - - disp->last_serial = serial; - if (!disp->xkb_state) - return; - - code = key + 8; - if (!wnd) - return; - - mask = shl_get_xkb_mods(disp->xkb_state); - num_syms = xkb_state_key_get_syms(disp->xkb_state, code, &syms); - ascii = shl_get_ascii(disp->xkb_state, code, syms, num_syms); - sym = XKB_KEY_NoSymbol; - if (num_syms == 1) - sym = syms[0]; - - handled = false; - shl_dlist_for_each(iter, &wnd->widget_list) { - widget = shl_dlist_entry(iter, struct wlt_widget, list); - if (widget->keyboard_cb) { - if (widget->keyboard_cb(widget, mask, sym, ascii, state, - handled, widget->data)) - handled = true; - } - } - - if (state == WL_KEYBOARD_KEY_STATE_RELEASED) { - ev_timer_update(disp->repeat_timer, NULL); - } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - disp->repeat_sym = sym; - disp->repeat_ascii = ascii; - spec.it_interval.tv_sec = 0; - spec.it_interval.tv_nsec = wlt_conf.xkb_repeat_rate * 1000000; - spec.it_value.tv_sec = 0; - spec.it_value.tv_nsec = wlt_conf.xkb_repeat_delay * 1000000; - ev_timer_update(disp->repeat_timer, &spec); - } -} - -static void repeat_event(struct ev_timer *timer, uint64_t num, void *data) -{ - struct wlt_display *disp = data; - struct wlt_window *wnd = disp->keyboard_focus; - struct wlt_widget *widget; - struct shl_dlist *iter; - unsigned int mask; - bool handled; - - if (!wnd) - return; - - mask = shl_get_xkb_mods(disp->xkb_state); - handled = false; - shl_dlist_for_each(iter, &wnd->widget_list) { - widget = shl_dlist_entry(iter, struct wlt_widget, list); - if (widget->keyboard_cb) { - if (widget->keyboard_cb(widget, mask, disp->repeat_sym, - disp->repeat_ascii, - WL_KEYBOARD_KEY_STATE_PRESSED, - handled, widget->data)) - handled = true; - } - } -} - -static void keyboard_modifiers(void *data, struct wl_keyboard *keyboard, - uint32_t serial, uint32_t mods_depressed, - uint32_t mods_latched, uint32_t mods_locked, - uint32_t group) -{ - struct wlt_display *disp = data; - - disp->last_serial = serial; - if (!disp->xkb_state) - return; - - xkb_state_update_mask(disp->xkb_state, mods_depressed, mods_latched, - mods_locked, 0, 0, group); -} - -static const struct wl_keyboard_listener keyboard_listener = { - .keymap = keyboard_keymap, - .enter = keyboard_enter, - .leave = keyboard_leave, - .key = keyboard_key, - .modifiers = keyboard_modifiers, -}; - -static void data_offer_unref(struct data_offer *offer) -{ - unsigned int i, len; - - if (!offer || !offer->ref || --offer->ref) - return; - - len = shl_array_get_length(offer->types); - for (i = 0; i < len; ++i) - free(*SHL_ARRAY_AT(offer->types, char*, i)); - shl_array_free(offer->types); - wl_data_offer_destroy(offer->w_offer); - free(offer); -} - -static void data_offer_offer(void *data, struct wl_data_offer *w_offer, - const char *type) -{ - char *tmp; - int ret; - struct data_offer *offer = wl_data_offer_get_user_data(w_offer); - - tmp = strdup(type); - if (!tmp) - return; - - ret = shl_array_push(offer->types, &tmp); - if (ret) { - free(tmp); - return; - } -} - -static const struct wl_data_offer_listener data_offer_listener = { - .offer = data_offer_offer, -}; - -static void data_dev_data_offer(void *data, struct wl_data_device *w_dev, - struct wl_data_offer *w_offer) -{ - struct data_offer *offer; - struct wlt_display *disp = data; - int ret; - - offer = malloc(sizeof(*offer)); - if (!offer) { - wl_data_offer_destroy(w_offer); - return; - } - memset(offer, 0, sizeof(*offer)); - offer->ref = 1; - offer->w_offer = w_offer; - offer->disp = disp; - - ret = shl_array_new(&offer->types, sizeof(char*), 4); - if (ret) { - wl_data_offer_destroy(w_offer); - free(offer); - return; - } - - wl_data_offer_add_listener(w_offer, &data_offer_listener, offer); - wl_data_offer_set_user_data(w_offer, offer); -} - -static void data_dev_enter(void *data, struct wl_data_device *w_dev, - uint32_t serial, struct wl_surface *w_surface, - wl_fixed_t x, wl_fixed_t y, - struct wl_data_offer *w_offer) -{ - struct wlt_display *disp = data; - - if (disp->drag_offer) { - data_offer_unref(disp->drag_offer); - disp->drag_offer = NULL; - } - - if (!w_offer) - return; - - disp->drag_offer = wl_data_offer_get_user_data(w_offer); -} - -static void data_dev_leave(void *data, struct wl_data_device *w_dev) -{ - struct wlt_display *disp = data; - - if (disp->drag_offer) { - data_offer_unref(disp->drag_offer); - disp->drag_offer = NULL; - } -} - -static void data_dev_motion(void *data, struct wl_data_device *w_dev, - uint32_t time, wl_fixed_t x, wl_fixed_t y) -{ -} - -static void data_dev_drop(void *data, struct wl_data_device *w_dev) -{ -} - -static void data_dev_selection(void *data, struct wl_data_device *w_dev, - struct wl_data_offer *w_offer) -{ - struct wlt_display *disp = data; - - if (disp->selection_offer) { - data_offer_unref(disp->selection_offer); - disp->selection_offer = NULL; - } - - if (!w_offer) - return; - - disp->selection_offer = wl_data_offer_get_user_data(w_offer); -} - -int wlt_display_get_selection_to_fd(struct wlt_display *disp, const char *mime, - int output_fd) -{ - unsigned int i, num; - struct data_offer *offer; - - if (!disp || !mime) - return -EINVAL; - if (!disp->selection_offer) - return -ENOENT; - - offer = disp->selection_offer; - num = shl_array_get_length(offer->types); - for (i = 0; i < num; ++i) { - if (!strcmp(mime, *SHL_ARRAY_AT(offer->types, char*, i))) - break; - } - - if (i == num) - return -EAGAIN; - - wl_data_offer_receive(offer->w_offer, mime, output_fd); - return 0; -} - -int wlt_display_get_selection_fd(struct wlt_display *disp, const char *mime) -{ - int p[2], ret; - - if (pipe2(p, O_CLOEXEC | O_NONBLOCK)) - return -EFAULT; - - ret = wlt_display_get_selection_to_fd(disp, mime, p[1]); - close(p[1]); - - if (ret) { - close(p[0]); - return ret; - } - - return p[0]; -} - -int wlt_display_new_data_source(struct wlt_display *disp, - struct wl_data_source **out) -{ - struct wl_data_source *src; - - if (!disp) - return -EINVAL; - - src = wl_data_device_manager_create_data_source(disp->w_manager); - if (!src) - return -EFAULT; - - *out = src; - return 0; -} - -void wlt_display_set_selection(struct wlt_display *disp, - struct wl_data_source *selection) -{ - if (!disp) - return; - - wl_data_device_set_selection(disp->w_data_dev, selection, - disp->last_serial); -} - -static const struct wl_data_device_listener data_dev_listener = { - .data_offer = data_dev_data_offer, - .enter = data_dev_enter, - .leave = data_dev_leave, - .motion = data_dev_motion, - .drop = data_dev_drop, - .selection = data_dev_selection, -}; - -static void check_ready(struct wlt_display *disp) -{ - if (disp->state > STATE_INIT) - return; - - if (disp->w_comp && - disp->w_seat && - disp->w_shell && - disp->w_shm && - disp->w_pointer && - disp->w_keyboard && - disp->w_manager) { - log_debug("wayland display initialized"); - load_cursors(disp); - - disp->w_data_dev = wl_data_device_manager_get_data_device( - disp->w_manager, disp->w_seat); - wl_data_device_add_listener(disp->w_data_dev, - &data_dev_listener, - disp); - - disp->state = STATE_RUNNING; - shl_hook_call(disp->listeners, disp, (void*)WLT_DISPLAY_READY); - } -} - -static void seat_capabilities(void *data, struct wl_seat *seat, - enum wl_seat_capability caps) -{ - struct wlt_display *disp = data; - - if (caps & WL_SEAT_CAPABILITY_POINTER && !disp->w_pointer) { - disp->w_pointer = wl_seat_get_pointer(seat); - wl_pointer_add_listener(disp->w_pointer, &pointer_listener, - disp); - } - - if (caps & WL_SEAT_CAPABILITY_KEYBOARD && !disp->w_keyboard) { - disp->w_keyboard = wl_seat_get_keyboard(seat); - wl_keyboard_add_listener(disp->w_keyboard, &keyboard_listener, - disp); - } - - check_ready(disp); -} - -static const struct wl_seat_listener seat_listener = { - .capabilities = seat_capabilities, -}; - -static void dp_global(void *data, struct wl_registry *registry, uint32_t id, - const char *iface, uint32_t version) -{ - struct wlt_display *disp = data; - - if (!strcmp(iface, "wl_display")) { - log_debug("new wl_display global"); - return; - } else if (!strcmp(iface, "wl_compositor")) { - if (disp->w_comp) { - log_error("global wl_compositor advertised twice"); - return; - } - disp->w_comp = wl_registry_bind(disp->w_registry, - id, - &wl_compositor_interface, - 1); - if (!disp->w_comp) { - log_error("cannot bind wl_compositor object"); - return; - } - } else if (!strcmp(iface, "wl_seat")) { - if (disp->w_seat) { - log_error("global wl_seat advertised twice"); - return; - } - disp->w_seat = wl_registry_bind(disp->w_registry, - id, - &wl_seat_interface, - 1); - if (!disp->w_seat) { - log_error("cannot bind wl_seat object"); - return; - } - - wl_seat_add_listener(disp->w_seat, &seat_listener, disp); - } else if (!strcmp(iface, "wl_shell")) { - if (disp->w_shell) { - log_error("global wl_shell advertised twice"); - return; - } - disp->w_shell = wl_registry_bind(disp->w_registry, - id, - &wl_shell_interface, - 1); - if (!disp->w_shell) { - log_error("cannot bind wl_shell object"); - return; - } - } else if (!strcmp(iface, "wl_shm")) { - if (disp->w_shm) { - log_error("global wl_shm advertised twice"); - return; - } - disp->w_shm = wl_registry_bind(disp->w_registry, - id, - &wl_shm_interface, - 1); - if (!disp->w_shm) { - log_error("cannot bind wl_shm object"); - return; - } - } else if (!strcmp(iface, "wl_data_device_manager")) { - if (disp->w_manager) { - log_error("global wl_data_device_manager advertised twice"); - return; - } - disp->w_manager = wl_registry_bind(disp->w_registry, - id, - &wl_data_device_manager_interface, - 1); - if (!disp->w_manager) { - log_error("cannot bind wl_data_device_manager_object"); - return; - } - } else { - log_debug("ignoring new unknown global %s", iface); - return; - } - - log_debug("new global %s", iface); - - check_ready(disp); -} - -static const struct wl_registry_listener registry_listener = { - .global = dp_global, - /* TODO: handle .global_remove */ -}; - -int wlt_display_new(struct wlt_display **out, - struct ev_eloop *eloop) -{ - struct wlt_display *disp; - int ret, fd; - - if (!out || !eloop) - return -EINVAL; - - log_debug("creating new wlt-display"); - - disp = malloc(sizeof(*disp)); - if (!disp) - return -ENOMEM; - memset(disp, 0, sizeof(*disp)); - disp->ref = 1; - disp->eloop = eloop; - shl_dlist_init(&disp->window_list); - - ret = shl_hook_new(&disp->listeners); - if (ret) { - log_error("cannot create listeners hook"); - goto err_free; - } - - disp->dp = wl_display_connect(NULL); - if (!disp->dp) { - log_error("cannot connect to wayland socket (%d): %m", errno); - ret = -EFAULT; - goto err_listener; - } - - fd = wl_display_get_fd(disp->dp); - if (fd < 0) { - log_error("cannot retrieve wayland FD"); - ret = -EFAULT; - goto err_dp; - } - - /* TODO: nonblocking wl_display doesn't work, yet. fix that upstream */ - /* - int set; - set = fcntl(fd, F_GETFL); - if (set < 0) { - log_error("cannot retrieve file flags for wayland FD (%d): %m", - errno); - ret = -EFAULT; - goto err_dp; - } - - set |= O_NONBLOCK; - ret = fcntl(fd, F_SETFL, set); - if (ret) { - log_error("cannot set file flags for wayland FD (%d): %m", - errno); - ret = -EFAULT; - goto err_dp; - }*/ - - ret = ev_eloop_new_fd(eloop, - &disp->dp_fd, - fd, - EV_READABLE, - dp_event, - disp); - if (ret) { - log_error("cannot create event-fd for wayland display (%d)", - ret); - goto err_dp; - } - - ret = ev_eloop_register_pre_cb(eloop, dp_pre_event, disp); - if (ret) { - log_error("cannot register pre-cb (%d)", ret); - goto err_dp_fd; - } - - ret = ev_eloop_new_timer(eloop, &disp->repeat_timer, NULL, - repeat_event, disp); - if (ret) { - log_error("cannot create repeat-timer"); - goto err_pre_cb; - } - - disp->w_registry = wl_display_get_registry(disp->dp); - if (!disp->w_registry) { - log_error("cannot get wayland registry object"); - goto err_timer; - } - - wl_registry_add_listener(disp->w_registry, ®istry_listener, disp); - - disp->xkb_ctx = xkb_context_new(0); - if (!disp->xkb_ctx) { - log_error("cannot create XKB context"); - goto err_timer; - } - - log_debug("wlt-display waiting for globals..."); - - ev_eloop_ref(disp->eloop); - *out = disp; - return 0; - -err_timer: - ev_eloop_rm_timer(disp->repeat_timer); -err_pre_cb: - ev_eloop_unregister_pre_cb(disp->eloop, dp_pre_event, disp); -err_dp_fd: - ev_eloop_rm_fd(disp->dp_fd); -err_dp: - wl_display_disconnect(disp->dp); -err_listener: - shl_hook_free(disp->listeners); -err_free: - free(disp); - return ret; -} - -void wlt_display_ref(struct wlt_display *disp) -{ - if (!disp || !disp->ref) - return; - - ++disp->ref; -} - -void wlt_display_unref(struct wlt_display *disp) -{ - if (!disp || !disp->ref || --disp->ref) - return; - - unload_cursors(disp); - wl_display_flush(disp->dp); - wl_display_disconnect(disp->dp); - ev_eloop_rm_timer(disp->repeat_timer); - ev_eloop_unregister_pre_cb(disp->eloop, dp_pre_event, disp); - ev_eloop_rm_fd(disp->dp_fd); - xkb_context_unref(disp->xkb_ctx); - shl_hook_free(disp->listeners); - ev_eloop_unref(disp->eloop); - free(disp); -} - -int wlt_display_register_cb(struct wlt_display *disp, - wlt_display_cb cb, void *data) -{ - if (!disp) - return -EINVAL; - - return shl_hook_add_cast(disp->listeners, cb, data, false); -} - -void wlt_display_unregister_cb(struct wlt_display *disp, - wlt_display_cb cb, void *data) -{ - if (!disp) - return; - - shl_hook_rm_cast(disp->listeners, cb, data); -} - -static void shell_surface_ping(void *data, struct wl_shell_surface *s, - uint32_t serial) -{ - wl_shell_surface_pong(s, serial); -} - -static void wlt_window_do_redraw(struct wlt_window *wnd, - unsigned int oldw, - unsigned int oldh) -{ - struct shl_dlist *iter; - struct wlt_widget *widget; - unsigned int x, y, flags; - struct wlt_rect alloc; - - flags = 0; - if (wnd->maximized) - flags |= WLT_WINDOW_MAXIMIZED; - if (wnd->fullscreen) - flags |= WLT_WINDOW_FULLSCREEN; - - alloc.x = 0; - alloc.y = 0; - alloc.width = wnd->buffer.width; - alloc.height = wnd->buffer.height; - shl_dlist_for_each(iter, &wnd->widget_list) { - widget = shl_dlist_entry(iter, struct wlt_widget, list); - if (widget->resize_cb) - widget->resize_cb(widget, flags, &alloc, widget->data); - } - - memset(wnd->buffer.data, 0, - wnd->buffer.stride * wnd->buffer.height); - - wnd->skip_damage = true; - shl_dlist_for_each(iter, &wnd->widget_list) { - widget = shl_dlist_entry(iter, struct wlt_widget, list); - if (widget->redraw_cb) - widget->redraw_cb(widget, flags, widget->data); - } - wnd->skip_damage = false; - - x = 0; - y = 0; - if (!wnd->buffer_attached) { - wnd->buffer_attached = true; - if (wnd->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT) - x = (int)oldw - wnd->buffer.width; - if (wnd->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP) - y = (int)oldh - wnd->buffer.height; - wnd->resize_edges = 0; - } - - wl_surface_attach(wnd->w_surface, wnd->w_buffer, x, y); - wl_surface_damage(wnd->w_surface, 0, 0, wnd->buffer.width, - wnd->buffer.height); - wl_surface_commit(wnd->w_surface); -} - -static int resize_window(struct wlt_window *wnd, unsigned int width, - unsigned int height) -{ - struct shl_dlist *iter; - struct wlt_widget *widget; - struct wl_buffer *old_buffer = NULL; - struct wlt_pool *old_pool = NULL; - size_t nsize; - int ret; - unsigned int oldw, oldh, neww, newh, minw, minh, flags; - - if (!width) - width = wnd->buffer.width; - if (!height) - height = wnd->buffer.height; - - if (!width || !height) - return -EINVAL; - - flags = 0; - if (wnd->maximized) - flags |= WLT_WINDOW_MAXIMIZED; - if (wnd->fullscreen) - flags |= WLT_WINDOW_FULLSCREEN; - - neww = 0; - newh = 0; - minw = 0; - minh = 0; - shl_dlist_for_each(iter, &wnd->widget_list) { - widget = shl_dlist_entry(iter, struct wlt_widget, list); - if (widget->prepare_resize_cb) - widget->prepare_resize_cb(widget, - flags, - width, height, - &minw, &minh, - &neww, &newh, - widget->data); - } - - if (neww) - width = neww; - if (newh) - height = newh; - - if (width == wnd->buffer.width && - height == wnd->buffer.height) { - wlt_window_do_redraw(wnd, width, height); - return 0; - } - - oldw = wnd->buffer.width; - oldh = wnd->buffer.height; - - nsize = width * height * 4; - if (wnd->pool && wnd->pool->size >= nsize) { - old_buffer = wnd->w_buffer; - wnd->w_buffer = wl_shm_pool_create_buffer(wnd->pool->w_pool, - 0, width, height, - width * 4, - WL_SHM_FORMAT_ARGB8888); - if (!wnd->w_buffer) { - log_error("cannot create wayland shm buffer"); - wnd->w_buffer = old_buffer; - return -ENOMEM; - } - } else { - old_pool = wnd->pool; - ret = wlt_pool_new(&wnd->pool, wnd->disp, nsize); - if (ret) { - log_error("cannot create memory pool"); - wnd->pool = old_pool; - return ret; - } - - old_buffer = wnd->w_buffer; - wnd->w_buffer = wl_shm_pool_create_buffer(wnd->pool->w_pool, - 0, width, height, - width * 4, - WL_SHM_FORMAT_ARGB8888); - if (!wnd->w_buffer) { - log_error("cannot create wayland shm buffer"); - wnd->w_buffer = old_buffer; - wlt_pool_free(wnd->pool); - wnd->pool = old_pool; - return -ENOMEM; - } - } - - wnd->buffer.data = wnd->pool->data; - wnd->buffer.width = width; - wnd->buffer.height = height; - wnd->buffer.stride = width * 4; - wnd->buffer_attached = false; - - wlt_window_do_redraw(wnd, oldw, oldh); - - if (old_buffer) - wl_buffer_destroy(old_buffer); - if (old_pool) - wlt_pool_free(old_pool); - - return 0; -} - -static void frame_callback(void *data, struct wl_callback *w_callback, - uint32_t time); -static void idle_frame(struct ev_eloop *eloop, void *unused, void *data); - -static const struct wl_callback_listener frame_callback_listener = { - .done = frame_callback, -}; - -static void do_frame(struct wlt_window *wnd) -{ - ev_eloop_unregister_idle_cb(wnd->disp->eloop, idle_frame, wnd, - EV_NORMAL); - - if (wnd->need_resize) { - wnd->need_frame = true; - wnd->need_resize = false; - wnd->w_frame = wl_surface_frame(wnd->w_surface); - wl_callback_add_listener(wnd->w_frame, - &frame_callback_listener, wnd); - resize_window(wnd, wnd->new_width, wnd->new_height); - } else { - wnd->need_frame = true; - wnd->w_frame = wl_surface_frame(wnd->w_surface); - wl_callback_add_listener(wnd->w_frame, - &frame_callback_listener, wnd); - wlt_window_do_redraw(wnd, wnd->buffer.width, - wnd->buffer.height); - } -} - -static void schedule_frame(struct wlt_window *wnd); - -static void frame_callback(void *data, struct wl_callback *w_callback, - uint32_t time) -{ - struct wlt_window *wnd = data; - - wl_callback_destroy(w_callback); - wnd->w_frame = NULL; - - wnd->idle_pending = false; - if (wnd->need_frame) - schedule_frame(wnd); -} - -static void idle_frame(struct ev_eloop *eloop, void *unused, void *data) -{ - struct wlt_window *wnd = data; - - do_frame(wnd); -} - -/* - * Buffer Handling and Frame Scheduling - * We use wl_shm for buffer allocation. This means, we have a single buffer - * client side and the server loads it into its backbuffer for rendering. If the - * server does not do this, we are screwed anyway, but that's on behalf of the - * server, so we don't care. - * - * However, this means, when we create a buffer, we need to notify the - * compositor and then wait until the compositor has created its back-buffer, - * before we continue using this buffer. We can use the "frame" callback to get - * notified about this. - * - * The logic we have is: - * You set the boolean flags what action is needed in wlt_window and then call - * "schedule_frame()". If we didn't already do any buffer operations in this - * frame, then this function schedules an idle-callback which then performs - * the requested functions (flags in wlt_window). Afterwards, it sets a marker - * that this frame was already used and schedules a frame-callback. - * If during this time another call to schedule_frame() is made, we do nothing - * but wait for the frame-callback. It will then directly perform all the - * requested functions and reschedule a frame-callback. - * If nothing was schedule for one frame, we have no more interest in - * frame-callbacks and thus we set "need_frame" to false again and don't - * schedule any more frame-callbacks. - */ -static void schedule_frame(struct wlt_window *wnd) -{ - int ret; - - if (!wnd) - return; - - wnd->need_frame = true; - - if (wnd->idle_pending) - return; - - ret = ev_eloop_register_idle_cb(wnd->disp->eloop, idle_frame, wnd, - EV_NORMAL); - if (ret) - log_error("cannot schedule idle callback: %d", ret); - else - wnd->idle_pending = true; -} - -static void shell_surface_configure(void *data, struct wl_shell_surface *s, - uint32_t edges, int32_t width, - int32_t height) -{ - struct wlt_window *wnd = data; - - if (width <= 0) - width = 1; - if (height <= 0) - height = 1; - - wnd->resize_edges = edges; - wlt_window_set_size(wnd, width, height); -} - -static void shell_surface_popup_done(void *data, struct wl_shell_surface *s) -{ -} - -static const struct wl_shell_surface_listener shell_surface_listener = { - .ping = shell_surface_ping, - .configure = shell_surface_configure, - .popup_done = shell_surface_popup_done, -}; - -static void close_window(struct ev_eloop *eloop, void *unused, void *data) -{ - struct wlt_window *wnd = data; - - ev_eloop_unregister_idle_cb(eloop, close_window, wnd, EV_NORMAL); - wnd->close_pending = false; - - if (wnd->close_cb) - wnd->close_cb(wnd, wnd->data); -} - -int wlt_display_create_window(struct wlt_display *disp, - struct wlt_window **out, - unsigned int width, - unsigned int height, - void *data) -{ - struct wlt_window *wnd; - int ret; - - if (!disp || !out || !width || !height) - return -EINVAL; - - if (disp->state != STATE_RUNNING) { - log_error("cannot create window, display is not running but in state %u", - disp->state); - return -EBUSY; - } - - wnd = malloc(sizeof(*wnd)); - if (!wnd) - return -ENOMEM; - memset(wnd, 0, sizeof(*wnd)); - wnd->ref = 1; - wnd->disp = disp; - wnd->data = data; - shl_dlist_init(&wnd->widget_list); - - wnd->w_surface = wl_compositor_create_surface(disp->w_comp); - if (!wnd->w_surface) { - log_error("cannot create wayland surface"); - ret = -EFAULT; - goto err_free; - } - - wnd->w_shell_surface = wl_shell_get_shell_surface(disp->w_shell, - wnd->w_surface); - if (!wnd->w_shell_surface) { - log_error("cannot retrieve shell-surface for wayland surface"); - ret = -EFAULT; - goto err_surface; - } - - wl_shell_surface_add_listener(wnd->w_shell_surface, - &shell_surface_listener, wnd); - wl_shell_surface_set_toplevel(wnd->w_shell_surface); - - ret = resize_window(wnd, width, height); - if (ret) - goto err_shell_surface; - - wlt_display_ref(disp); - shl_dlist_link(&disp->window_list, &wnd->list); - *out = wnd; - return 0; - -err_shell_surface: - wl_shell_surface_destroy(wnd->w_shell_surface); -err_surface: - wl_surface_destroy(wnd->w_surface); -err_free: - free(wnd); - return ret; -} - -void wlt_window_ref(struct wlt_window *wnd) -{ - if (!wnd || !wnd->ref) - return; - - ++wnd->ref; -} - -void wlt_window_unref(struct wlt_window *wnd) -{ - struct wlt_widget *widget; - - if (!wnd || !wnd->ref || --wnd->ref) - return; - - while (!shl_dlist_empty(&wnd->widget_list)) { - widget = shl_dlist_entry(wnd->widget_list.next, - struct wlt_widget, list); - wlt_widget_destroy(widget); - } - - if (wnd->close_pending) - ev_eloop_unregister_idle_cb(wnd->disp->eloop, close_window, - wnd, EV_NORMAL); - if (wnd->idle_pending) - ev_eloop_unregister_idle_cb(wnd->disp->eloop, idle_frame, wnd, - EV_NORMAL); - shl_dlist_unlink(&wnd->list); - if (wnd->w_frame) - wl_callback_destroy(wnd->w_frame); - if (wnd->w_buffer) - wl_buffer_destroy(wnd->w_buffer); - if (wnd->pool) - wlt_pool_free(wnd->pool); - wl_shell_surface_destroy(wnd->w_shell_surface); - wl_surface_destroy(wnd->w_surface); - wlt_display_unref(wnd->disp); - free(wnd); -} - -int wlt_window_create_widget(struct wlt_window *wnd, - struct wlt_widget **out, - void *data) -{ - struct wlt_widget *widget; - - if (!wnd || !out) - return -EINVAL; - - widget = malloc(sizeof(*widget)); - if (!widget) - return -ENOMEM; - memset(widget, 0, sizeof(*widget)); - widget->wnd = wnd; - widget->data = data; - - wlt_window_set_size(wnd, wnd->buffer.width, wnd->buffer.height); - shl_dlist_link_tail(&wnd->widget_list, &widget->list); - *out = widget; - return 0; -} - -void wlt_window_schedule_redraw(struct wlt_window *wnd) -{ - if (!wnd) - return; - - schedule_frame(wnd); -} - -void wlt_window_damage(struct wlt_window *wnd, - struct wlt_rect *damage) -{ - if (!wnd || !damage || wnd->skip_damage) - return; - - wl_surface_damage(wnd->w_surface, damage->x, damage->y, - damage->width, damage->height); - wl_surface_commit(wnd->w_surface); -} - -void wlt_window_get_buffer(struct wlt_window *wnd, - const struct wlt_rect *alloc, - struct wlt_shm_buffer *buf) -{ - struct wlt_shm_buffer *rbuf; - - if (!wnd || !buf) - return; - - rbuf = &wnd->buffer; - - if (!alloc) { - memcpy(buf, rbuf, sizeof(*buf)); - return; - } - - if (alloc->x >= rbuf->width || - alloc->y >= rbuf->height) { - memset(buf, 0, sizeof(*buf)); - return; - } - - /* set width */ - if (alloc->x + alloc->width > rbuf->width) - buf->width = rbuf->width - alloc->x; - else - buf->width = alloc->width; - - /* set height */ - if (alloc->y + alloc->height > rbuf->height) - buf->height = rbuf->height - alloc->y; - else - buf->height = alloc->height; - - /* set stride */ - buf->stride = rbuf->stride; - - /* set data */ - buf->data = rbuf->data; - buf->data += alloc->y * rbuf->stride; - buf->data += alloc->x * 4; -} - -void wlt_window_move(struct wlt_window *wnd) -{ - if (!wnd) - return; - - wl_shell_surface_move(wnd->w_shell_surface, - wnd->disp->w_seat, - wnd->disp->last_serial); -} - -void wlt_window_resize(struct wlt_window *wnd, uint32_t edges) -{ - if (!wnd) - return; - - wl_shell_surface_resize(wnd->w_shell_surface, - wnd->disp->w_seat, - wnd->disp->last_serial, - edges); -} - -int wlt_window_set_size(struct wlt_window *wnd, - unsigned int width, unsigned int height) -{ - if (!wnd) - return -EINVAL; - - wnd->new_width = width; - wnd->new_height = height; - wnd->need_resize = true; - schedule_frame(wnd); - - return 0; -} - -void wlt_window_set_cursor(struct wlt_window *wnd, unsigned int cursor) -{ - if (!wnd) - return; - - set_cursor(wnd->disp, cursor); -} - -void wlt_window_set_close_cb(struct wlt_window *wnd, - wlt_window_close_cb cb) -{ - if (!wnd) - return; - - wnd->close_cb = cb; -} - -void wlt_window_close(struct wlt_window *wnd) -{ - if (!wnd) - return; - - wnd->close_pending = true; - ev_eloop_register_idle_cb(wnd->disp->eloop, close_window, wnd, - EV_NORMAL); -} - -void wlt_window_toggle_maximize(struct wlt_window *wnd) -{ - if (!wnd) - return; - - if (wnd->maximized) { - if (!wnd->fullscreen) { - wl_shell_surface_set_toplevel(wnd->w_shell_surface); - wlt_window_set_size(wnd, wnd->saved_width, - wnd->saved_height); - } - } else { - if (!wnd->fullscreen) { - wnd->saved_width = wnd->buffer.width; - wnd->saved_height = wnd->buffer.height; - wl_shell_surface_set_maximized(wnd->w_shell_surface, - NULL); - } - } - - wnd->maximized = !wnd->maximized; -} - -bool wlt_window_is_maximized(struct wlt_window *wnd) -{ - return wnd && wnd->maximized; -} - -void wlt_window_toggle_fullscreen(struct wlt_window *wnd) -{ - if (!wnd) - return; - - if (wnd->fullscreen) { - if (wnd->maximized) { - wl_shell_surface_set_maximized(wnd->w_shell_surface, - NULL); - } else { - wl_shell_surface_set_toplevel(wnd->w_shell_surface); - wlt_window_set_size(wnd, wnd->saved_width, - wnd->saved_height); - } - } else { - if (!wnd->maximized) { - wnd->saved_width = wnd->buffer.width; - wnd->saved_height = wnd->buffer.height; - } - wl_shell_surface_set_fullscreen(wnd->w_shell_surface, - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, - 0, NULL); - } - - wnd->fullscreen = !wnd->fullscreen; -} - -bool wlt_window_is_fullscreen(struct wlt_window *wnd) -{ - return wnd && wnd->fullscreen; -} - -struct ev_eloop *wlt_window_get_eloop(struct wlt_window *wnd) -{ - if (!wnd) - return NULL; - - return wnd->disp->eloop; -} - -struct wlt_display *wlt_window_get_display(struct wlt_window *wnd) -{ - if (!wnd) - return NULL; - - return wnd->disp; -} - -void wlt_widget_destroy(struct wlt_widget *widget) -{ - if (!widget) - return; - - if (widget->destroy_cb) - widget->destroy_cb(widget, widget->data); - shl_dlist_unlink(&widget->list); - free(widget); -} - -struct wlt_window *wlt_widget_get_window(struct wlt_widget *widget) -{ - if (!widget) - return NULL; - - return widget->wnd; -} - -void wlt_widget_set_redraw_cb(struct wlt_widget *widget, - wlt_widget_redraw_cb cb) -{ - if (!widget) - return; - - widget->redraw_cb = cb; -} - -void wlt_widget_set_destroy_cb(struct wlt_widget *widget, - wlt_widget_destroy_cb cb) -{ - if (!widget) - return; - - widget->destroy_cb = cb; -} - -void wlt_widget_set_resize_cb(struct wlt_widget *widget, - wlt_widget_prepare_resize_cb prepare_cb, - wlt_widget_resize_cb cb) -{ - if (!widget) - return; - - widget->prepare_resize_cb = prepare_cb; - widget->resize_cb = cb; -} - -void wlt_widget_set_pointer_cb(struct wlt_widget *widget, - wlt_widget_pointer_enter_cb enter_cb, - wlt_widget_pointer_leave_cb leave_cb, - wlt_widget_pointer_motion_cb motion_cb, - wlt_widget_pointer_button_cb button_cb) -{ - if (!widget) - return; - - widget->pointer_enter_cb = enter_cb; - widget->pointer_leave_cb = leave_cb; - widget->pointer_motion_cb = motion_cb; - widget->pointer_button_cb = button_cb; -} - -void wlt_widget_set_keyboard_cb(struct wlt_widget *widget, - wlt_widget_keyboard_cb cb) -{ - if (!widget) - return; - - widget->keyboard_cb = cb; -} diff --git a/src/wlt_toolkit.h b/src/wlt_toolkit.h deleted file mode 100644 index 44ce0ec..0000000 --- a/src/wlt_toolkit.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * wlt - Toolkit Helper - * - * Copyright (c) 2012 David Herrmann <dh.herrmann@googlemail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Wayland Terminal toolkit helpers - */ - -#ifndef WLT_TOOLKIT_H -#define WLT_TOOLKIT_H - -#include <stdbool.h> -#include <stdlib.h> -#include "eloop.h" - -struct wlt_display; -struct wlt_window; -struct wlt_widget; - -enum wlt_display_event { - WLT_DISPLAY_HUP, - WLT_DISPLAY_READY, -}; - -struct wlt_rect { - unsigned int x; - unsigned int y; - unsigned int width; - unsigned int height; -}; - -struct wlt_shm_buffer { - uint8_t *data; - unsigned int width; - unsigned int height; - unsigned int stride; -}; - -enum cursor_type { - WLT_CURSOR_NONE, - WLT_CURSOR_TOP, - WLT_CURSOR_BOTTOM, - WLT_CURSOR_LEFT, - WLT_CURSOR_RIGHT, - WLT_CURSOR_TOP_LEFT, - WLT_CURSOR_TOP_RIGHT, - WLT_CURSOR_BOTTOM_LEFT, - WLT_CURSOR_BOTTOM_RIGHT, - WLT_CURSOR_DRAGGING, - WLT_CURSOR_LEFT_PTR, - WLT_CURSOR_IBEAM, - WLT_CURSOR_NUM, -}; - -#define WLT_WINDOW_MAXIMIZED 0x01 -#define WLT_WINDOW_FULLSCREEN 0x02 - -typedef void (*wlt_display_cb) (struct wlt_display *disp, - unsigned int event, - void *data); -typedef void (*wlt_window_close_cb) (struct wlt_window *wnd, void *data); -typedef void (*wlt_widget_redraw_cb) (struct wlt_widget *widget, - unsigned int flags, - void *data); -typedef void (*wlt_widget_destroy_cb) (struct wlt_widget *widget, - void *data); -typedef void (*wlt_widget_prepare_resize_cb) (struct wlt_widget *widget, - unsigned int flags, - unsigned int width, - unsigned int height, - unsigned int *min_width, - unsigned int *min_height, - unsigned int *new_width, - unsigned int *new_height, - void *data); -typedef void (*wlt_widget_resize_cb) (struct wlt_widget *widget, - unsigned int flags, - struct wlt_rect *allocation, - void *data); -typedef void (*wlt_widget_pointer_enter_cb) (struct wlt_widget *widget, - unsigned int x, - unsigned int y, - void *data); -typedef void (*wlt_widget_pointer_leave_cb) (struct wlt_widget *widget, - void *data); -typedef void (*wlt_widget_pointer_motion_cb) (struct wlt_widget *widget, - unsigned int x, - unsigned int y, - void *data); -typedef void (*wlt_widget_pointer_button_cb) (struct wlt_widget *widget, - uint32_t button, - uint32_t state, - void *data); -typedef bool (*wlt_widget_keyboard_cb) (struct wlt_widget *widget, - unsigned int mods, - uint32_t key, - uint32_t ascii, - uint32_t state, - bool handled, - void *data); - -int wlt_display_new(struct wlt_display **out, - struct ev_eloop *eloop); -void wlt_display_ref(struct wlt_display *disp); -void wlt_display_unref(struct wlt_display *disp); - -int wlt_display_create_window(struct wlt_display *disp, - struct wlt_window **out, - unsigned int width, - unsigned int height, - void *data); -int wlt_display_register_cb(struct wlt_display *disp, - wlt_display_cb cb, void *data); -void wlt_display_unregister_cb(struct wlt_display *disp, - wlt_display_cb cb, void *data); - -int wlt_display_get_selection_fd(struct wlt_display *disp, const char *mime); -int wlt_display_get_selection_to_fd(struct wlt_display *disp, const char *mime, - int output_fd); -int wlt_display_new_data_source(struct wlt_display *disp, - struct wl_data_source **out); -void wlt_display_set_selection(struct wlt_display *disp, - struct wl_data_source *selection); - -void wlt_window_ref(struct wlt_window *wnd); -void wlt_window_unref(struct wlt_window *wnd); - -int wlt_window_create_widget(struct wlt_window *wnd, - struct wlt_widget **out, - void *data); -void wlt_window_schedule_redraw(struct wlt_window *wnd); -void wlt_window_damage(struct wlt_window *wnd, - struct wlt_rect *damage); -void wlt_window_get_buffer(struct wlt_window *wnd, - const struct wlt_rect *alloc, - struct wlt_shm_buffer *buf); -void wlt_window_move(struct wlt_window *wnd); -void wlt_window_resize(struct wlt_window *wnd, uint32_t edges); -int wlt_window_set_size(struct wlt_window *wnd, - unsigned int width, unsigned int height); -void wlt_window_set_cursor(struct wlt_window *wnd, unsigned int cursor); -void wlt_window_set_close_cb(struct wlt_window *wnd, - wlt_window_close_cb cb); -void wlt_window_close(struct wlt_window *wnd); -void wlt_window_toggle_maximize(struct wlt_window *wnd); -bool wlt_window_is_maximized(struct wlt_window *wnd); -void wlt_window_toggle_fullscreen(struct wlt_window *wnd); -bool wlt_window_is_fullscreen(struct wlt_window *wnd); -struct ev_eloop *wlt_window_get_eloop(struct wlt_window *wnd); -struct wlt_display *wlt_window_get_display(struct wlt_window *wnd); - -void wlt_widget_destroy(struct wlt_widget *widget); -struct wlt_window *wlt_widget_get_window(struct wlt_widget *widget); -void wlt_widget_set_redraw_cb(struct wlt_widget *widget, - wlt_widget_redraw_cb cb); -void wlt_widget_set_destroy_cb(struct wlt_widget *widget, - wlt_widget_destroy_cb cb); -void wlt_widget_set_resize_cb(struct wlt_widget *widget, - wlt_widget_prepare_resize_cb prepare_cb, - wlt_widget_resize_cb cb); -void wlt_widget_set_pointer_cb(struct wlt_widget *widget, - wlt_widget_pointer_enter_cb enter_cb, - wlt_widget_pointer_leave_cb leave_cb, - wlt_widget_pointer_motion_cb motion_cb, - wlt_widget_pointer_button_cb button_cb); -void wlt_widget_set_keyboard_cb(struct wlt_widget *widget, - wlt_widget_keyboard_cb cb); - -static inline bool wlt_rect_contains(struct wlt_rect *rect, - unsigned int x, - unsigned int y) -{ - if (x < rect->x || y < rect->y) - return false; - if (x >= rect->x + rect->width) - return false; - if (y >= rect->y + rect->height) - return false; - return true; -} - -#endif /* WLT_TOOLKIT_H */ |