linux-qubasis

linux oasis port as a qubes template

git clone https://9o.is/git/linux-qubasis.git

0001-Port-to-wayland-using-wld.patch

(125874B)


      1 From 86283aea345fd72e4889eee233daefc41615d979 Mon Sep 17 00:00:00 2001
      2 From: Michael Forney <mforney@mforney.org>
      3 Date: Sun, 30 Oct 2016 23:54:56 -0700
      4 Subject: [PATCH] Port to wayland using wld
      5 
      6 ---
      7  Makefile     |   12 +-
      8  config.def.h |  500 ++++++-----
      9  config.mk    |   12 +-
     10  st.c         | 2366 +++++++++++++++++++++++++-------------------------
     11  4 files changed, 1463 insertions(+), 1427 deletions(-)
     12 
     13 diff --git a/Makefile b/Makefile
     14 index fb026c4..053d3e0 100644
     15 --- a/Makefile
     16 +++ b/Makefile
     17 @@ -3,7 +3,7 @@
     18  
     19  include config.mk
     20  
     21 -SRC = st.c
     22 +SRC = st.c xdg-shell-unstable-v5-protocol.c
     23  OBJ = ${SRC:.c=.o}
     24  
     25  all: options st
     26 @@ -17,6 +17,16 @@ options:
     27  config.h:
     28  	cp config.def.h config.h
     29  
     30 +xdg-shell-unstable-v5-protocol.c:
     31 +	@echo GEN $@
     32 +	@wayland-scanner code ${XDG_SHELL_PROTO} $@
     33 +
     34 +xdg-shell-unstable-v5-client-protocol.h:
     35 +	@echo GEN $@
     36 +	@wayland-scanner client-header ${XDG_SHELL_PROTO} $@
     37 +
     38 +st.o: xdg-shell-unstable-v5-client-protocol.h
     39 +
     40  .c.o:
     41  	@echo CC $<
     42  	@${CC} -c ${CFLAGS} $<
     43 diff --git a/config.def.h b/config.def.h
     44 index a719e36..49ca50b 100644
     45 --- a/config.def.h
     46 +++ b/config.def.h
     47 @@ -38,13 +38,13 @@ static char worddelimiters[] = " ";
     48  static unsigned int doubleclicktimeout = 300;
     49  static unsigned int tripleclicktimeout = 600;
     50  
     51 +/* key repeat timeouts (in milliseconds) */
     52 +static unsigned int keyrepeatdelay = 500;
     53 +static unsigned int keyrepeatinterval = 25;
     54 +
     55  /* alt screens */
     56  static int allowaltscreen = 1;
     57  
     58 -/* frames per second st should at maximum draw to the screen */
     59 -static unsigned int xfps = 120;
     60 -static unsigned int actionfps = 30;
     61 -
     62  /*
     63   * blinking timeout (set to 0 to disable blinking) for the terminal blinking
     64   * attribute.
     65 @@ -60,7 +60,9 @@ static unsigned int cursorthickness = 2;
     66   * bell volume. It must be a value between -100 and 100. Use 0 for disabling
     67   * it
     68   */
     69 -static int bellvolume = 0;
     70 +/* XXX: Wayland does not have a bell.
     71 + * static int bellvolume = 0;
     72 + */
     73  
     74  /* default TERM value */
     75  static char termname[] = "st-256color";
     76 @@ -138,11 +140,9 @@ static unsigned int cols = 80;
     77  static unsigned int rows = 24;
     78  
     79  /*
     80 - * Default colour and shape of the mouse cursor
     81 + * Default shape of the mouse cursor
     82   */
     83 -static unsigned int mouseshape = XC_xterm;
     84 -static unsigned int mousefg = 7;
     85 -static unsigned int mousebg = 0;
     86 +static char mouseshape[] = "xterm";
     87  
     88  /*
     89   * Color used to display font attributes when fontconfig selected a font which
     90 @@ -156,36 +156,38 @@ static unsigned int defaultattr = 11;
     91   */
     92  static MouseShortcut mshortcuts[] = {
     93  	/* button               mask            string */
     94 -	{ Button4,              XK_ANY_MOD,     "\031" },
     95 -	{ Button5,              XK_ANY_MOD,     "\005" },
     96 +	{ -1,                   MOD_MASK_NONE,  "" }
     97 +};
     98 +
     99 +static Axiskey ashortcuts[] = {
    100 +	/* axis		    direction	mask		string */
    101 +	{ AXIS_VERTICAL,    +1,		MOD_MASK_ANY,	"\031"},
    102 +	{ AXIS_VERTICAL,    -1,		MOD_MASK_ANY,	"\005"},
    103  };
    104  
    105  /* Internal keyboard shortcuts. */
    106 -#define MODKEY Mod1Mask
    107 +#define MODKEY MOD_MASK_ALT
    108  
    109  static Shortcut shortcuts[] = {
    110 -	/* mask                 keysym          function        argument */
    111 -	{ XK_ANY_MOD,           XK_Break,       sendbreak,      {.i =  0} },
    112 -	{ ControlMask,          XK_Print,       toggleprinter,  {.i =  0} },
    113 -	{ ShiftMask,            XK_Print,       printscreen,    {.i =  0} },
    114 -	{ XK_ANY_MOD,           XK_Print,       printsel,       {.i =  0} },
    115 -	{ MODKEY|ShiftMask,     XK_Prior,       xzoom,          {.f = +1} },
    116 -	{ MODKEY|ShiftMask,     XK_Next,        xzoom,          {.f = -1} },
    117 -	{ MODKEY|ShiftMask,     XK_Home,        xzoomreset,     {.f =  0} },
    118 -	{ ShiftMask,            XK_Insert,      selpaste,       {.i =  0} },
    119 -	{ MODKEY|ShiftMask,     XK_Insert,      clippaste,      {.i =  0} },
    120 -	{ MODKEY|ShiftMask,     XK_C,           clipcopy,       {.i =  0} },
    121 -	{ MODKEY|ShiftMask,     XK_V,           clippaste,      {.i =  0} },
    122 -	{ MODKEY,               XK_Num_Lock,    numlock,        {.i =  0} },
    123 -	{ MODKEY,               XK_Control_L,   iso14755,       {.i =  0} },
    124 +	/* modifier                     key                     function        argument */
    125 +	{ MOD_MASK_ANY,                 XKB_KEY_Break,          sendbreak,      {.i =  0} },
    126 +	{ MOD_MASK_CTRL,                XKB_KEY_Print,          toggleprinter,  {.i =  0} },
    127 +	{ MOD_MASK_SHIFT,               XKB_KEY_Print,          printscreen,    {.i =  0} },
    128 +	{ MOD_MASK_ANY,                 XKB_KEY_Print,          printsel,       {.i =  0} },
    129 +	{ MODKEY|MOD_MASK_SHIFT,        XKB_KEY_Prior,          wlzoom,         {.f = +1} },
    130 +	{ MODKEY|MOD_MASK_SHIFT,        XKB_KEY_Next,           wlzoom,         {.f = -1} },
    131 +	{ MODKEY|MOD_MASK_SHIFT,        XKB_KEY_Home,           wlzoomreset,    {.f =  0} },
    132 +	{ MOD_MASK_SHIFT,               XKB_KEY_Insert,         selpaste,       {.i =  0} },
    133 +	{ MODKEY,                       XKB_KEY_Num_Lock,       numlock,        {.i =  0} },
    134 +	{ MODKEY,                       XKB_KEY_Control_L,      iso14755,       {.i =  0} },
    135  };
    136  
    137  /*
    138   * Special keys (change & recompile st.info accordingly)
    139   *
    140   * Mask value:
    141 - * * Use XK_ANY_MOD to match the key no matter modifiers state
    142 - * * Use XK_NO_MOD to match the key alone (no modifiers)
    143 + * * Use MOD_MASK_ANY to match the key no matter modifiers state
    144 + * * Use MOD_MASK_NONE to match the key alone (no modifiers)
    145   * appkey value:
    146   * * 0: no value
    147   * * > 0: keypad application mode enabled
    148 @@ -201,7 +203,7 @@ static Shortcut shortcuts[] = {
    149   * * < 0: crlf mode is disabled
    150   *
    151   * Be careful with the order of the definitions because st searches in
    152 - * this table sequentially, so any XK_ANY_MOD must be in the last
    153 + * this table sequentially, so any MOD_MASK_ANY must be in the last
    154   * position for a key.
    155   */
    156  
    157 @@ -209,239 +211,233 @@ static Shortcut shortcuts[] = {
    158   * If you want keys other than the X11 function keys (0xFD00 - 0xFFFF)
    159   * to be mapped below, add them to this array.
    160   */
    161 -static KeySym mappedkeys[] = { -1 };
    162 +static xkb_keysym_t mappedkeys[] = { -1 };
    163  
    164 -/*
    165 - * State bits to ignore when matching key or button events.  By default,
    166 - * numlock (Mod2Mask) and keyboard layout (XK_SWITCH_MOD) are ignored.
    167 - */
    168 -static uint ignoremod = Mod2Mask|XK_SWITCH_MOD;
    169 +/* State bits to ignore when matching key or button events. */
    170 +static uint ignoremod = 0;
    171  
    172  /*
    173   * Override mouse-select while mask is active (when MODE_MOUSE is set).
    174 - * Note that if you want to use ShiftMask with selmasks, set this to an other
    175 - * modifier, set to 0 to not use it.
    176 + * Note that if you want to use MOD_MASK_SHIFT with selmasks, set this to an
    177 + * other modifier, set to 0 to not use it.
    178   */
    179 -static uint forceselmod = ShiftMask;
    180 +static uint forceselmod = MOD_MASK_SHIFT;
    181  
    182  /*
    183   * This is the huge key array which defines all compatibility to the Linux
    184   * world. Please decide about changes wisely.
    185   */
    186  static Key key[] = {
    187 -	/* keysym           mask            string      appkey appcursor crlf */
    188 -	{ XK_KP_Home,       ShiftMask,      "\033[2J",       0,   -1,    0},
    189 -	{ XK_KP_Home,       ShiftMask,      "\033[1;2H",     0,   +1,    0},
    190 -	{ XK_KP_Home,       XK_ANY_MOD,     "\033[H",        0,   -1,    0},
    191 -	{ XK_KP_Home,       XK_ANY_MOD,     "\033[1~",       0,   +1,    0},
    192 -	{ XK_KP_Up,         XK_ANY_MOD,     "\033Ox",       +1,    0,    0},
    193 -	{ XK_KP_Up,         XK_ANY_MOD,     "\033[A",        0,   -1,    0},
    194 -	{ XK_KP_Up,         XK_ANY_MOD,     "\033OA",        0,   +1,    0},
    195 -	{ XK_KP_Down,       XK_ANY_MOD,     "\033Or",       +1,    0,    0},
    196 -	{ XK_KP_Down,       XK_ANY_MOD,     "\033[B",        0,   -1,    0},
    197 -	{ XK_KP_Down,       XK_ANY_MOD,     "\033OB",        0,   +1,    0},
    198 -	{ XK_KP_Left,       XK_ANY_MOD,     "\033Ot",       +1,    0,    0},
    199 -	{ XK_KP_Left,       XK_ANY_MOD,     "\033[D",        0,   -1,    0},
    200 -	{ XK_KP_Left,       XK_ANY_MOD,     "\033OD",        0,   +1,    0},
    201 -	{ XK_KP_Right,      XK_ANY_MOD,     "\033Ov",       +1,    0,    0},
    202 -	{ XK_KP_Right,      XK_ANY_MOD,     "\033[C",        0,   -1,    0},
    203 -	{ XK_KP_Right,      XK_ANY_MOD,     "\033OC",        0,   +1,    0},
    204 -	{ XK_KP_Prior,      ShiftMask,      "\033[5;2~",     0,    0,    0},
    205 -	{ XK_KP_Prior,      XK_ANY_MOD,     "\033[5~",       0,    0,    0},
    206 -	{ XK_KP_Begin,      XK_ANY_MOD,     "\033[E",        0,    0,    0},
    207 -	{ XK_KP_End,        ControlMask,    "\033[J",       -1,    0,    0},
    208 -	{ XK_KP_End,        ControlMask,    "\033[1;5F",    +1,    0,    0},
    209 -	{ XK_KP_End,        ShiftMask,      "\033[K",       -1,    0,    0},
    210 -	{ XK_KP_End,        ShiftMask,      "\033[1;2F",    +1,    0,    0},
    211 -	{ XK_KP_End,        XK_ANY_MOD,     "\033[4~",       0,    0,    0},
    212 -	{ XK_KP_Next,       ShiftMask,      "\033[6;2~",     0,    0,    0},
    213 -	{ XK_KP_Next,       XK_ANY_MOD,     "\033[6~",       0,    0,    0},
    214 -	{ XK_KP_Insert,     ShiftMask,      "\033[2;2~",    +1,    0,    0},
    215 -	{ XK_KP_Insert,     ShiftMask,      "\033[4l",      -1,    0,    0},
    216 -	{ XK_KP_Insert,     ControlMask,    "\033[L",       -1,    0,    0},
    217 -	{ XK_KP_Insert,     ControlMask,    "\033[2;5~",    +1,    0,    0},
    218 -	{ XK_KP_Insert,     XK_ANY_MOD,     "\033[4h",      -1,    0,    0},
    219 -	{ XK_KP_Insert,     XK_ANY_MOD,     "\033[2~",      +1,    0,    0},
    220 -	{ XK_KP_Delete,     ControlMask,    "\033[M",       -1,    0,    0},
    221 -	{ XK_KP_Delete,     ControlMask,    "\033[3;5~",    +1,    0,    0},
    222 -	{ XK_KP_Delete,     ShiftMask,      "\033[2K",      -1,    0,    0},
    223 -	{ XK_KP_Delete,     ShiftMask,      "\033[3;2~",    +1,    0,    0},
    224 -	{ XK_KP_Delete,     XK_ANY_MOD,     "\033[P",       -1,    0,    0},
    225 -	{ XK_KP_Delete,     XK_ANY_MOD,     "\033[3~",      +1,    0,    0},
    226 -	{ XK_KP_Multiply,   XK_ANY_MOD,     "\033Oj",       +2,    0,    0},
    227 -	{ XK_KP_Add,        XK_ANY_MOD,     "\033Ok",       +2,    0,    0},
    228 -	{ XK_KP_Enter,      XK_ANY_MOD,     "\033OM",       +2,    0,    0},
    229 -	{ XK_KP_Enter,      XK_ANY_MOD,     "\r",           -1,    0,   -1},
    230 -	{ XK_KP_Enter,      XK_ANY_MOD,     "\r\n",         -1,    0,   +1},
    231 -	{ XK_KP_Subtract,   XK_ANY_MOD,     "\033Om",       +2,    0,    0},
    232 -	{ XK_KP_Decimal,    XK_ANY_MOD,     "\033On",       +2,    0,    0},
    233 -	{ XK_KP_Divide,     XK_ANY_MOD,     "\033Oo",       +2,    0,    0},
    234 -	{ XK_KP_0,          XK_ANY_MOD,     "\033Op",       +2,    0,    0},
    235 -	{ XK_KP_1,          XK_ANY_MOD,     "\033Oq",       +2,    0,    0},
    236 -	{ XK_KP_2,          XK_ANY_MOD,     "\033Or",       +2,    0,    0},
    237 -	{ XK_KP_3,          XK_ANY_MOD,     "\033Os",       +2,    0,    0},
    238 -	{ XK_KP_4,          XK_ANY_MOD,     "\033Ot",       +2,    0,    0},
    239 -	{ XK_KP_5,          XK_ANY_MOD,     "\033Ou",       +2,    0,    0},
    240 -	{ XK_KP_6,          XK_ANY_MOD,     "\033Ov",       +2,    0,    0},
    241 -	{ XK_KP_7,          XK_ANY_MOD,     "\033Ow",       +2,    0,    0},
    242 -	{ XK_KP_8,          XK_ANY_MOD,     "\033Ox",       +2,    0,    0},
    243 -	{ XK_KP_9,          XK_ANY_MOD,     "\033Oy",       +2,    0,    0},
    244 -	{ XK_Up,            ShiftMask,      "\033[1;2A",     0,    0,    0},
    245 -	{ XK_Up,            Mod1Mask,       "\033[1;3A",     0,    0,    0},
    246 -	{ XK_Up,         ShiftMask|Mod1Mask,"\033[1;4A",     0,    0,    0},
    247 -	{ XK_Up,            ControlMask,    "\033[1;5A",     0,    0,    0},
    248 -	{ XK_Up,      ShiftMask|ControlMask,"\033[1;6A",     0,    0,    0},
    249 -	{ XK_Up,       ControlMask|Mod1Mask,"\033[1;7A",     0,    0,    0},
    250 -	{ XK_Up,ShiftMask|ControlMask|Mod1Mask,"\033[1;8A",  0,    0,    0},
    251 -	{ XK_Up,            XK_ANY_MOD,     "\033[A",        0,   -1,    0},
    252 -	{ XK_Up,            XK_ANY_MOD,     "\033OA",        0,   +1,    0},
    253 -	{ XK_Down,          ShiftMask,      "\033[1;2B",     0,    0,    0},
    254 -	{ XK_Down,          Mod1Mask,       "\033[1;3B",     0,    0,    0},
    255 -	{ XK_Down,       ShiftMask|Mod1Mask,"\033[1;4B",     0,    0,    0},
    256 -	{ XK_Down,          ControlMask,    "\033[1;5B",     0,    0,    0},
    257 -	{ XK_Down,    ShiftMask|ControlMask,"\033[1;6B",     0,    0,    0},
    258 -	{ XK_Down,     ControlMask|Mod1Mask,"\033[1;7B",     0,    0,    0},
    259 -	{ XK_Down,ShiftMask|ControlMask|Mod1Mask,"\033[1;8B",0,    0,    0},
    260 -	{ XK_Down,          XK_ANY_MOD,     "\033[B",        0,   -1,    0},
    261 -	{ XK_Down,          XK_ANY_MOD,     "\033OB",        0,   +1,    0},
    262 -	{ XK_Left,          ShiftMask,      "\033[1;2D",     0,    0,    0},
    263 -	{ XK_Left,          Mod1Mask,       "\033[1;3D",     0,    0,    0},
    264 -	{ XK_Left,       ShiftMask|Mod1Mask,"\033[1;4D",     0,    0,    0},
    265 -	{ XK_Left,          ControlMask,    "\033[1;5D",     0,    0,    0},
    266 -	{ XK_Left,    ShiftMask|ControlMask,"\033[1;6D",     0,    0,    0},
    267 -	{ XK_Left,     ControlMask|Mod1Mask,"\033[1;7D",     0,    0,    0},
    268 -	{ XK_Left,ShiftMask|ControlMask|Mod1Mask,"\033[1;8D",0,    0,    0},
    269 -	{ XK_Left,          XK_ANY_MOD,     "\033[D",        0,   -1,    0},
    270 -	{ XK_Left,          XK_ANY_MOD,     "\033OD",        0,   +1,    0},
    271 -	{ XK_Right,         ShiftMask,      "\033[1;2C",     0,    0,    0},
    272 -	{ XK_Right,         Mod1Mask,       "\033[1;3C",     0,    0,    0},
    273 -	{ XK_Right,      ShiftMask|Mod1Mask,"\033[1;4C",     0,    0,    0},
    274 -	{ XK_Right,         ControlMask,    "\033[1;5C",     0,    0,    0},
    275 -	{ XK_Right,   ShiftMask|ControlMask,"\033[1;6C",     0,    0,    0},
    276 -	{ XK_Right,    ControlMask|Mod1Mask,"\033[1;7C",     0,    0,    0},
    277 -	{ XK_Right,ShiftMask|ControlMask|Mod1Mask,"\033[1;8C",0,   0,    0},
    278 -	{ XK_Right,         XK_ANY_MOD,     "\033[C",        0,   -1,    0},
    279 -	{ XK_Right,         XK_ANY_MOD,     "\033OC",        0,   +1,    0},
    280 -	{ XK_ISO_Left_Tab,  ShiftMask,      "\033[Z",        0,    0,    0},
    281 -	{ XK_Return,        Mod1Mask,       "\033\r",        0,    0,   -1},
    282 -	{ XK_Return,        Mod1Mask,       "\033\r\n",      0,    0,   +1},
    283 -	{ XK_Return,        XK_ANY_MOD,     "\r",            0,    0,   -1},
    284 -	{ XK_Return,        XK_ANY_MOD,     "\r\n",          0,    0,   +1},
    285 -	{ XK_Insert,        ShiftMask,      "\033[4l",      -1,    0,    0},
    286 -	{ XK_Insert,        ShiftMask,      "\033[2;2~",    +1,    0,    0},
    287 -	{ XK_Insert,        ControlMask,    "\033[L",       -1,    0,    0},
    288 -	{ XK_Insert,        ControlMask,    "\033[2;5~",    +1,    0,    0},
    289 -	{ XK_Insert,        XK_ANY_MOD,     "\033[4h",      -1,    0,    0},
    290 -	{ XK_Insert,        XK_ANY_MOD,     "\033[2~",      +1,    0,    0},
    291 -	{ XK_Delete,        ControlMask,    "\033[M",       -1,    0,    0},
    292 -	{ XK_Delete,        ControlMask,    "\033[3;5~",    +1,    0,    0},
    293 -	{ XK_Delete,        ShiftMask,      "\033[2K",      -1,    0,    0},
    294 -	{ XK_Delete,        ShiftMask,      "\033[3;2~",    +1,    0,    0},
    295 -	{ XK_Delete,        XK_ANY_MOD,     "\033[P",       -1,    0,    0},
    296 -	{ XK_Delete,        XK_ANY_MOD,     "\033[3~",      +1,    0,    0},
    297 -	{ XK_BackSpace,     XK_NO_MOD,      "\177",          0,    0,    0},
    298 -	{ XK_BackSpace,     Mod1Mask,       "\033\177",      0,    0,    0},
    299 -	{ XK_Home,          ShiftMask,      "\033[2J",       0,   -1,    0},
    300 -	{ XK_Home,          ShiftMask,      "\033[1;2H",     0,   +1,    0},
    301 -	{ XK_Home,          XK_ANY_MOD,     "\033[H",        0,   -1,    0},
    302 -	{ XK_Home,          XK_ANY_MOD,     "\033[1~",       0,   +1,    0},
    303 -	{ XK_End,           ControlMask,    "\033[J",       -1,    0,    0},
    304 -	{ XK_End,           ControlMask,    "\033[1;5F",    +1,    0,    0},
    305 -	{ XK_End,           ShiftMask,      "\033[K",       -1,    0,    0},
    306 -	{ XK_End,           ShiftMask,      "\033[1;2F",    +1,    0,    0},
    307 -	{ XK_End,           XK_ANY_MOD,     "\033[4~",       0,    0,    0},
    308 -	{ XK_Prior,         ControlMask,    "\033[5;5~",     0,    0,    0},
    309 -	{ XK_Prior,         ShiftMask,      "\033[5;2~",     0,    0,    0},
    310 -	{ XK_Prior,         XK_ANY_MOD,     "\033[5~",       0,    0,    0},
    311 -	{ XK_Next,          ControlMask,    "\033[6;5~",     0,    0,    0},
    312 -	{ XK_Next,          ShiftMask,      "\033[6;2~",     0,    0,    0},
    313 -	{ XK_Next,          XK_ANY_MOD,     "\033[6~",       0,    0,    0},
    314 -	{ XK_F1,            XK_NO_MOD,      "\033OP" ,       0,    0,    0},
    315 -	{ XK_F1, /* F13 */  ShiftMask,      "\033[1;2P",     0,    0,    0},
    316 -	{ XK_F1, /* F25 */  ControlMask,    "\033[1;5P",     0,    0,    0},
    317 -	{ XK_F1, /* F37 */  Mod4Mask,       "\033[1;6P",     0,    0,    0},
    318 -	{ XK_F1, /* F49 */  Mod1Mask,       "\033[1;3P",     0,    0,    0},
    319 -	{ XK_F1, /* F61 */  Mod3Mask,       "\033[1;4P",     0,    0,    0},
    320 -	{ XK_F2,            XK_NO_MOD,      "\033OQ" ,       0,    0,    0},
    321 -	{ XK_F2, /* F14 */  ShiftMask,      "\033[1;2Q",     0,    0,    0},
    322 -	{ XK_F2, /* F26 */  ControlMask,    "\033[1;5Q",     0,    0,    0},
    323 -	{ XK_F2, /* F38 */  Mod4Mask,       "\033[1;6Q",     0,    0,    0},
    324 -	{ XK_F2, /* F50 */  Mod1Mask,       "\033[1;3Q",     0,    0,    0},
    325 -	{ XK_F2, /* F62 */  Mod3Mask,       "\033[1;4Q",     0,    0,    0},
    326 -	{ XK_F3,            XK_NO_MOD,      "\033OR" ,       0,    0,    0},
    327 -	{ XK_F3, /* F15 */  ShiftMask,      "\033[1;2R",     0,    0,    0},
    328 -	{ XK_F3, /* F27 */  ControlMask,    "\033[1;5R",     0,    0,    0},
    329 -	{ XK_F3, /* F39 */  Mod4Mask,       "\033[1;6R",     0,    0,    0},
    330 -	{ XK_F3, /* F51 */  Mod1Mask,       "\033[1;3R",     0,    0,    0},
    331 -	{ XK_F3, /* F63 */  Mod3Mask,       "\033[1;4R",     0,    0,    0},
    332 -	{ XK_F4,            XK_NO_MOD,      "\033OS" ,       0,    0,    0},
    333 -	{ XK_F4, /* F16 */  ShiftMask,      "\033[1;2S",     0,    0,    0},
    334 -	{ XK_F4, /* F28 */  ControlMask,    "\033[1;5S",     0,    0,    0},
    335 -	{ XK_F4, /* F40 */  Mod4Mask,       "\033[1;6S",     0,    0,    0},
    336 -	{ XK_F4, /* F52 */  Mod1Mask,       "\033[1;3S",     0,    0,    0},
    337 -	{ XK_F5,            XK_NO_MOD,      "\033[15~",      0,    0,    0},
    338 -	{ XK_F5, /* F17 */  ShiftMask,      "\033[15;2~",    0,    0,    0},
    339 -	{ XK_F5, /* F29 */  ControlMask,    "\033[15;5~",    0,    0,    0},
    340 -	{ XK_F5, /* F41 */  Mod4Mask,       "\033[15;6~",    0,    0,    0},
    341 -	{ XK_F5, /* F53 */  Mod1Mask,       "\033[15;3~",    0,    0,    0},
    342 -	{ XK_F6,            XK_NO_MOD,      "\033[17~",      0,    0,    0},
    343 -	{ XK_F6, /* F18 */  ShiftMask,      "\033[17;2~",    0,    0,    0},
    344 -	{ XK_F6, /* F30 */  ControlMask,    "\033[17;5~",    0,    0,    0},
    345 -	{ XK_F6, /* F42 */  Mod4Mask,       "\033[17;6~",    0,    0,    0},
    346 -	{ XK_F6, /* F54 */  Mod1Mask,       "\033[17;3~",    0,    0,    0},
    347 -	{ XK_F7,            XK_NO_MOD,      "\033[18~",      0,    0,    0},
    348 -	{ XK_F7, /* F19 */  ShiftMask,      "\033[18;2~",    0,    0,    0},
    349 -	{ XK_F7, /* F31 */  ControlMask,    "\033[18;5~",    0,    0,    0},
    350 -	{ XK_F7, /* F43 */  Mod4Mask,       "\033[18;6~",    0,    0,    0},
    351 -	{ XK_F7, /* F55 */  Mod1Mask,       "\033[18;3~",    0,    0,    0},
    352 -	{ XK_F8,            XK_NO_MOD,      "\033[19~",      0,    0,    0},
    353 -	{ XK_F8, /* F20 */  ShiftMask,      "\033[19;2~",    0,    0,    0},
    354 -	{ XK_F8, /* F32 */  ControlMask,    "\033[19;5~",    0,    0,    0},
    355 -	{ XK_F8, /* F44 */  Mod4Mask,       "\033[19;6~",    0,    0,    0},
    356 -	{ XK_F8, /* F56 */  Mod1Mask,       "\033[19;3~",    0,    0,    0},
    357 -	{ XK_F9,            XK_NO_MOD,      "\033[20~",      0,    0,    0},
    358 -	{ XK_F9, /* F21 */  ShiftMask,      "\033[20;2~",    0,    0,    0},
    359 -	{ XK_F9, /* F33 */  ControlMask,    "\033[20;5~",    0,    0,    0},
    360 -	{ XK_F9, /* F45 */  Mod4Mask,       "\033[20;6~",    0,    0,    0},
    361 -	{ XK_F9, /* F57 */  Mod1Mask,       "\033[20;3~",    0,    0,    0},
    362 -	{ XK_F10,           XK_NO_MOD,      "\033[21~",      0,    0,    0},
    363 -	{ XK_F10, /* F22 */ ShiftMask,      "\033[21;2~",    0,    0,    0},
    364 -	{ XK_F10, /* F34 */ ControlMask,    "\033[21;5~",    0,    0,    0},
    365 -	{ XK_F10, /* F46 */ Mod4Mask,       "\033[21;6~",    0,    0,    0},
    366 -	{ XK_F10, /* F58 */ Mod1Mask,       "\033[21;3~",    0,    0,    0},
    367 -	{ XK_F11,           XK_NO_MOD,      "\033[23~",      0,    0,    0},
    368 -	{ XK_F11, /* F23 */ ShiftMask,      "\033[23;2~",    0,    0,    0},
    369 -	{ XK_F11, /* F35 */ ControlMask,    "\033[23;5~",    0,    0,    0},
    370 -	{ XK_F11, /* F47 */ Mod4Mask,       "\033[23;6~",    0,    0,    0},
    371 -	{ XK_F11, /* F59 */ Mod1Mask,       "\033[23;3~",    0,    0,    0},
    372 -	{ XK_F12,           XK_NO_MOD,      "\033[24~",      0,    0,    0},
    373 -	{ XK_F12, /* F24 */ ShiftMask,      "\033[24;2~",    0,    0,    0},
    374 -	{ XK_F12, /* F36 */ ControlMask,    "\033[24;5~",    0,    0,    0},
    375 -	{ XK_F12, /* F48 */ Mod4Mask,       "\033[24;6~",    0,    0,    0},
    376 -	{ XK_F12, /* F60 */ Mod1Mask,       "\033[24;3~",    0,    0,    0},
    377 -	{ XK_F13,           XK_NO_MOD,      "\033[1;2P",     0,    0,    0},
    378 -	{ XK_F14,           XK_NO_MOD,      "\033[1;2Q",     0,    0,    0},
    379 -	{ XK_F15,           XK_NO_MOD,      "\033[1;2R",     0,    0,    0},
    380 -	{ XK_F16,           XK_NO_MOD,      "\033[1;2S",     0,    0,    0},
    381 -	{ XK_F17,           XK_NO_MOD,      "\033[15;2~",    0,    0,    0},
    382 -	{ XK_F18,           XK_NO_MOD,      "\033[17;2~",    0,    0,    0},
    383 -	{ XK_F19,           XK_NO_MOD,      "\033[18;2~",    0,    0,    0},
    384 -	{ XK_F20,           XK_NO_MOD,      "\033[19;2~",    0,    0,    0},
    385 -	{ XK_F21,           XK_NO_MOD,      "\033[20;2~",    0,    0,    0},
    386 -	{ XK_F22,           XK_NO_MOD,      "\033[21;2~",    0,    0,    0},
    387 -	{ XK_F23,           XK_NO_MOD,      "\033[23;2~",    0,    0,    0},
    388 -	{ XK_F24,           XK_NO_MOD,      "\033[24;2~",    0,    0,    0},
    389 -	{ XK_F25,           XK_NO_MOD,      "\033[1;5P",     0,    0,    0},
    390 -	{ XK_F26,           XK_NO_MOD,      "\033[1;5Q",     0,    0,    0},
    391 -	{ XK_F27,           XK_NO_MOD,      "\033[1;5R",     0,    0,    0},
    392 -	{ XK_F28,           XK_NO_MOD,      "\033[1;5S",     0,    0,    0},
    393 -	{ XK_F29,           XK_NO_MOD,      "\033[15;5~",    0,    0,    0},
    394 -	{ XK_F30,           XK_NO_MOD,      "\033[17;5~",    0,    0,    0},
    395 -	{ XK_F31,           XK_NO_MOD,      "\033[18;5~",    0,    0,    0},
    396 -	{ XK_F32,           XK_NO_MOD,      "\033[19;5~",    0,    0,    0},
    397 -	{ XK_F33,           XK_NO_MOD,      "\033[20;5~",    0,    0,    0},
    398 -	{ XK_F34,           XK_NO_MOD,      "\033[21;5~",    0,    0,    0},
    399 -	{ XK_F35,           XK_NO_MOD,      "\033[23;5~",    0,    0,    0},
    400 +	/* keysym                mask             string      appkey appcursor crlf */
    401 +	{ XKB_KEY_KP_Home,       MOD_MASK_SHIFT,  "\033[2J",       0,   -1,    0},
    402 +	{ XKB_KEY_KP_Home,       MOD_MASK_SHIFT,  "\033[1;2H",     0,   +1,    0},
    403 +	{ XKB_KEY_KP_Home,       MOD_MASK_ANY,    "\033[H",        0,   -1,    0},
    404 +	{ XKB_KEY_KP_Home,       MOD_MASK_ANY,    "\033[1~",       0,   +1,    0},
    405 +	{ XKB_KEY_KP_Up,         MOD_MASK_ANY,    "\033Ox",       +1,    0,    0},
    406 +	{ XKB_KEY_KP_Up,         MOD_MASK_ANY,    "\033[A",        0,   -1,    0},
    407 +	{ XKB_KEY_KP_Up,         MOD_MASK_ANY,    "\033OA",        0,   +1,    0},
    408 +	{ XKB_KEY_KP_Down,       MOD_MASK_ANY,    "\033Or",       +1,    0,    0},
    409 +	{ XKB_KEY_KP_Down,       MOD_MASK_ANY,    "\033[B",        0,   -1,    0},
    410 +	{ XKB_KEY_KP_Down,       MOD_MASK_ANY,    "\033OB",        0,   +1,    0},
    411 +	{ XKB_KEY_KP_Left,       MOD_MASK_ANY,    "\033Ot",       +1,    0,    0},
    412 +	{ XKB_KEY_KP_Left,       MOD_MASK_ANY,    "\033[D",        0,   -1,    0},
    413 +	{ XKB_KEY_KP_Left,       MOD_MASK_ANY,    "\033OD",        0,   +1,    0},
    414 +	{ XKB_KEY_KP_Right,      MOD_MASK_ANY,    "\033Ov",       +1,    0,    0},
    415 +	{ XKB_KEY_KP_Right,      MOD_MASK_ANY,    "\033[C",        0,   -1,    0},
    416 +	{ XKB_KEY_KP_Right,      MOD_MASK_ANY,    "\033OC",        0,   +1,    0},
    417 +	{ XKB_KEY_KP_Prior,      MOD_MASK_SHIFT,  "\033[5;2~",     0,    0,    0},
    418 +	{ XKB_KEY_KP_Prior,      MOD_MASK_ANY,    "\033[5~",       0,    0,    0},
    419 +	{ XKB_KEY_KP_Begin,      MOD_MASK_ANY,    "\033[E",        0,    0,    0},
    420 +	{ XKB_KEY_KP_End,        MOD_MASK_CTRL,   "\033[J",       -1,    0,    0},
    421 +	{ XKB_KEY_KP_End,        MOD_MASK_CTRL,   "\033[1;5F",    +1,    0,    0},
    422 +	{ XKB_KEY_KP_End,        MOD_MASK_SHIFT,  "\033[K",       -1,    0,    0},
    423 +	{ XKB_KEY_KP_End,        MOD_MASK_SHIFT,  "\033[1;2F",    +1,    0,    0},
    424 +	{ XKB_KEY_KP_End,        MOD_MASK_ANY,    "\033[4~",       0,    0,    0},
    425 +	{ XKB_KEY_KP_Next,       MOD_MASK_SHIFT,  "\033[6;2~",     0,    0,    0},
    426 +	{ XKB_KEY_KP_Next,       MOD_MASK_ANY,    "\033[6~",       0,    0,    0},
    427 +	{ XKB_KEY_KP_Insert,     MOD_MASK_SHIFT,  "\033[2;2~",    +1,    0,    0},
    428 +	{ XKB_KEY_KP_Insert,     MOD_MASK_SHIFT,  "\033[4l",      -1,    0,    0},
    429 +	{ XKB_KEY_KP_Insert,     MOD_MASK_CTRL,   "\033[L",       -1,    0,    0},
    430 +	{ XKB_KEY_KP_Insert,     MOD_MASK_CTRL,   "\033[2;5~",    +1,    0,    0},
    431 +	{ XKB_KEY_KP_Insert,     MOD_MASK_ANY,    "\033[4h",      -1,    0,    0},
    432 +	{ XKB_KEY_KP_Insert,     MOD_MASK_ANY,    "\033[2~",      +1,    0,    0},
    433 +	{ XKB_KEY_KP_Delete,     MOD_MASK_CTRL,   "\033[M",       -1,    0,    0},
    434 +	{ XKB_KEY_KP_Delete,     MOD_MASK_CTRL,   "\033[3;5~",    +1,    0,    0},
    435 +	{ XKB_KEY_KP_Delete,     MOD_MASK_SHIFT,  "\033[2K",      -1,    0,    0},
    436 +	{ XKB_KEY_KP_Delete,     MOD_MASK_SHIFT,  "\033[3;2~",    +1,    0,    0},
    437 +	{ XKB_KEY_KP_Delete,     MOD_MASK_ANY,    "\033[P",       -1,    0,    0},
    438 +	{ XKB_KEY_KP_Delete,     MOD_MASK_ANY,    "\033[3~",      +1,    0,    0},
    439 +	{ XKB_KEY_KP_Multiply,   MOD_MASK_ANY,    "\033Oj",       +2,    0,    0},
    440 +	{ XKB_KEY_KP_Add,        MOD_MASK_ANY,    "\033Ok",       +2,    0,    0},
    441 +	{ XKB_KEY_KP_Enter,      MOD_MASK_ANY,    "\033OM",       +2,    0,    0},
    442 +	{ XKB_KEY_KP_Enter,      MOD_MASK_ANY,    "\r",           -1,    0,   -1},
    443 +	{ XKB_KEY_KP_Enter,      MOD_MASK_ANY,    "\r\n",         -1,    0,   +1},
    444 +	{ XKB_KEY_KP_Subtract,   MOD_MASK_ANY,    "\033Om",       +2,    0,    0},
    445 +	{ XKB_KEY_KP_Decimal,    MOD_MASK_ANY,    "\033On",       +2,    0,    0},
    446 +	{ XKB_KEY_KP_Divide,     MOD_MASK_ANY,    "\033Oo",       +2,    0,    0},
    447 +	{ XKB_KEY_KP_0,          MOD_MASK_ANY,    "\033Op",       +2,    0,    0},
    448 +	{ XKB_KEY_KP_1,          MOD_MASK_ANY,    "\033Oq",       +2,    0,    0},
    449 +	{ XKB_KEY_KP_2,          MOD_MASK_ANY,    "\033Or",       +2,    0,    0},
    450 +	{ XKB_KEY_KP_3,          MOD_MASK_ANY,    "\033Os",       +2,    0,    0},
    451 +	{ XKB_KEY_KP_4,          MOD_MASK_ANY,    "\033Ot",       +2,    0,    0},
    452 +	{ XKB_KEY_KP_5,          MOD_MASK_ANY,    "\033Ou",       +2,    0,    0},
    453 +	{ XKB_KEY_KP_6,          MOD_MASK_ANY,    "\033Ov",       +2,    0,    0},
    454 +	{ XKB_KEY_KP_7,          MOD_MASK_ANY,    "\033Ow",       +2,    0,    0},
    455 +	{ XKB_KEY_KP_8,          MOD_MASK_ANY,    "\033Ox",       +2,    0,    0},
    456 +	{ XKB_KEY_KP_9,          MOD_MASK_ANY,    "\033Oy",       +2,    0,    0},
    457 +	{ XKB_KEY_Up,            MOD_MASK_SHIFT,  "\033[1;2A",     0,    0,    0},
    458 +	{ XKB_KEY_Up,            MOD_MASK_ALT,    "\033[1;3A",     0,    0,    0},
    459 +	{ XKB_KEY_Up, MOD_MASK_SHIFT|MOD_MASK_ALT,"\033[1;4A",     0,    0,    0},
    460 +	{ XKB_KEY_Up,            MOD_MASK_CTRL,   "\033[1;5A",     0,    0,    0},
    461 +	{ XKB_KEY_Up,MOD_MASK_SHIFT|MOD_MASK_CTRL,"\033[1;6A",     0,    0,    0},
    462 +	{ XKB_KEY_Up,  MOD_MASK_CTRL|MOD_MASK_ALT,"\033[1;7A",     0,    0,    0},
    463 +	{ XKB_KEY_Up,MOD_MASK_SHIFT|MOD_MASK_CTRL|MOD_MASK_ALT,"\033[1;8A",0,0,0},
    464 +	{ XKB_KEY_Up,            MOD_MASK_ANY,    "\033[A",        0,   -1,    0},
    465 +	{ XKB_KEY_Up,            MOD_MASK_ANY,    "\033OA",        0,   +1,    0},
    466 +	{ XKB_KEY_Down,          MOD_MASK_SHIFT,  "\033[1;2B",     0,    0,    0},
    467 +	{ XKB_KEY_Down,          MOD_MASK_ALT,    "\033[1;3B",     0,    0,    0},
    468 +	{ XKB_KEY_Down,MOD_MASK_SHIFT|MOD_MASK_ALT,"\033[1;4B",    0,    0,    0},
    469 +	{ XKB_KEY_Down,         MOD_MASK_CTRL,    "\033[1;5B",     0,    0,    0},
    470 +	{ XKB_KEY_Down,MOD_MASK_SHIFT|MOD_MASK_CTRL,"\033[1;6B",   0,    0,    0},
    471 +	{ XKB_KEY_Down,MOD_MASK_CTRL|MOD_MASK_ALT,"\033[1;7B",     0,    0,    0},
    472 +	{ XKB_KEY_Down,MOD_MASK_SHIFT|MOD_MASK_CTRL|MOD_MASK_ALT,"\033[1;8B",0,0,0},
    473 +	{ XKB_KEY_Down,          MOD_MASK_ANY,    "\033[B",        0,   -1,    0},
    474 +	{ XKB_KEY_Down,          MOD_MASK_ANY,    "\033OB",        0,   +1,    0},
    475 +	{ XKB_KEY_Left,          MOD_MASK_SHIFT,  "\033[1;2D",     0,    0,    0},
    476 +	{ XKB_KEY_Left,          MOD_MASK_ALT,    "\033[1;3D",     0,    0,    0},
    477 +	{ XKB_KEY_Left,MOD_MASK_SHIFT|MOD_MASK_ALT,"\033[1;4D",    0,    0,    0},
    478 +	{ XKB_KEY_Left,          MOD_MASK_CTRL,   "\033[1;5D",     0,    0,    0},
    479 +	{ XKB_KEY_Left,MOD_MASK_SHIFT|MOD_MASK_CTRL,"\033[1;6D",   0,    0,    0},
    480 +	{ XKB_KEY_Left,MOD_MASK_CTRL|MOD_MASK_ALT,"\033[1;7D",     0,    0,    0},
    481 +	{ XKB_KEY_Left,MOD_MASK_SHIFT|MOD_MASK_CTRL|MOD_MASK_ALT,"\033[1;8D",0,0,0},
    482 +	{ XKB_KEY_Left,          MOD_MASK_ANY,    "\033[D",        0,   -1,    0},
    483 +	{ XKB_KEY_Left,          MOD_MASK_ANY,    "\033OD",        0,   +1,    0},
    484 +	{ XKB_KEY_Right,         MOD_MASK_SHIFT,  "\033[1;2C",     0,    0,    0},
    485 +	{ XKB_KEY_Right,         MOD_MASK_ALT,    "\033[1;3C",     0,    0,    0},
    486 +	{ XKB_KEY_Right,MOD_MASK_SHIFT|MOD_MASK_ALT,"\033[1;4C",   0,    0,    0},
    487 +	{ XKB_KEY_Right,         MOD_MASK_CTRL,   "\033[1;5C",     0,    0,    0},
    488 +	{ XKB_KEY_Right,MOD_MASK_SHIFT|MOD_MASK_CTRL,"\033[1;6C",  0,    0,    0},
    489 +	{ XKB_KEY_Right,MOD_MASK_CTRL|MOD_MASK_ALT,"\033[1;7C",    0,    0,    0},
    490 +	{ XKB_KEY_Right,MOD_MASK_SHIFT|MOD_MASK_CTRL|MOD_MASK_ALT,"\033[1;8C",0,0,0},
    491 +	{ XKB_KEY_Right,         MOD_MASK_ANY,    "\033[C",        0,   -1,    0},
    492 +	{ XKB_KEY_Right,         MOD_MASK_ANY,    "\033OC",        0,   +1,    0},
    493 +	{ XKB_KEY_ISO_Left_Tab,  MOD_MASK_SHIFT,  "\033[Z",        0,    0,    0},
    494 +	{ XKB_KEY_Return,        MOD_MASK_ALT,    "\033\r",        0,    0,   -1},
    495 +	{ XKB_KEY_Return,        MOD_MASK_ALT,    "\033\r\n",      0,    0,   +1},
    496 +	{ XKB_KEY_Return,        MOD_MASK_ANY,    "\r",            0,    0,   -1},
    497 +	{ XKB_KEY_Return,        MOD_MASK_ANY,    "\r\n",          0,    0,   +1},
    498 +	{ XKB_KEY_Insert,        MOD_MASK_SHIFT,  "\033[4l",      -1,    0,    0},
    499 +	{ XKB_KEY_Insert,        MOD_MASK_SHIFT,  "\033[2;2~",    +1,    0,    0},
    500 +	{ XKB_KEY_Insert,        MOD_MASK_CTRL,   "\033[L",       -1,    0,    0},
    501 +	{ XKB_KEY_Insert,        MOD_MASK_CTRL,   "\033[2;5~",    +1,    0,    0},
    502 +	{ XKB_KEY_Insert,        MOD_MASK_ANY,    "\033[4h",      -1,    0,    0},
    503 +	{ XKB_KEY_Insert,        MOD_MASK_ANY,    "\033[2~",      +1,    0,    0},
    504 +	{ XKB_KEY_Delete,        MOD_MASK_CTRL,   "\033[M",       -1,    0,    0},
    505 +	{ XKB_KEY_Delete,        MOD_MASK_CTRL,   "\033[3;5~",    +1,    0,    0},
    506 +	{ XKB_KEY_Delete,        MOD_MASK_SHIFT,  "\033[2K",      -1,    0,    0},
    507 +	{ XKB_KEY_Delete,        MOD_MASK_SHIFT,  "\033[3;2~",    +1,    0,    0},
    508 +	{ XKB_KEY_Delete,        MOD_MASK_ANY,    "\033[P",       -1,    0,    0},
    509 +	{ XKB_KEY_Delete,        MOD_MASK_ANY,    "\033[3~",      +1,    0,    0},
    510 +	{ XKB_KEY_BackSpace,     MOD_MASK_NONE,   "\177",          0,    0,    0},
    511 +	{ XKB_KEY_BackSpace,     MOD_MASK_CTRL,   "\033\177",      0,    0,    0},
    512 +	{ XKB_KEY_Home,          MOD_MASK_SHIFT,  "\033[2J",       0,   -1,    0},
    513 +	{ XKB_KEY_Home,          MOD_MASK_SHIFT,  "\033[1;2H",     0,   +1,    0},
    514 +	{ XKB_KEY_Home,          MOD_MASK_ANY,    "\033[H",        0,   -1,    0},
    515 +	{ XKB_KEY_Home,          MOD_MASK_ANY,    "\033[1~",       0,   +1,    0},
    516 +	{ XKB_KEY_End,           MOD_MASK_CTRL,   "\033[J",       -1,    0,    0},
    517 +	{ XKB_KEY_End,           MOD_MASK_CTRL,   "\033[1;5F",    +1,    0,    0},
    518 +	{ XKB_KEY_End,           MOD_MASK_SHIFT,  "\033[K",       -1,    0,    0},
    519 +	{ XKB_KEY_End,           MOD_MASK_SHIFT,  "\033[1;2F",    +1,    0,    0},
    520 +	{ XKB_KEY_End,           MOD_MASK_ANY,    "\033[4~",       0,    0,    0},
    521 +	{ XKB_KEY_Prior,         MOD_MASK_CTRL,   "\033[5;5~",     0,    0,    0},
    522 +	{ XKB_KEY_Prior,         MOD_MASK_SHIFT,  "\033[5;2~",     0,    0,    0},
    523 +	{ XKB_KEY_Prior,         MOD_MASK_ANY,    "\033[5~",       0,    0,    0},
    524 +	{ XKB_KEY_Next,          MOD_MASK_CTRL,   "\033[6;5~",     0,    0,    0},
    525 +	{ XKB_KEY_Next,          MOD_MASK_SHIFT,  "\033[6;2~",     0,    0,    0},
    526 +	{ XKB_KEY_Next,          MOD_MASK_ANY,    "\033[6~",       0,    0,    0},
    527 +	{ XKB_KEY_F1,            MOD_MASK_NONE,   "\033OP" ,       0,    0,    0},
    528 +	{ XKB_KEY_F1, /* F13 */  MOD_MASK_SHIFT,  "\033[1;2P",     0,    0,    0},
    529 +	{ XKB_KEY_F1, /* F25 */  MOD_MASK_CTRL,   "\033[1;5P",     0,    0,    0},
    530 +	{ XKB_KEY_F1, /* F37 */  MOD_MASK_LOGO,   "\033[1;6P",     0,    0,    0},
    531 +	{ XKB_KEY_F1, /* F49 */  MOD_MASK_ALT,    "\033[1;3P",     0,    0,    0},
    532 +	{ XKB_KEY_F2,            MOD_MASK_NONE,   "\033OQ" ,       0,    0,    0},
    533 +	{ XKB_KEY_F2, /* F14 */  MOD_MASK_SHIFT,  "\033[1;2Q",     0,    0,    0},
    534 +	{ XKB_KEY_F2, /* F26 */  MOD_MASK_CTRL,   "\033[1;5Q",     0,    0,    0},
    535 +	{ XKB_KEY_F2, /* F38 */  MOD_MASK_LOGO,   "\033[1;6Q",     0,    0,    0},
    536 +	{ XKB_KEY_F2, /* F50 */  MOD_MASK_ALT,    "\033[1;3Q",     0,    0,    0},
    537 +	{ XKB_KEY_F3,            MOD_MASK_NONE,   "\033OR" ,       0,    0,    0},
    538 +	{ XKB_KEY_F3, /* F15 */  MOD_MASK_SHIFT,  "\033[1;2R",     0,    0,    0},
    539 +	{ XKB_KEY_F3, /* F27 */  MOD_MASK_CTRL,   "\033[1;5R",     0,    0,    0},
    540 +	{ XKB_KEY_F3, /* F39 */  MOD_MASK_LOGO,   "\033[1;6R",     0,    0,    0},
    541 +	{ XKB_KEY_F3, /* F51 */  MOD_MASK_ALT,    "\033[1;3R",     0,    0,    0},
    542 +	{ XKB_KEY_F4,            MOD_MASK_NONE,   "\033OS" ,       0,    0,    0},
    543 +	{ XKB_KEY_F4, /* F16 */  MOD_MASK_SHIFT,  "\033[1;2S",     0,    0,    0},
    544 +	{ XKB_KEY_F4, /* F28 */  MOD_MASK_CTRL,   "\033[1;5S",     0,    0,    0},
    545 +	{ XKB_KEY_F4, /* F40 */  MOD_MASK_LOGO,   "\033[1;6S",     0,    0,    0},
    546 +	{ XKB_KEY_F4, /* F52 */  MOD_MASK_ALT,    "\033[1;3S",     0,    0,    0},
    547 +	{ XKB_KEY_F5,            MOD_MASK_NONE,   "\033[15~",      0,    0,    0},
    548 +	{ XKB_KEY_F5, /* F17 */  MOD_MASK_SHIFT,  "\033[15;2~",    0,    0,    0},
    549 +	{ XKB_KEY_F5, /* F29 */  MOD_MASK_CTRL,   "\033[15;5~",    0,    0,    0},
    550 +	{ XKB_KEY_F5, /* F41 */  MOD_MASK_LOGO,   "\033[15;6~",    0,    0,    0},
    551 +	{ XKB_KEY_F5, /* F53 */  MOD_MASK_ALT,    "\033[15;3~",    0,    0,    0},
    552 +	{ XKB_KEY_F6,            MOD_MASK_NONE,   "\033[17~",      0,    0,    0},
    553 +	{ XKB_KEY_F6, /* F18 */  MOD_MASK_SHIFT,  "\033[17;2~",    0,    0,    0},
    554 +	{ XKB_KEY_F6, /* F30 */  MOD_MASK_CTRL,   "\033[17;5~",    0,    0,    0},
    555 +	{ XKB_KEY_F6, /* F42 */  MOD_MASK_LOGO,   "\033[17;6~",    0,    0,    0},
    556 +	{ XKB_KEY_F6, /* F54 */  MOD_MASK_ALT,    "\033[17;3~",    0,    0,    0},
    557 +	{ XKB_KEY_F7,            MOD_MASK_NONE,   "\033[18~",      0,    0,    0},
    558 +	{ XKB_KEY_F7, /* F19 */  MOD_MASK_SHIFT,  "\033[18;2~",    0,    0,    0},
    559 +	{ XKB_KEY_F7, /* F31 */  MOD_MASK_CTRL,   "\033[18;5~",    0,    0,    0},
    560 +	{ XKB_KEY_F7, /* F43 */  MOD_MASK_LOGO,   "\033[18;6~",    0,    0,    0},
    561 +	{ XKB_KEY_F7, /* F55 */  MOD_MASK_ALT,    "\033[18;3~",    0,    0,    0},
    562 +	{ XKB_KEY_F8,            MOD_MASK_NONE,   "\033[19~",      0,    0,    0},
    563 +	{ XKB_KEY_F8, /* F20 */  MOD_MASK_SHIFT,  "\033[19;2~",    0,    0,    0},
    564 +	{ XKB_KEY_F8, /* F32 */  MOD_MASK_CTRL,   "\033[19;5~",    0,    0,    0},
    565 +	{ XKB_KEY_F8, /* F44 */  MOD_MASK_LOGO,   "\033[19;6~",    0,    0,    0},
    566 +	{ XKB_KEY_F8, /* F56 */  MOD_MASK_ALT,    "\033[19;3~",    0,    0,    0},
    567 +	{ XKB_KEY_F9,            MOD_MASK_NONE,   "\033[20~",      0,    0,    0},
    568 +	{ XKB_KEY_F9, /* F21 */  MOD_MASK_SHIFT,  "\033[20;2~",    0,    0,    0},
    569 +	{ XKB_KEY_F9, /* F33 */  MOD_MASK_CTRL,   "\033[20;5~",    0,    0,    0},
    570 +	{ XKB_KEY_F9, /* F45 */  MOD_MASK_LOGO,   "\033[20;6~",    0,    0,    0},
    571 +	{ XKB_KEY_F9, /* F57 */  MOD_MASK_ALT,    "\033[20;3~",    0,    0,    0},
    572 +	{ XKB_KEY_F10,           MOD_MASK_NONE,   "\033[21~",      0,    0,    0},
    573 +	{ XKB_KEY_F10, /* F22 */ MOD_MASK_SHIFT,  "\033[21;2~",    0,    0,    0},
    574 +	{ XKB_KEY_F10, /* F34 */ MOD_MASK_CTRL,   "\033[21;5~",    0,    0,    0},
    575 +	{ XKB_KEY_F10, /* F46 */ MOD_MASK_LOGO,   "\033[21;6~",    0,    0,    0},
    576 +	{ XKB_KEY_F10, /* F58 */ MOD_MASK_ALT,    "\033[21;3~",    0,    0,    0},
    577 +	{ XKB_KEY_F11,           MOD_MASK_NONE,   "\033[23~",      0,    0,    0},
    578 +	{ XKB_KEY_F11, /* F23 */ MOD_MASK_SHIFT,  "\033[23;2~",    0,    0,    0},
    579 +	{ XKB_KEY_F11, /* F35 */ MOD_MASK_CTRL,   "\033[23;5~",    0,    0,    0},
    580 +	{ XKB_KEY_F11, /* F47 */ MOD_MASK_LOGO,   "\033[23;6~",    0,    0,    0},
    581 +	{ XKB_KEY_F11, /* F59 */ MOD_MASK_ALT,    "\033[23;3~",    0,    0,    0},
    582 +	{ XKB_KEY_F12,           MOD_MASK_NONE,   "\033[24~",      0,    0,    0},
    583 +	{ XKB_KEY_F12, /* F24 */ MOD_MASK_SHIFT,  "\033[24;2~",    0,    0,    0},
    584 +	{ XKB_KEY_F12, /* F36 */ MOD_MASK_CTRL,   "\033[24;5~",    0,    0,    0},
    585 +	{ XKB_KEY_F12, /* F48 */ MOD_MASK_LOGO,   "\033[24;6~",    0,    0,    0},
    586 +	{ XKB_KEY_F12, /* F60 */ MOD_MASK_ALT,    "\033[24;3~",    0,    0,    0},
    587 +	{ XKB_KEY_F13,           MOD_MASK_NONE,   "\033[1;2P",     0,    0,    0},
    588 +	{ XKB_KEY_F14,           MOD_MASK_NONE,   "\033[1;2Q",     0,    0,    0},
    589 +	{ XKB_KEY_F15,           MOD_MASK_NONE,   "\033[1;2R",     0,    0,    0},
    590 +	{ XKB_KEY_F16,           MOD_MASK_NONE,   "\033[1;2S",     0,    0,    0},
    591 +	{ XKB_KEY_F17,           MOD_MASK_NONE,   "\033[15;2~",    0,    0,    0},
    592 +	{ XKB_KEY_F18,           MOD_MASK_NONE,   "\033[17;2~",    0,    0,    0},
    593 +	{ XKB_KEY_F19,           MOD_MASK_NONE,   "\033[18;2~",    0,    0,    0},
    594 +	{ XKB_KEY_F20,           MOD_MASK_NONE,   "\033[19;2~",    0,    0,    0},
    595 +	{ XKB_KEY_F21,           MOD_MASK_NONE,   "\033[20;2~",    0,    0,    0},
    596 +	{ XKB_KEY_F22,           MOD_MASK_NONE,   "\033[21;2~",    0,    0,    0},
    597 +	{ XKB_KEY_F23,           MOD_MASK_NONE,   "\033[23;2~",    0,    0,    0},
    598 +	{ XKB_KEY_F24,           MOD_MASK_NONE,   "\033[24;2~",    0,    0,    0},
    599 +	{ XKB_KEY_F25,           MOD_MASK_NONE,   "\033[1;5P",     0,    0,    0},
    600 +	{ XKB_KEY_F26,           MOD_MASK_NONE,   "\033[1;5Q",     0,    0,    0},
    601 +	{ XKB_KEY_F27,           MOD_MASK_NONE,   "\033[1;5R",     0,    0,    0},
    602 +	{ XKB_KEY_F28,           MOD_MASK_NONE,   "\033[1;5S",     0,    0,    0},
    603 +	{ XKB_KEY_F29,           MOD_MASK_NONE,   "\033[15;5~",    0,    0,    0},
    604 +	{ XKB_KEY_F30,           MOD_MASK_NONE,   "\033[17;5~",    0,    0,    0},
    605 +	{ XKB_KEY_F31,           MOD_MASK_NONE,   "\033[18;5~",    0,    0,    0},
    606 +	{ XKB_KEY_F32,           MOD_MASK_NONE,   "\033[19;5~",    0,    0,    0},
    607 +	{ XKB_KEY_F33,           MOD_MASK_NONE,   "\033[20;5~",    0,    0,    0},
    608 +	{ XKB_KEY_F34,           MOD_MASK_NONE,   "\033[21;5~",    0,    0,    0},
    609 +	{ XKB_KEY_F35,           MOD_MASK_NONE,   "\033[23;5~",    0,    0,    0},
    610  };
    611  
    612  /*
    613 @@ -452,7 +448,7 @@ static Key key[] = {
    614   * If no match is found, regular selection is used.
    615   */
    616  static uint selmasks[] = {
    617 -	[SEL_RECTANGULAR] = Mod1Mask,
    618 +	[SEL_RECTANGULAR] = MOD_MASK_ALT,
    619  };
    620  
    621  /*
    622 diff --git a/config.mk b/config.mk
    623 index c84c5ee..7da06f1 100644
    624 --- a/config.mk
    625 +++ b/config.mk
    626 @@ -7,16 +7,12 @@ VERSION = 0.7
    627  PREFIX = /usr/local
    628  MANPREFIX = ${PREFIX}/share/man
    629  
    630 -X11INC = /usr/X11R6/include
    631 -X11LIB = /usr/X11R6/lib
    632 +PKGCFG = fontconfig wayland-client wayland-cursor xkbcommon wld
    633 +XDG_SHELL_PROTO = `pkg-config --variable=pkgdatadir wayland-protocols`/unstable/xdg-shell/xdg-shell-unstable-v5.xml
    634  
    635  # includes and libs
    636 -INCS = -I. -I/usr/include -I${X11INC} \
    637 -       `pkg-config --cflags fontconfig` \
    638 -       `pkg-config --cflags freetype2`
    639 -LIBS = -L/usr/lib -lc -L${X11LIB} -lm -lrt -lX11 -lutil -lXft \
    640 -       `pkg-config --libs fontconfig`  \
    641 -       `pkg-config --libs freetype2`
    642 +INCS = -I. -I/usr/include `pkg-config --cflags ${PKGCFG}`
    643 +LIBS = -L/usr/lib -lc -lm -lrt -lutil `pkg-config --libs ${PKGCFG}`
    644  
    645  # flags
    646  CPPFLAGS = -DVERSION=\"${VERSION}\" -D_XOPEN_SOURCE=600
    647 diff --git a/st.c b/st.c
    648 index fbcd9e0..9ead681 100644
    649 --- a/st.c
    650 +++ b/st.c
    651 @@ -3,6 +3,8 @@
    652  #include <errno.h>
    653  #include <fcntl.h>
    654  #include <limits.h>
    655 +/* for BTN_* definitions */
    656 +#include <linux/input.h>
    657  #include <locale.h>
    658  #include <pwd.h>
    659  #include <stdarg.h>
    660 @@ -12,6 +14,7 @@
    661  #include <signal.h>
    662  #include <stdint.h>
    663  #include <sys/ioctl.h>
    664 +#include <sys/mman.h>
    665  #include <sys/select.h>
    666  #include <sys/stat.h>
    667  #include <sys/time.h>
    668 @@ -21,23 +24,19 @@
    669  #include <time.h>
    670  #include <unistd.h>
    671  #include <libgen.h>
    672 -#include <X11/Xatom.h>
    673 -#include <X11/Xlib.h>
    674 -#include <X11/Xutil.h>
    675 -#include <X11/cursorfont.h>
    676 -#include <X11/keysym.h>
    677 -#include <X11/Xft/Xft.h>
    678 -#include <X11/XKBlib.h>
    679 +#include <wayland-client.h>
    680 +#include <wayland-cursor.h>
    681 +#include <xkbcommon/xkbcommon.h>
    682 +#include <wld/wld.h>
    683 +#include <wld/wayland.h>
    684  #include <fontconfig/fontconfig.h>
    685  #include <wchar.h>
    686  
    687  #include "arg.h"
    688 +#include "xdg-shell-client-protocol.h"
    689  
    690  char *argv0;
    691  
    692 -#define Glyph Glyph_
    693 -#define Font Font_
    694 -
    695  #if   defined(__linux)
    696   #include <pty.h>
    697  #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
    698 @@ -47,10 +46,6 @@ char *argv0;
    699  #endif
    700  
    701  
    702 -/* XEMBED messages */
    703 -#define XEMBED_FOCUS_IN  4
    704 -#define XEMBED_FOCUS_OUT 5
    705 -
    706  /* Arbitrary sizes */
    707  #define UTF_INVALID   0xFFFD
    708  #define UTF_SIZ       4
    709 @@ -58,15 +53,25 @@ char *argv0;
    710  #define ESC_ARG_SIZ   16
    711  #define STR_BUF_SIZ   ESC_BUF_SIZ
    712  #define STR_ARG_SIZ   ESC_ARG_SIZ
    713 +#define DRAW_BUF_SIZ  20*1024
    714  #define XK_ANY_MOD    UINT_MAX
    715  #define XK_NO_MOD     0
    716  #define XK_SWITCH_MOD (1<<13)
    717  
    718 +#define MOD_MASK_ANY	UINT_MAX
    719 +#define MOD_MASK_NONE	0
    720 +#define MOD_MASK_CTRL	(1<<0)
    721 +#define MOD_MASK_ALT	(1<<1)
    722 +#define MOD_MASK_SHIFT	(1<<2)
    723 +#define MOD_MASK_LOGO	(1<<3)
    724 +
    725 +#define AXIS_VERTICAL	WL_POINTER_AXIS_VERTICAL_SCROLL
    726 +#define AXIS_HORIZONTAL	WL_POINTER_AXIS_HORIZONTAL_SCROLL
    727 +
    728  /* macros */
    729  #define MIN(a, b)		((a) < (b) ? (a) : (b))
    730  #define MAX(a, b)		((a) < (b) ? (b) : (a))
    731  #define LEN(a)			(sizeof(a) / sizeof(a)[0])
    732 -#define NUMMAXLEN(x)		((int)(sizeof(x) * 2.56 + 0.5) + 1)
    733  #define DEFAULT(a, b)		(a) = (a) ? (a) : (b)
    734  #define BETWEEN(x, a, b)	((a) <= (x) && (x) <= (b))
    735  #define DIVCEIL(n, d)		(((n) + ((d) - 1)) / (d))
    736 @@ -89,7 +94,7 @@ char *argv0;
    737  #define TRUEBLUE(x)		(((x) & 0xff) << 8)
    738  
    739  /* constants */
    740 -#define ISO14755CMD		"dmenu -w %lu -p codepoint: </dev/null"
    741 +#define ISO14755CMD		"dmenu -p codepoint: </dev/null"
    742  
    743  enum glyph_attribute {
    744  	ATTR_NULL       = 0,
    745 @@ -195,9 +200,6 @@ typedef unsigned short ushort;
    746  
    747  typedef uint_least32_t Rune;
    748  
    749 -typedef XftDraw *Draw;
    750 -typedef XftColor Color;
    751 -
    752  typedef struct {
    753  	Rune u;           /* character code */
    754  	ushort mode;      /* attribute flags */
    755 @@ -242,7 +244,6 @@ typedef struct {
    756  	Line *line;   /* screen */
    757  	Line *alt;    /* alternate screen */
    758  	int *dirty;  /* dirtyness of lines */
    759 -	XftGlyphFontSpec *specbuf; /* font spec buffer used for rendering */
    760  	TCursor c;    /* cursor */
    761  	int top;      /* top    scroll limit */
    762  	int bot;      /* bottom scroll limit */
    763 @@ -255,29 +256,54 @@ typedef struct {
    764  	int *tabs;
    765  } Term;
    766  
    767 -/* Purely graphic info */
    768  typedef struct {
    769 -	Display *dpy;
    770 -	Colormap cmap;
    771 -	Window win;
    772 -	Drawable buf;
    773 -	Atom xembed, wmdeletewin, netwmname, netwmpid;
    774 -	XIM xim;
    775 -	XIC xic;
    776 -	Draw draw;
    777 -	Visual *vis;
    778 -	XSetWindowAttributes attrs;
    779 -	int scr;
    780 -	int isfixed; /* is fixed geometry? */
    781 -	int l, t; /* left and top offset */
    782 -	int gm; /* geometry mask */
    783 +	struct xkb_context *ctx;
    784 +	struct xkb_keymap *keymap;
    785 +	struct xkb_state *state;
    786 +	xkb_mod_index_t ctrl, alt, shift, logo;
    787 +	unsigned int mods;
    788 +} XKB;
    789 +
    790 +typedef struct {
    791 +	struct wl_display *dpy;
    792 +	struct wl_compositor *cmp;
    793 +	struct wl_shm *shm;
    794 +	struct wl_seat *seat;
    795 +	struct wl_keyboard *keyboard;
    796 +	struct wl_pointer *pointer;
    797 +	struct wl_data_device_manager *datadevmanager;
    798 +	struct wl_data_device *datadev;
    799 +	struct wl_data_offer *seloffer;
    800 +	struct wl_surface *surface;
    801 +	struct wl_buffer *buffer;
    802 +	struct xdg_wm_base *wm;
    803 +	struct xdg_surface *xdgsurface;
    804 +	struct xdg_toplevel *toplevel;
    805 +	XKB xkb;
    806 +	bool configured;
    807 +	int px, py; /* pointer x and y */
    808  	int tw, th; /* tty width and height */
    809  	int w, h; /* window width and height */
    810  	int ch; /* char height */
    811  	int cw; /* char width  */
    812 +	int vis;
    813  	char state; /* focus, redraw, visible */
    814  	int cursor; /* cursor style */
    815 -} XWindow;
    816 +	struct wl_callback * framecb;
    817 +} Wayland;
    818 +
    819 +typedef struct {
    820 +	struct wld_context *ctx;
    821 +	struct wld_font_context *fontctx;
    822 +	struct wld_renderer *renderer;
    823 +	struct wld_buffer *buffer, *oldbuffer;
    824 +} WLD;
    825 +
    826 +typedef struct {
    827 +	struct wl_cursor_theme *theme;
    828 +	struct wl_cursor *cursor;
    829 +	struct wl_surface *surface;
    830 +} Cursor;
    831  
    832  typedef struct {
    833  	uint b;
    834 @@ -286,7 +312,14 @@ typedef struct {
    835  } MouseShortcut;
    836  
    837  typedef struct {
    838 -	KeySym k;
    839 +	int axis;
    840 +	int dir;
    841 +	uint mask;
    842 +	char s[ESC_BUF_SIZ];
    843 +} Axiskey;
    844 +
    845 +typedef struct {
    846 +	xkb_keysym_t k;
    847  	uint mask;
    848  	char *s;
    849  	/* three valued logic variables: 0 indifferent, 1 on, -1 off */
    850 @@ -310,11 +343,10 @@ typedef struct {
    851  		int x, y;
    852  	} nb, ne, ob, oe;
    853  
    854 -	char *primary, *clipboard;
    855 -	Atom xtarget;
    856 +	char *primary;
    857 +	struct wl_data_source *source;
    858  	int alt;
    859 -	struct timespec tclick1;
    860 -	struct timespec tclick2;
    861 +	uint32_t tclick1, tclick2;
    862  } Selection;
    863  
    864  typedef union {
    865 @@ -326,19 +358,25 @@ typedef union {
    866  
    867  typedef struct {
    868  	uint mod;
    869 -	KeySym keysym;
    870 +	xkb_keysym_t keysym;
    871  	void (*func)(const Arg *);
    872  	const Arg arg;
    873  } Shortcut;
    874  
    875 +typedef struct {
    876 +	char str[32];
    877 +	uint32_t key;
    878 +	int len;
    879 +	bool started;
    880 +	struct timespec last;
    881 +} Repeat;
    882 +
    883  /* function definitions used in config.h */
    884 -static void clipcopy(const Arg *);
    885 -static void clippaste(const Arg *);
    886  static void numlock(const Arg *);
    887  static void selpaste(const Arg *);
    888 -static void xzoom(const Arg *);
    889 -static void xzoomabs(const Arg *);
    890 -static void xzoomreset(const Arg *);
    891 +static void wlzoom(const Arg *);
    892 +static void wlzoomabs(const Arg *);
    893 +static void wlzoomreset(const Arg *);
    894  static void printsel(const Arg *);
    895  static void printscreen(const Arg *) ;
    896  static void iso14755(const Arg *);
    897 @@ -358,16 +396,15 @@ typedef struct {
    898  	int badweight;
    899  	short lbearing;
    900  	short rbearing;
    901 -	XftFont *match;
    902 +	struct wld_font *match;
    903  	FcFontSet *set;
    904  	FcPattern *pattern;
    905  } Font;
    906  
    907  /* Drawing Context */
    908  typedef struct {
    909 -	Color col[MAX(LEN(colorname), 256)];
    910 +	uint32_t col[MAX(LEN(colorname), 256)];
    911  	Font font, bfont, ifont, ibfont;
    912 -	GC gc;
    913  } DC;
    914  
    915  static void die(const char *, ...);
    916 @@ -378,6 +415,7 @@ static void execsh(void);
    917  static void stty(void);
    918  static void sigchld(int);
    919  static void run(void);
    920 +static void cresize(int, int);
    921  
    922  static void csidump(void);
    923  static void csihandle(void);
    924 @@ -433,56 +471,80 @@ static void ttysend(char *, size_t);
    925  static void ttywrite(const char *, size_t);
    926  static void tstrsequence(uchar);
    927  
    928 -static inline ushort sixd_to_16bit(int);
    929 -static int xmakeglyphfontspecs(XftGlyphFontSpec *, const Glyph *, int, int, int);
    930 -static void xdrawglyphfontspecs(const XftGlyphFontSpec *, Glyph, int, int, int);
    931 -static void xdrawglyph(Glyph, int, int);
    932 -static void xhints(void);
    933 -static void xclear(int, int, int, int);
    934 -static void xdrawcursor(void);
    935 -static void xinit(void);
    936 -static void xloadcols(void);
    937 -static int xsetcolorname(int, const char *);
    938 -static int xgeommasktogravity(int);
    939 -static int xloadfont(Font *, FcPattern *);
    940 -static void xloadfonts(char *, double);
    941 -static void xsettitle(char *);
    942 -static void xresettitle(void);
    943 -static void xsetpointermotion(int);
    944 -static void xseturgency(int);
    945 -static void xsetsel(char *, Time);
    946 -static void xunloadfont(Font *);
    947 -static void xunloadfonts(void);
    948 -static void xresize(int, int);
    949 -
    950 -static void expose(XEvent *);
    951 -static void visibility(XEvent *);
    952 -static void unmap(XEvent *);
    953 -static char *kmap(KeySym, uint);
    954 -static void kpress(XEvent *);
    955 -static void cmessage(XEvent *);
    956 -static void cresize(int, int);
    957 -static void resize(XEvent *);
    958 -static void focus(XEvent *);
    959 -static void brelease(XEvent *);
    960 -static void bpress(XEvent *);
    961 -static void bmotion(XEvent *);
    962 -static void propnotify(XEvent *);
    963 -static void selnotify(XEvent *);
    964 -static void selclear(XEvent *);
    965 -static void selrequest(XEvent *);
    966 +static inline uchar sixd_to_8bit(int);
    967 +static void wldraws(char *, Glyph, int, int, int, int);
    968 +static void wldrawglyph(Glyph, int, int);
    969 +static void wlclear(int, int, int, int);
    970 +static void wldrawcursor(void);
    971 +static void wlinit(void);
    972 +static void wlloadcols(void);
    973 +static int wlsetcolorname(int, const char *);
    974 +static void wlloadcursor(void);
    975 +static int wlloadfont(Font *, FcPattern *);
    976 +static void wlloadfonts(char *, double);
    977 +static void wlsettitle(char *);
    978 +static void wlresettitle(void);
    979 +static void wlseturgency(int);
    980 +static void wlsetsel(char*, uint32_t);
    981 +static void wlunloadfont(Font *f);
    982 +static void wlunloadfonts(void);
    983 +static void wlresize(int, int);
    984 +
    985 +static void regglobal(void *, struct wl_registry *, uint32_t, const char *,
    986 +		uint32_t);
    987 +static void regglobalremove(void *, struct wl_registry *, uint32_t);
    988 +static void surfenter(void *, struct wl_surface *, struct wl_output *);
    989 +static void surfleave(void *, struct wl_surface *, struct wl_output *);
    990 +static void framedone(void *, struct wl_callback *, uint32_t);
    991 +static void kbdkeymap(void *, struct wl_keyboard *, uint32_t, int32_t, uint32_t);
    992 +static void kbdenter(void *, struct wl_keyboard *, uint32_t,
    993 +		struct wl_surface *, struct wl_array *);
    994 +static void kbdleave(void *, struct wl_keyboard *, uint32_t,
    995 +		struct wl_surface *);
    996 +static void kbdkey(void *, struct wl_keyboard *, uint32_t, uint32_t, uint32_t,
    997 +		uint32_t);
    998 +static void kbdmodifiers(void *, struct wl_keyboard *, uint32_t, uint32_t,
    999 +		uint32_t, uint32_t, uint32_t);
   1000 +static void kbdrepeatinfo(void *, struct wl_keyboard *, int32_t, int32_t);
   1001 +static void ptrenter(void *, struct wl_pointer *, uint32_t, struct wl_surface *,
   1002 +		wl_fixed_t, wl_fixed_t);
   1003 +static void ptrleave(void *, struct wl_pointer *, uint32_t,
   1004 +		struct wl_surface *);
   1005 +static void ptrmotion(void *, struct wl_pointer *, uint32_t,
   1006 +		wl_fixed_t, wl_fixed_t);
   1007 +static void ptrbutton(void *, struct wl_pointer *, uint32_t, uint32_t,
   1008 +		uint32_t, uint32_t);
   1009 +static void ptraxis(void *, struct wl_pointer *, uint32_t, uint32_t,
   1010 +		wl_fixed_t);
   1011 +static void wmping(void *, struct xdg_wm_base *, uint32_t);
   1012 +static void xdgsurfconfigure(void *, struct xdg_surface *, uint32_t);
   1013 +static void toplevelconfigure(void *, struct xdg_toplevel *,
   1014 +		int32_t, int32_t, struct wl_array *);
   1015 +static void toplevelclose(void *, struct xdg_toplevel *);
   1016 +static void datadevoffer(void *, struct wl_data_device *,
   1017 +		struct wl_data_offer *);
   1018 +static void datadeventer(void *, struct wl_data_device *, uint32_t,
   1019 +		struct wl_surface *, wl_fixed_t, wl_fixed_t, struct wl_data_offer *);
   1020 +static void datadevleave(void *, struct wl_data_device *);
   1021 +static void datadevmotion(void *, struct wl_data_device *, uint32_t,
   1022 +		wl_fixed_t x, wl_fixed_t y);
   1023 +static void datadevdrop(void *, struct wl_data_device *);
   1024 +static void datadevselection(void *, struct wl_data_device *,
   1025 +		struct wl_data_offer *);
   1026 +static void dataofferoffer(void *, struct wl_data_offer *, const char *);
   1027 +static void datasrctarget(void *, struct wl_data_source *, const char *);
   1028 +static void datasrcsend(void *, struct wl_data_source *, const char *, int32_t);
   1029 +static void datasrccancelled(void *, struct wl_data_source *);
   1030  
   1031  static void selinit(void);
   1032  static void selnormalize(void);
   1033  static inline int selected(int, int);
   1034  static char *getsel(void);
   1035 -static void selcopy(Time);
   1036 +static void selcopy(uint32_t);
   1037  static void selscroll(int, int);
   1038  static void selsnap(int *, int *, int);
   1039  static int x2col(int);
   1040  static int y2row(int);
   1041 -static void getbuttoninfo(XEvent *);
   1042 -static void mousereport(XEvent *);
   1043  
   1044  static size_t utf8decode(char *, Rune *, size_t);
   1045  static Rune utf8decodebyte(char, size_t *);
   1046 @@ -498,41 +560,37 @@ static char *xstrdup(char *);
   1047  
   1048  static void usage(void);
   1049  
   1050 -static void (*handler[LASTEvent])(XEvent *) = {
   1051 -	[KeyPress] = kpress,
   1052 -	[ClientMessage] = cmessage,
   1053 -	[ConfigureNotify] = resize,
   1054 -	[VisibilityNotify] = visibility,
   1055 -	[UnmapNotify] = unmap,
   1056 -	[Expose] = expose,
   1057 -	[FocusIn] = focus,
   1058 -	[FocusOut] = focus,
   1059 -	[MotionNotify] = bmotion,
   1060 -	[ButtonPress] = bpress,
   1061 -	[ButtonRelease] = brelease,
   1062 -/*
   1063 - * Uncomment if you want the selection to disappear when you select something
   1064 - * different in another window.
   1065 - */
   1066 -/*	[SelectionClear] = selclear, */
   1067 -	[SelectionNotify] = selnotify,
   1068 -/*
   1069 - * PropertyNotify is only turned on when there is some INCR transfer happening
   1070 - * for the selection retrieval.
   1071 - */
   1072 -	[PropertyNotify] = propnotify,
   1073 -	[SelectionRequest] = selrequest,
   1074 -};
   1075 +static struct wl_registry_listener reglistener = { regglobal, regglobalremove };
   1076 +static struct wl_surface_listener surflistener = { surfenter, surfleave };
   1077 +static struct wl_callback_listener framelistener = { framedone };
   1078 +static struct wl_keyboard_listener kbdlistener =
   1079 +	{ kbdkeymap, kbdenter, kbdleave, kbdkey, kbdmodifiers, kbdrepeatinfo };
   1080 +static struct wl_pointer_listener ptrlistener =
   1081 +	{ ptrenter, ptrleave, ptrmotion, ptrbutton, ptraxis };
   1082 +static struct xdg_wm_base_listener wmlistener = { wmping };
   1083 +static struct xdg_surface_listener xdgsurflistener = { xdgsurfconfigure };
   1084 +static struct xdg_toplevel_listener toplevellistener =
   1085 +	{ toplevelconfigure, toplevelclose };
   1086 +static struct wl_data_device_listener datadevlistener =
   1087 +	{ datadevoffer, datadeventer, datadevleave, datadevmotion, datadevdrop,
   1088 +	  datadevselection };
   1089 +static struct wl_data_offer_listener dataofferlistener = { dataofferoffer };
   1090 +static struct wl_data_source_listener datasrclistener =
   1091 +	{ datasrctarget, datasrcsend, datasrccancelled };
   1092  
   1093  /* Globals */
   1094  static DC dc;
   1095 -static XWindow xw;
   1096 +static Wayland wl;
   1097 +static WLD wld;
   1098 +static Cursor cursor;
   1099  static Term term;
   1100  static CSIEscape csiescseq;
   1101  static STREscape strescseq;
   1102  static int cmdfd;
   1103  static pid_t pid;
   1104  static Selection sel;
   1105 +static Repeat repeat;
   1106 +static bool needdraw = true;
   1107  static int iofd = 1;
   1108  static char **opt_cmd  = NULL;
   1109  static char *opt_class = NULL;
   1110 @@ -543,6 +601,7 @@ static char *opt_line  = NULL;
   1111  static char *opt_name  = NULL;
   1112  static char *opt_title = NULL;
   1113  static int oldbutton   = 3; /* button event on startup: 3 = release */
   1114 +static int oldx, oldy;
   1115  
   1116  static char *usedfont = NULL;
   1117  static double usedfontsize = 0;
   1118 @@ -562,7 +621,7 @@ enum {
   1119  };
   1120  
   1121  typedef struct {
   1122 -	XftFont *font;
   1123 +	struct wld_font *font;
   1124  	int flags;
   1125  	Rune unicodep;
   1126  } Fontcache;
   1127 @@ -707,23 +766,20 @@ utf8validate(Rune *u, size_t i)
   1128  void
   1129  selinit(void)
   1130  {
   1131 -	clock_gettime(CLOCK_MONOTONIC, &sel.tclick1);
   1132 -	clock_gettime(CLOCK_MONOTONIC, &sel.tclick2);
   1133 +	sel.tclick1 = 0;
   1134 +	sel.tclick2 = 0;
   1135  	sel.mode = SEL_IDLE;
   1136  	sel.snap = 0;
   1137  	sel.ob.x = -1;
   1138  	sel.primary = NULL;
   1139 -	sel.clipboard = NULL;
   1140 -	sel.xtarget = XInternAtom(xw.dpy, "UTF8_STRING", 0);
   1141 -	if (sel.xtarget == None)
   1142 -		sel.xtarget = XA_STRING;
   1143 +	sel.source = NULL;
   1144  }
   1145  
   1146  int
   1147  x2col(int x)
   1148  {
   1149  	x -= borderpx;
   1150 -	x /= xw.cw;
   1151 +	x /= wl.cw;
   1152  
   1153  	return LIMIT(x, 0, term.col-1);
   1154  }
   1155 @@ -732,7 +788,7 @@ int
   1156  y2row(int y)
   1157  {
   1158  	y -= borderpx;
   1159 -	y /= xw.ch;
   1160 +	y /= wl.ch;
   1161  
   1162  	return LIMIT(y, 0, term.row-1);
   1163  }
   1164 @@ -868,15 +924,15 @@ selsnap(int *x, int *y, int direction)
   1165  }
   1166  
   1167  void
   1168 -getbuttoninfo(XEvent *e)
   1169 +getbuttoninfo(void)
   1170  {
   1171  	int type;
   1172 -	uint state = e->xbutton.state & ~(Button1Mask | forceselmod);
   1173 +	uint state = wl.xkb.mods & ~forceselmod;
   1174  
   1175  	sel.alt = IS_SET(MODE_ALTSCREEN);
   1176  
   1177 -	sel.oe.x = x2col(e->xbutton.x);
   1178 -	sel.oe.y = y2row(e->xbutton.y);
   1179 +	sel.oe.x = x2col(wl.px);
   1180 +	sel.oe.y = y2row(wl.py);
   1181  	selnormalize();
   1182  
   1183  	sel.type = SEL_REGULAR;
   1184 @@ -889,59 +945,20 @@ getbuttoninfo(XEvent *e)
   1185  }
   1186  
   1187  void
   1188 -mousereport(XEvent *e)
   1189 +wlmousereport(int button, bool release, int x, int y)
   1190  {
   1191 -	int x = x2col(e->xbutton.x), y = y2row(e->xbutton.y),
   1192 -	    button = e->xbutton.button, state = e->xbutton.state,
   1193 -	    len;
   1194 +	int len;
   1195  	char buf[40];
   1196 -	static int ox, oy;
   1197 -
   1198 -	/* from urxvt */
   1199 -	if (e->xbutton.type == MotionNotify) {
   1200 -		if (x == ox && y == oy)
   1201 -			return;
   1202 -		if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
   1203 -			return;
   1204 -		/* MOUSE_MOTION: no reporting if no button is pressed */
   1205 -		if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3)
   1206 -			return;
   1207 -
   1208 -		button = oldbutton + 32;
   1209 -		ox = x;
   1210 -		oy = y;
   1211 -	} else {
   1212 -		if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) {
   1213 -			button = 3;
   1214 -		} else {
   1215 -			button -= Button1;
   1216 -			if (button >= 3)
   1217 -				button += 64 - 3;
   1218 -		}
   1219 -		if (e->xbutton.type == ButtonPress) {
   1220 -			oldbutton = button;
   1221 -			ox = x;
   1222 -			oy = y;
   1223 -		} else if (e->xbutton.type == ButtonRelease) {
   1224 -			oldbutton = 3;
   1225 -			/* MODE_MOUSEX10: no button release reporting */
   1226 -			if (IS_SET(MODE_MOUSEX10))
   1227 -				return;
   1228 -			if (button == 64 || button == 65)
   1229 -				return;
   1230 -		}
   1231 -	}
   1232  
   1233  	if (!IS_SET(MODE_MOUSEX10)) {
   1234 -		button += ((state & ShiftMask  ) ? 4  : 0)
   1235 -			+ ((state & Mod4Mask   ) ? 8  : 0)
   1236 -			+ ((state & ControlMask) ? 16 : 0);
   1237 +		button += ((wl.xkb.mods & MOD_MASK_SHIFT) ? 4  : 0)
   1238 +			+ ((wl.xkb.mods & MOD_MASK_LOGO ) ? 8  : 0)
   1239 +			+ ((wl.xkb.mods & MOD_MASK_CTRL ) ? 16 : 0);
   1240  	}
   1241  
   1242  	if (IS_SET(MODE_MOUSESGR)) {
   1243  		len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
   1244 -				button, x+1, y+1,
   1245 -				e->xbutton.type == ButtonRelease ? 'm' : 'M');
   1246 +				button, x+1, y+1, release ? 'm' : 'M');
   1247  	} else if (x < 223 && y < 223) {
   1248  		len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
   1249  				32+button, 32+x+1, 32+y+1);
   1250 @@ -953,53 +970,59 @@ mousereport(XEvent *e)
   1251  }
   1252  
   1253  void
   1254 -bpress(XEvent *e)
   1255 +wlmousereportbutton(uint32_t button, uint32_t state)
   1256  {
   1257 -	struct timespec now;
   1258 -	MouseShortcut *ms;
   1259 +	bool release = state == WL_POINTER_BUTTON_STATE_RELEASED;
   1260  
   1261 -	if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) {
   1262 -		mousereport(e);
   1263 -		return;
   1264 +	if (!IS_SET(MODE_MOUSESGR) && release) {
   1265 +		button = 3;
   1266 +	} else {
   1267 +		switch (button) {
   1268 +		case BTN_LEFT:
   1269 +			button = 0;
   1270 +			break;
   1271 +		case BTN_MIDDLE:
   1272 +			button = 1;
   1273 +			break;
   1274 +		case BTN_RIGHT:
   1275 +			button = 2;
   1276 +			break;
   1277 +		}
   1278  	}
   1279  
   1280 -	for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
   1281 -		if (e->xbutton.button == ms->b
   1282 -				&& match(ms->mask, e->xbutton.state)) {
   1283 -			ttysend(ms->s, strlen(ms->s));
   1284 -			return;
   1285 -		}
   1286 +	oldbutton = release ? 3 : button;
   1287 +
   1288 +	/* don't report release events when in X10 mode */
   1289 +	if (IS_SET(MODE_MOUSEX10) && release) {
   1290 +		return;
   1291  	}
   1292  
   1293 -	if (e->xbutton.button == Button1) {
   1294 -		clock_gettime(CLOCK_MONOTONIC, &now);
   1295 +	wlmousereport(button, release, oldx, oldy);
   1296 +}
   1297  
   1298 -		/* Clear previous selection, logically and visually. */
   1299 -		selclear(NULL);
   1300 -		sel.mode = SEL_EMPTY;
   1301 -		sel.type = SEL_REGULAR;
   1302 -		sel.oe.x = sel.ob.x = x2col(e->xbutton.x);
   1303 -		sel.oe.y = sel.ob.y = y2row(e->xbutton.y);
   1304 +void
   1305 +wlmousereportmotion(wl_fixed_t fx, wl_fixed_t fy)
   1306 +{
   1307 +	int x = x2col(wl_fixed_to_int(fx)), y = y2row(wl_fixed_to_int(fy));
   1308  
   1309 -		/*
   1310 -		 * If the user clicks below predefined timeouts specific
   1311 -		 * snapping behaviour is exposed.
   1312 -		 */
   1313 -		if (TIMEDIFF(now, sel.tclick2) <= tripleclicktimeout) {
   1314 -			sel.snap = SNAP_LINE;
   1315 -		} else if (TIMEDIFF(now, sel.tclick1) <= doubleclicktimeout) {
   1316 -			sel.snap = SNAP_WORD;
   1317 -		} else {
   1318 -			sel.snap = 0;
   1319 -		}
   1320 -		selnormalize();
   1321 +	if (x == oldx && y == oldy)
   1322 +		return;
   1323 +	if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
   1324 +		return;
   1325 +	/* MOUSE_MOTION: no reporting if no button is pressed */
   1326 +	if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3)
   1327 +		return;
   1328  
   1329 -		if (sel.snap != 0)
   1330 -			sel.mode = SEL_READY;
   1331 -		tsetdirt(sel.nb.y, sel.ne.y);
   1332 -		sel.tclick2 = sel.tclick1;
   1333 -		sel.tclick1 = now;
   1334 -	}
   1335 +	oldx = x;
   1336 +	oldy = y;
   1337 +	wlmousereport(oldbutton + 32, false, x, y);
   1338 +}
   1339 +
   1340 +void
   1341 +wlmousereportaxis(uint32_t axis, wl_fixed_t amount)
   1342 +{
   1343 +	wlmousereport(64 + (axis == AXIS_VERTICAL ? 4 : 6)
   1344 +		+ (amount > 0 ? 1 : 0), false, oldx, oldy);
   1345  }
   1346  
   1347  char *
   1348 @@ -1057,148 +1080,67 @@ getsel(void)
   1349  }
   1350  
   1351  void
   1352 -selcopy(Time t)
   1353 -{
   1354 -	xsetsel(getsel(), t);
   1355 -}
   1356 -
   1357 -void
   1358 -propnotify(XEvent *e)
   1359 +selcopy(uint32_t serial)
   1360  {
   1361 -	XPropertyEvent *xpev;
   1362 -	Atom clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
   1363 -
   1364 -	xpev = &e->xproperty;
   1365 -	if (xpev->state == PropertyNewValue &&
   1366 -			(xpev->atom == XA_PRIMARY ||
   1367 -			 xpev->atom == clipboard)) {
   1368 -		selnotify(e);
   1369 -	}
   1370 +	wlsetsel(getsel(), serial);
   1371  }
   1372  
   1373 -void
   1374 -selnotify(XEvent *e)
   1375 +static inline void
   1376 +selwritebuf(char *buf, int len)
   1377  {
   1378 -	ulong nitems, ofs, rem;
   1379 -	int format;
   1380 -	uchar *data, *last, *repl;
   1381 -	Atom type, incratom, property;
   1382 -
   1383 -	incratom = XInternAtom(xw.dpy, "INCR", 0);
   1384 -
   1385 -	ofs = 0;
   1386 -	if (e->type == SelectionNotify) {
   1387 -		property = e->xselection.property;
   1388 -	} else if(e->type == PropertyNotify) {
   1389 -		property = e->xproperty.atom;
   1390 -	} else {
   1391 -		return;
   1392 -	}
   1393 -	if (property == None)
   1394 -		return;
   1395 -
   1396 -	do {
   1397 -		if (XGetWindowProperty(xw.dpy, xw.win, property, ofs,
   1398 -					BUFSIZ/4, False, AnyPropertyType,
   1399 -					&type, &format, &nitems, &rem,
   1400 -					&data)) {
   1401 -			fprintf(stderr, "Clipboard allocation failed\n");
   1402 -			return;
   1403 -		}
   1404 -
   1405 -		if (e->type == PropertyNotify && nitems == 0 && rem == 0) {
   1406 -			/*
   1407 -			 * If there is some PropertyNotify with no data, then
   1408 -			 * this is the signal of the selection owner that all
   1409 -			 * data has been transferred. We won't need to receive
   1410 -			 * PropertyNotify events anymore.
   1411 -			 */
   1412 -			MODBIT(xw.attrs.event_mask, 0, PropertyChangeMask);
   1413 -			XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
   1414 -					&xw.attrs);
   1415 -		}
   1416 -
   1417 -		if (type == incratom) {
   1418 -			/*
   1419 -			 * Activate the PropertyNotify events so we receive
   1420 -			 * when the selection owner does send us the next
   1421 -			 * chunk of data.
   1422 -			 */
   1423 -			MODBIT(xw.attrs.event_mask, 1, PropertyChangeMask);
   1424 -			XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask,
   1425 -					&xw.attrs);
   1426 -
   1427 -			/*
   1428 -			 * Deleting the property is the transfer start signal.
   1429 -			 */
   1430 -			XDeleteProperty(xw.dpy, xw.win, (int)property);
   1431 -			continue;
   1432 -		}
   1433 -
   1434 -		/*
   1435 -		 * As seen in getsel:
   1436 -		 * Line endings are inconsistent in the terminal and GUI world
   1437 -		 * copy and pasting. When receiving some selection data,
   1438 -		 * replace all '\n' with '\r'.
   1439 -		 * FIXME: Fix the computer world.
   1440 -		 */
   1441 -		repl = data;
   1442 -		last = data + nitems * format / 8;
   1443 -		while ((repl = memchr(repl, '\n', last - repl))) {
   1444 -			*repl++ = '\r';
   1445 -		}
   1446 -
   1447 -		if (IS_SET(MODE_BRCKTPASTE) && ofs == 0)
   1448 -			ttywrite("\033[200~", 6);
   1449 -		ttysend((char *)data, nitems * format / 8);
   1450 -		if (IS_SET(MODE_BRCKTPASTE) && rem == 0)
   1451 -			ttywrite("\033[201~", 6);
   1452 -		XFree(data);
   1453 -		/* number of 32-bit chunks returned */
   1454 -		ofs += nitems * format / 32;
   1455 -	} while (rem > 0);
   1456 +	char *repl = buf;
   1457  
   1458  	/*
   1459 -	 * Deleting the property again tells the selection owner to send the
   1460 -	 * next data chunk in the property.
   1461 +	 * As seen in getsel:
   1462 +	 * Line endings are inconsistent in the terminal and GUI world
   1463 +	 * copy and pasting. When receiving some selection data,
   1464 +	 * replace all '\n' with '\r'.
   1465 +	 * FIXME: Fix the computer world.
   1466  	 */
   1467 -	XDeleteProperty(xw.dpy, xw.win, (int)property);
   1468 -}
   1469 +	while ((repl = memchr(repl, '\n', len))) {
   1470 +		*repl++ = '\r';
   1471 +	}
   1472  
   1473 -void
   1474 -selpaste(const Arg *dummy)
   1475 -{
   1476 -	XConvertSelection(xw.dpy, XA_PRIMARY, sel.xtarget, XA_PRIMARY,
   1477 -			xw.win, CurrentTime);
   1478 +	ttysend(buf, len);
   1479  }
   1480  
   1481  void
   1482 -clipcopy(const Arg *dummy)
   1483 +selpaste(const Arg *dummy)
   1484  {
   1485 -	Atom clipboard;
   1486 +	int fds[2], len, left;
   1487 +	char buf[BUFSIZ], *str;
   1488  
   1489 -	if (sel.clipboard != NULL)
   1490 -		free(sel.clipboard);
   1491 -
   1492 -	if (sel.primary != NULL) {
   1493 -		sel.clipboard = xstrdup(sel.primary);
   1494 -		clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
   1495 -		XSetSelectionOwner(xw.dpy, clipboard, xw.win, CurrentTime);
   1496 +	if (wl.seloffer) {
   1497 +		if (IS_SET(MODE_BRCKTPASTE))
   1498 +			ttywrite("\033[200~", 6);
   1499 +		/* check if we are pasting from ourselves */
   1500 +		if (sel.source) {
   1501 +			str = sel.primary;
   1502 +			left = strlen(sel.primary);
   1503 +			while (left > 0) {
   1504 +				len = MIN(sizeof buf, left);
   1505 +				memcpy(buf, str, len);
   1506 +				selwritebuf(buf, len);
   1507 +				left -= len;
   1508 +				str += len;
   1509 +			}
   1510 +		} else {
   1511 +			pipe(fds);
   1512 +			wl_data_offer_receive(wl.seloffer, "text/plain", fds[1]);
   1513 +			close(fds[1]);
   1514 +			wl_display_flush(wl.dpy);
   1515 +			while ((len = read(fds[0], buf, sizeof buf)) > 0) {
   1516 +				selwritebuf(buf, len);
   1517 +			}
   1518 +			close(fds[0]);
   1519 +		}
   1520 +		if (IS_SET(MODE_BRCKTPASTE))
   1521 +			ttywrite("\033[201~", 6);
   1522  	}
   1523  }
   1524  
   1525  void
   1526 -clippaste(const Arg *dummy)
   1527 -{
   1528 -	Atom clipboard;
   1529 -
   1530 -	clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
   1531 -	XConvertSelection(xw.dpy, clipboard, sel.xtarget, clipboard,
   1532 -			xw.win, CurrentTime);
   1533 -}
   1534 -
   1535 -void
   1536 -selclear(XEvent *e)
   1537 +selclear(void)
   1538  {
   1539  	if (sel.ob.x == -1)
   1540  		return;
   1541 @@ -1208,117 +1150,19 @@ selclear(XEvent *e)
   1542  }
   1543  
   1544  void
   1545 -selrequest(XEvent *e)
   1546 -{
   1547 -	XSelectionRequestEvent *xsre;
   1548 -	XSelectionEvent xev;
   1549 -	Atom xa_targets, string, clipboard;
   1550 -	char *seltext;
   1551 -
   1552 -	xsre = (XSelectionRequestEvent *) e;
   1553 -	xev.type = SelectionNotify;
   1554 -	xev.requestor = xsre->requestor;
   1555 -	xev.selection = xsre->selection;
   1556 -	xev.target = xsre->target;
   1557 -	xev.time = xsre->time;
   1558 -	if (xsre->property == None)
   1559 -		xsre->property = xsre->target;
   1560 -
   1561 -	/* reject */
   1562 -	xev.property = None;
   1563 -
   1564 -	xa_targets = XInternAtom(xw.dpy, "TARGETS", 0);
   1565 -	if (xsre->target == xa_targets) {
   1566 -		/* respond with the supported type */
   1567 -		string = sel.xtarget;
   1568 -		XChangeProperty(xsre->display, xsre->requestor, xsre->property,
   1569 -				XA_ATOM, 32, PropModeReplace,
   1570 -				(uchar *) &string, 1);
   1571 -		xev.property = xsre->property;
   1572 -	} else if (xsre->target == sel.xtarget || xsre->target == XA_STRING) {
   1573 -		/*
   1574 -		 * xith XA_STRING non ascii characters may be incorrect in the
   1575 -		 * requestor. It is not our problem, use utf8.
   1576 -		 */
   1577 -		clipboard = XInternAtom(xw.dpy, "CLIPBOARD", 0);
   1578 -		if (xsre->selection == XA_PRIMARY) {
   1579 -			seltext = sel.primary;
   1580 -		} else if (xsre->selection == clipboard) {
   1581 -			seltext = sel.clipboard;
   1582 -		} else {
   1583 -			fprintf(stderr,
   1584 -				"Unhandled clipboard selection 0x%lx\n",
   1585 -				xsre->selection);
   1586 -			return;
   1587 -		}
   1588 -		if (seltext != NULL) {
   1589 -			XChangeProperty(xsre->display, xsre->requestor,
   1590 -					xsre->property, xsre->target,
   1591 -					8, PropModeReplace,
   1592 -					(uchar *)seltext, strlen(seltext));
   1593 -			xev.property = xsre->property;
   1594 -		}
   1595 -	}
   1596 -
   1597 -	/* all done, send a notification to the listener */
   1598 -	if (!XSendEvent(xsre->display, xsre->requestor, 1, 0, (XEvent *) &xev))
   1599 -		fprintf(stderr, "Error sending SelectionNotify event\n");
   1600 -}
   1601 -
   1602 -void
   1603 -xsetsel(char *str, Time t)
   1604 +wlsetsel(char *str, uint32_t serial)
   1605  {
   1606  	free(sel.primary);
   1607  	sel.primary = str;
   1608  
   1609 -	XSetSelectionOwner(xw.dpy, XA_PRIMARY, xw.win, t);
   1610 -	if (XGetSelectionOwner(xw.dpy, XA_PRIMARY) != xw.win)
   1611 -		selclear(0);
   1612 -}
   1613 -
   1614 -void
   1615 -brelease(XEvent *e)
   1616 -{
   1617 -	if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) {
   1618 -		mousereport(e);
   1619 -		return;
   1620 -	}
   1621 -
   1622 -	if (e->xbutton.button == Button2) {
   1623 -		selpaste(NULL);
   1624 -	} else if (e->xbutton.button == Button1) {
   1625 -		if (sel.mode == SEL_READY) {
   1626 -			getbuttoninfo(e);
   1627 -			selcopy(e->xbutton.time);
   1628 -		} else
   1629 -			selclear(NULL);
   1630 -		sel.mode = SEL_IDLE;
   1631 -		tsetdirt(sel.nb.y, sel.ne.y);
   1632 -	}
   1633 -}
   1634 -
   1635 -void
   1636 -bmotion(XEvent *e)
   1637 -{
   1638 -	int oldey, oldex, oldsby, oldsey;
   1639 -
   1640 -	if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forceselmod)) {
   1641 -		mousereport(e);
   1642 -		return;
   1643 +	if (str) {
   1644 +		sel.source = wl_data_device_manager_create_data_source(wl.datadevmanager);
   1645 +		wl_data_source_add_listener(sel.source, &datasrclistener, NULL);
   1646 +		wl_data_source_offer(sel.source, "text/plain;charset=utf-8");
   1647 +	} else {
   1648 +		sel.source = NULL;
   1649  	}
   1650 -
   1651 -	if (!sel.mode)
   1652 -		return;
   1653 -
   1654 -	sel.mode = SEL_READY;
   1655 -	oldey = sel.oe.y;
   1656 -	oldex = sel.oe.x;
   1657 -	oldsby = sel.nb.y;
   1658 -	oldsey = sel.ne.y;
   1659 -	getbuttoninfo(e);
   1660 -
   1661 -	if (oldey != sel.oe.y || oldex != sel.oe.x)
   1662 -		tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey));
   1663 +	wl_data_device_set_selection(wl.datadev, sel.source, serial);
   1664  }
   1665  
   1666  void
   1667 @@ -1337,7 +1181,6 @@ execsh(void)
   1668  {
   1669  	char **args, *sh, *prog;
   1670  	const struct passwd *pw;
   1671 -	char buf[sizeof(long) * 8 + 1];
   1672  
   1673  	errno = 0;
   1674  	if ((pw = getpwuid(getuid())) == NULL) {
   1675 @@ -1358,8 +1201,6 @@ execsh(void)
   1676  		prog = sh;
   1677  	args = (opt_cmd) ? opt_cmd : (char *[]) {prog, NULL};
   1678  
   1679 -	snprintf(buf, sizeof(buf), "%lu", xw.win);
   1680 -
   1681  	unsetenv("COLUMNS");
   1682  	unsetenv("LINES");
   1683  	unsetenv("TERMCAP");
   1684 @@ -1368,7 +1209,6 @@ execsh(void)
   1685  	setenv("SHELL", sh, 1);
   1686  	setenv("HOME", pw->pw_dir, 1);
   1687  	setenv("TERM", termname, 1);
   1688 -	setenv("WINDOWID", buf, 1);
   1689  
   1690  	signal(SIGCHLD, SIG_DFL);
   1691  	signal(SIGHUP, SIG_DFL);
   1692 @@ -1513,6 +1353,7 @@ ttyread(void)
   1693  	if (buflen > 0)
   1694  		memmove(buf, ptr, buflen);
   1695  
   1696 +	needdraw = true;
   1697  	return ret;
   1698  }
   1699  
   1700 @@ -1606,8 +1447,8 @@ ttyresize(void)
   1701  
   1702  	w.ws_row = term.row;
   1703  	w.ws_col = term.col;
   1704 -	w.ws_xpixel = xw.tw;
   1705 -	w.ws_ypixel = xw.th;
   1706 +	w.ws_xpixel = wl.tw;
   1707 +	w.ws_ypixel = wl.th;
   1708  	if (ioctl(cmdfd, TIOCSWINSZ, &w) < 0)
   1709  		fprintf(stderr, "Couldn't set window size: %s\n", strerror(errno));
   1710  }
   1711 @@ -1637,6 +1478,8 @@ tsetdirt(int top, int bot)
   1712  
   1713  	for (i = top; i <= bot; i++)
   1714  		term.dirty[i] = 1;
   1715 +
   1716 +	needdraw = true;
   1717  }
   1718  
   1719  void
   1720 @@ -1771,7 +1614,7 @@ selscroll(int orig, int n)
   1721  
   1722  	if (BETWEEN(sel.ob.y, orig, term.bot) || BETWEEN(sel.oe.y, orig, term.bot)) {
   1723  		if ((sel.ob.y += n) > term.bot || (sel.oe.y += n) < term.top) {
   1724 -			selclear(NULL);
   1725 +			selclear();
   1726  			return;
   1727  		}
   1728  		if (sel.type == SEL_RECTANGULAR) {
   1729 @@ -1917,7 +1760,7 @@ tclearregion(int x1, int y1, int x2, int y2)
   1730  		for (x = x1; x <= x2; x++) {
   1731  			gp = &term.line[y][x];
   1732  			if (selected(x, y))
   1733 -				selclear(NULL);
   1734 +				selclear();
   1735  			gp->fg = term.c.attr.fg;
   1736  			gp->bg = term.c.attr.bg;
   1737  			gp->mode = 0;
   1738 @@ -2180,22 +2023,18 @@ tsetmode(int priv, int set, int *args, int narg)
   1739  				MODBIT(term.mode, !set, MODE_HIDE);
   1740  				break;
   1741  			case 9:    /* X10 mouse compatibility mode */
   1742 -				xsetpointermotion(0);
   1743  				MODBIT(term.mode, 0, MODE_MOUSE);
   1744  				MODBIT(term.mode, set, MODE_MOUSEX10);
   1745  				break;
   1746  			case 1000: /* 1000: report button press */
   1747 -				xsetpointermotion(0);
   1748  				MODBIT(term.mode, 0, MODE_MOUSE);
   1749  				MODBIT(term.mode, set, MODE_MOUSEBTN);
   1750  				break;
   1751  			case 1002: /* 1002: report motion on button press */
   1752 -				xsetpointermotion(0);
   1753  				MODBIT(term.mode, 0, MODE_MOUSE);
   1754  				MODBIT(term.mode, set, MODE_MOUSEMOTION);
   1755  				break;
   1756  			case 1003: /* 1003: enable all mouse motions */
   1757 -				xsetpointermotion(set);
   1758  				MODBIT(term.mode, 0, MODE_MOUSE);
   1759  				MODBIT(term.mode, set, MODE_MOUSEMANY);
   1760  				break;
   1761 @@ -2368,7 +2207,7 @@ csihandle(void)
   1762  		tputtab(csiescseq.arg[0]);
   1763  		break;
   1764  	case 'J': /* ED -- Clear screen */
   1765 -		selclear(NULL);
   1766 +		selclear();
   1767  		switch (csiescseq.arg[0]) {
   1768  		case 0: /* below */
   1769  			tclearregion(term.c.x, term.c.y, term.col-1, term.c.y);
   1770 @@ -2475,7 +2314,7 @@ csihandle(void)
   1771  			if (!BETWEEN(csiescseq.arg[0], 0, 6)) {
   1772  				goto unknown;
   1773  			}
   1774 -			xw.cursor = csiescseq.arg[0];
   1775 +			wl.cursor = csiescseq.arg[0];
   1776  			break;
   1777  		default:
   1778  			goto unknown;
   1779 @@ -2531,7 +2370,7 @@ strhandle(void)
   1780  		case 1:
   1781  		case 2:
   1782  			if (narg > 1)
   1783 -				xsettitle(strescseq.args[1]);
   1784 +				wlsettitle(strescseq.args[1]);
   1785  			return;
   1786  		case 4: /* color set */
   1787  			if (narg < 3)
   1788 @@ -2540,7 +2379,7 @@ strhandle(void)
   1789  			/* FALLTHROUGH */
   1790  		case 104: /* color reset, here p = NULL */
   1791  			j = (narg > 1) ? atoi(strescseq.args[1]) : -1;
   1792 -			if (xsetcolorname(j, p)) {
   1793 +			if (wlsetcolorname(j, p)) {
   1794  				fprintf(stderr, "erresc: invalid color %s\n", p);
   1795  			} else {
   1796  				/*
   1797 @@ -2553,7 +2392,7 @@ strhandle(void)
   1798  		}
   1799  		break;
   1800  	case 'k': /* old title set compatibility */
   1801 -		xsettitle(strescseq.args[0]);
   1802 +		wlsettitle(strescseq.args[0]);
   1803  		return;
   1804  	case 'P': /* DCS -- Device Control String */
   1805  		term.mode |= ESC_DCS;
   1806 @@ -2642,13 +2481,11 @@ tprinter(char *s, size_t len)
   1807  void
   1808  iso14755(const Arg *arg)
   1809  {
   1810 -	char cmd[sizeof(ISO14755CMD) + NUMMAXLEN(xw.win)];
   1811  	FILE *p;
   1812  	char *us, *e, codepoint[9], uc[UTF_SIZ];
   1813  	unsigned long utf32;
   1814  
   1815 -	snprintf(cmd, sizeof(cmd), ISO14755CMD, xw.win);
   1816 -	if (!(p = popen(cmd, "r")))
   1817 +	if (!(p = popen(ISO14755CMD, "r")))
   1818  		return;
   1819  
   1820  	us = fgets(codepoint, sizeof(codepoint), p);
   1821 @@ -2747,6 +2584,7 @@ techo(Rune u)
   1822  		}
   1823  	}
   1824  	tputc(u);
   1825 +	needdraw = true;
   1826  }
   1827  
   1828  void
   1829 @@ -2833,10 +2671,12 @@ tcontrolcode(uchar ascii)
   1830  			/* backwards compatibility to xterm */
   1831  			strhandle();
   1832  		} else {
   1833 -			if (!(xw.state & WIN_FOCUSED))
   1834 -				xseturgency(1);
   1835 -			if (bellvolume)
   1836 -				XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL);
   1837 +			if (!(wl.state & WIN_FOCUSED))
   1838 +				wlseturgency(1);
   1839 +			/* XXX: No bell on wayland
   1840 +			 * if (bellvolume)
   1841 +			 *     XkbBell(xw.dpy, xw.win, bellvolume, (Atom)NULL);
   1842 +			 */
   1843  		}
   1844  		break;
   1845  	case '\033': /* ESC */
   1846 @@ -2968,8 +2808,8 @@ eschandle(uchar ascii)
   1847  		break;
   1848  	case 'c': /* RIS -- Reset to inital state */
   1849  		treset();
   1850 -		xresettitle();
   1851 -		xloadcols();
   1852 +		wlresettitle();
   1853 +		wlloadcols();
   1854  		break;
   1855  	case '=': /* DECPAM -- Application keypad */
   1856  		term.mode |= MODE_APPKEYPAD;
   1857 @@ -3026,7 +2866,7 @@ tputc(Rune u)
   1858  	 */
   1859  	if (term.esc & ESC_STR) {
   1860  		if (u == '\a' || u == 030 || u == 032 || u == 033 ||
   1861 -		   ISCONTROLC1(u)) {
   1862 +		    ISCONTROLC1(u)) {
   1863  			term.esc &= ~(ESC_START|ESC_STR|ESC_DCS);
   1864  			if (IS_SET(MODE_SIXEL)) {
   1865  				/* TODO: render sixel */;
   1866 @@ -3109,7 +2949,7 @@ check_control_code:
   1867  		return;
   1868  	}
   1869  	if (sel.ob.x != -1 && BETWEEN(term.c.y, sel.ob.y, sel.oe.y))
   1870 -		selclear(NULL);
   1871 +		selclear();
   1872  
   1873  	gp = &term.line[term.c.y][term.c.x];
   1874  	if (IS_SET(MODE_WRAP) && (term.c.state & CURSOR_WRAPNEXT)) {
   1875 @@ -3176,9 +3016,6 @@ tresize(int col, int row)
   1876  		free(term.alt[i]);
   1877  	}
   1878  
   1879 -	/* resize to new width */
   1880 -	term.specbuf = xrealloc(term.specbuf, col * sizeof(XftGlyphFontSpec));
   1881 -
   1882  	/* resize to new height */
   1883  	term.line = xrealloc(term.line, row * sizeof(Line));
   1884  	term.alt  = xrealloc(term.alt,  row * sizeof(Line));
   1885 @@ -3228,155 +3065,107 @@ tresize(int col, int row)
   1886  }
   1887  
   1888  void
   1889 -xresize(int col, int row)
   1890 +wlresize(int col, int row)
   1891  {
   1892 -	xw.tw = MAX(1, col * xw.cw);
   1893 -	xw.th = MAX(1, row * xw.ch);
   1894 +	union wld_object object;
   1895 +
   1896 +	wl.tw = MAX(1, col * wl.cw);
   1897 +	wl.th = MAX(1, row * wl.ch);
   1898  
   1899 -	XFreePixmap(xw.dpy, xw.buf);
   1900 -	xw.buf = XCreatePixmap(xw.dpy, xw.win, xw.w, xw.h,
   1901 -			DefaultDepth(xw.dpy, xw.scr));
   1902 -	XftDrawChange(xw.draw, xw.buf);
   1903 -	xclear(0, 0, xw.w, xw.h);
   1904 +	wld.oldbuffer = wld.buffer;
   1905 +	wld.buffer = wld_create_buffer(wld.ctx, wl.w, wl.h,
   1906 +			WLD_FORMAT_XRGB8888, 0);
   1907 +	wld_export(wld.buffer, WLD_WAYLAND_OBJECT_BUFFER, &object);
   1908 +	wl.buffer = object.ptr;
   1909  }
   1910  
   1911 -ushort
   1912 -sixd_to_16bit(int x)
   1913 +uchar
   1914 +sixd_to_8bit(int x)
   1915  {
   1916 -	return x == 0 ? 0 : 0x3737 + 0x2828 * x;
   1917 +	return x == 0 ? 0 : 0x37 + 0x28 * x;
   1918  }
   1919  
   1920  int
   1921 -xloadcolor(int i, const char *name, Color *ncolor)
   1922 +wlloadcolor(int i, const char *name, uint32_t *color)
   1923  {
   1924 -	XRenderColor color = { .alpha = 0xffff };
   1925 -
   1926  	if (!name) {
   1927  		if (BETWEEN(i, 16, 255)) { /* 256 color */
   1928  			if (i < 6*6*6+16) { /* same colors as xterm */
   1929 -				color.red   = sixd_to_16bit( ((i-16)/36)%6 );
   1930 -				color.green = sixd_to_16bit( ((i-16)/6) %6 );
   1931 -				color.blue  = sixd_to_16bit( ((i-16)/1) %6 );
   1932 +				*color = 0xff << 24 | sixd_to_8bit(((i-16)/36)%6) << 16
   1933 +					| sixd_to_8bit(((i-16)/6)%6) << 8
   1934 +					| sixd_to_8bit(((i-16)/1)%6);
   1935  			} else { /* greyscale */
   1936 -				color.red = 0x0808 + 0x0a0a * (i - (6*6*6+16));
   1937 -				color.green = color.blue = color.red;
   1938 +				*color = 0xff << 24 | (0x8 + 0xa * (i-(6*6*6+16))) * 0x10101;
   1939  			}
   1940 -			return XftColorAllocValue(xw.dpy, xw.vis,
   1941 -			                          xw.cmap, &color, ncolor);
   1942 +			return true;
   1943  		} else
   1944  			name = colorname[i];
   1945  	}
   1946  
   1947 -	return XftColorAllocName(xw.dpy, xw.vis, xw.cmap, name, ncolor);
   1948 +	return wld_lookup_named_color(name, color);
   1949  }
   1950  
   1951  void
   1952 -xloadcols(void)
   1953 +wlloadcols(void)
   1954  {
   1955  	int i;
   1956 -	static int loaded;
   1957 -	Color *cp;
   1958 -
   1959 -	if (loaded) {
   1960 -		for (cp = dc.col; cp < &dc.col[LEN(dc.col)]; ++cp)
   1961 -			XftColorFree(xw.dpy, xw.vis, xw.cmap, cp);
   1962 -	}
   1963  
   1964  	for (i = 0; i < LEN(dc.col); i++)
   1965 -		if (!xloadcolor(i, NULL, &dc.col[i])) {
   1966 +		if (!wlloadcolor(i, NULL, &dc.col[i])) {
   1967  			if (colorname[i])
   1968  				die("Could not allocate color '%s'\n", colorname[i]);
   1969  			else
   1970  				die("Could not allocate color %d\n", i);
   1971  		}
   1972 -	loaded = 1;
   1973  }
   1974  
   1975  int
   1976 -xsetcolorname(int x, const char *name)
   1977 +wlsetcolorname(int x, const char *name)
   1978  {
   1979 -	Color ncolor;
   1980 +	uint32_t color;
   1981  
   1982  	if (!BETWEEN(x, 0, LEN(dc.col)))
   1983  		return 1;
   1984  
   1985 -
   1986 -	if (!xloadcolor(x, name, &ncolor))
   1987 +	if (!wlloadcolor(x, name, &color))
   1988  		return 1;
   1989  
   1990 -	XftColorFree(xw.dpy, xw.vis, xw.cmap, &dc.col[x]);
   1991 -	dc.col[x] = ncolor;
   1992 +	dc.col[x] = color;
   1993  
   1994  	return 0;
   1995  }
   1996  
   1997 -/*
   1998 - * Absolute coordinates.
   1999 - */
   2000 -void
   2001 -xclear(int x1, int y1, int x2, int y2)
   2002 +static void wlloadcursor(void)
   2003  {
   2004 -	XftDrawRect(xw.draw,
   2005 -			&dc.col[IS_SET(MODE_REVERSE)? defaultfg : defaultbg],
   2006 -			x1, y1, x2-x1, y2-y1);
   2007 -}
   2008 +	char *names[] = { mouseshape, "xterm", "ibeam", "text" };
   2009 +	int i;
   2010  
   2011 -void
   2012 -xhints(void)
   2013 -{
   2014 -	XClassHint class = {opt_name ? opt_name : termname,
   2015 -	                    opt_class ? opt_class : termname};
   2016 -	XWMHints wm = {.flags = InputHint, .input = 1};
   2017 -	XSizeHints *sizeh = NULL;
   2018 -
   2019 -	sizeh = XAllocSizeHints();
   2020 -
   2021 -	sizeh->flags = PSize | PResizeInc | PBaseSize;
   2022 -	sizeh->height = xw.h;
   2023 -	sizeh->width = xw.w;
   2024 -	sizeh->height_inc = xw.ch;
   2025 -	sizeh->width_inc = xw.cw;
   2026 -	sizeh->base_height = 2 * borderpx;
   2027 -	sizeh->base_width = 2 * borderpx;
   2028 -	if (xw.isfixed) {
   2029 -		sizeh->flags |= PMaxSize | PMinSize;
   2030 -		sizeh->min_width = sizeh->max_width = xw.w;
   2031 -		sizeh->min_height = sizeh->max_height = xw.h;
   2032 -	}
   2033 -	if (xw.gm & (XValue|YValue)) {
   2034 -		sizeh->flags |= USPosition | PWinGravity;
   2035 -		sizeh->x = xw.l;
   2036 -		sizeh->y = xw.t;
   2037 -		sizeh->win_gravity = xgeommasktogravity(xw.gm);
   2038 -	}
   2039 +	cursor.theme = wl_cursor_theme_load(NULL, 32, wl.shm);
   2040 +
   2041 +	for (i = 0; !cursor.cursor && i < LEN(names); i++)
   2042 +		cursor.cursor = wl_cursor_theme_get_cursor(cursor.theme, names[i]);
   2043  
   2044 -	XSetWMProperties(xw.dpy, xw.win, NULL, NULL, NULL, 0, sizeh, &wm,
   2045 -			&class);
   2046 -	XFree(sizeh);
   2047 +	cursor.surface = wl_compositor_create_surface(wl.cmp);
   2048  }
   2049  
   2050 -int
   2051 -xgeommasktogravity(int mask)
   2052 +/*
   2053 + * Absolute coordinates.
   2054 + */
   2055 +void
   2056 +wlclear(int x1, int y1, int x2, int y2)
   2057  {
   2058 -	switch (mask & (XNegative|YNegative)) {
   2059 -	case 0:
   2060 -		return NorthWestGravity;
   2061 -	case XNegative:
   2062 -		return NorthEastGravity;
   2063 -	case YNegative:
   2064 -		return SouthWestGravity;
   2065 -	}
   2066 +	uint32_t color = dc.col[IS_SET(MODE_REVERSE) ? defaultfg : defaultbg];
   2067  
   2068 -	return SouthEastGravity;
   2069 +	wld_fill_rectangle(wld.renderer, color, x1, y1, x2 - x1, y2 - y1);
   2070  }
   2071  
   2072  int
   2073 -xloadfont(Font *f, FcPattern *pattern)
   2074 +wlloadfont(Font *f, FcPattern *pattern)
   2075  {
   2076  	FcPattern *configured;
   2077  	FcPattern *match;
   2078  	FcResult result;
   2079 -	XGlyphInfo extents;
   2080 +	struct wld_extents extents;
   2081  	int wantattr, haveattr;
   2082  
   2083  	/*
   2084 @@ -3389,7 +3178,7 @@ xloadfont(Font *f, FcPattern *pattern)
   2085  		return 1;
   2086  
   2087  	FcConfigSubstitute(NULL, configured, FcMatchPattern);
   2088 -	XftDefaultSubstitute(xw.dpy, xw.scr, configured);
   2089 +	FcDefaultSubstitute(configured);
   2090  
   2091  	match = FcFontMatch(NULL, configured, &result);
   2092  	if (!match) {
   2093 @@ -3397,37 +3186,36 @@ xloadfont(Font *f, FcPattern *pattern)
   2094  		return 1;
   2095  	}
   2096  
   2097 -	if (!(f->match = XftFontOpenPattern(xw.dpy, match))) {
   2098 +	if (!(f->match = wld_font_open_pattern(wld.fontctx, match))) {
   2099  		FcPatternDestroy(configured);
   2100  		FcPatternDestroy(match);
   2101  		return 1;
   2102  	}
   2103  
   2104 -	if ((XftPatternGetInteger(pattern, "slant", 0, &wantattr) ==
   2105 -	    XftResultMatch)) {
   2106 +	if ((FcPatternGetInteger(pattern, "slant", 0, &wantattr) ==
   2107 +	    FcResultMatch)) {
   2108  		/*
   2109  		 * Check if xft was unable to find a font with the appropriate
   2110  		 * slant but gave us one anyway. Try to mitigate.
   2111  		 */
   2112 -		if ((XftPatternGetInteger(f->match->pattern, "slant", 0,
   2113 -		    &haveattr) != XftResultMatch) || haveattr < wantattr) {
   2114 +		if ((FcPatternGetInteger(match, "slant", 0,
   2115 +		    &haveattr) != FcResultMatch) || haveattr < wantattr) {
   2116  			f->badslant = 1;
   2117  			fputs("st: font slant does not match\n", stderr);
   2118  		}
   2119  	}
   2120  
   2121 -	if ((XftPatternGetInteger(pattern, "weight", 0, &wantattr) ==
   2122 -	    XftResultMatch)) {
   2123 -		if ((XftPatternGetInteger(f->match->pattern, "weight", 0,
   2124 -		    &haveattr) != XftResultMatch) || haveattr != wantattr) {
   2125 +	if ((FcPatternGetInteger(pattern, "weight", 0, &wantattr) ==
   2126 +	    FcResultMatch)) {
   2127 +		if ((FcPatternGetInteger(match, "weight", 0,
   2128 +		    &haveattr) != FcResultMatch) || haveattr != wantattr) {
   2129  			f->badweight = 1;
   2130  			fputs("st: font weight does not match\n", stderr);
   2131  		}
   2132  	}
   2133  
   2134 -	XftTextExtentsUtf8(xw.dpy, f->match,
   2135 -		(const FcChar8 *) ascii_printable,
   2136 -		strlen(ascii_printable), &extents);
   2137 +
   2138 +	wld_font_text_extents(f->match, ascii_printable, &extents);
   2139  
   2140  	f->set = NULL;
   2141  	f->pattern = configured;
   2142 @@ -3435,23 +3223,24 @@ xloadfont(Font *f, FcPattern *pattern)
   2143  	f->ascent = f->match->ascent;
   2144  	f->descent = f->match->descent;
   2145  	f->lbearing = 0;
   2146 -	f->rbearing = f->match->max_advance_width;
   2147 +	f->rbearing = f->match->max_advance;
   2148  
   2149  	f->height = f->ascent + f->descent;
   2150 -	f->width = DIVCEIL(extents.xOff, strlen(ascii_printable));
   2151 +	f->width = DIVCEIL(extents.advance, strlen(ascii_printable));
   2152  
   2153  	return 0;
   2154  }
   2155  
   2156  void
   2157 -xloadfonts(char *fontstr, double fontsize)
   2158 +wlloadfonts(char *fontstr, double fontsize)
   2159  {
   2160  	FcPattern *pattern;
   2161  	double fontval;
   2162  	float ceilf(float);
   2163  
   2164  	if (fontstr[0] == '-') {
   2165 -		pattern = XftXlfdParse(fontstr, False, False);
   2166 +		/* XXX: need XftXlfdParse equivalent */
   2167 +		pattern = NULL;
   2168  	} else {
   2169  		pattern = FcNameParse((FcChar8 *)fontstr);
   2170  	}
   2171 @@ -3482,11 +3271,14 @@ xloadfonts(char *fontstr, double fontsize)
   2172  		defaultfontsize = usedfontsize;
   2173  	}
   2174  
   2175 -	if (xloadfont(&dc.font, pattern))
   2176 +	FcConfigSubstitute(0, pattern, FcMatchPattern);
   2177 +	FcDefaultSubstitute(pattern);
   2178 +
   2179 +	if (wlloadfont(&dc.font, pattern))
   2180  		die("st: can't open font %s\n", fontstr);
   2181  
   2182  	if (usedfontsize < 0) {
   2183 -		FcPatternGetDouble(dc.font.match->pattern,
   2184 +		FcPatternGetDouble(dc.font.pattern,
   2185  		                   FC_PIXEL_SIZE, 0, &fontval);
   2186  		usedfontsize = fontval;
   2187  		if (fontsize == 0)
   2188 @@ -3494,282 +3286,339 @@ xloadfonts(char *fontstr, double fontsize)
   2189  	}
   2190  
   2191  	/* Setting character width and height. */
   2192 -	xw.cw = ceilf(dc.font.width * cwscale);
   2193 -	xw.ch = ceilf(dc.font.height * chscale);
   2194 +	wl.cw = ceilf(dc.font.width * cwscale);
   2195 +	wl.ch = ceilf(dc.font.height * chscale);
   2196  
   2197  	FcPatternDel(pattern, FC_SLANT);
   2198  	FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
   2199 -	if (xloadfont(&dc.ifont, pattern))
   2200 +	if (wlloadfont(&dc.ifont, pattern))
   2201  		die("st: can't open font %s\n", fontstr);
   2202  
   2203  	FcPatternDel(pattern, FC_WEIGHT);
   2204  	FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
   2205 -	if (xloadfont(&dc.ibfont, pattern))
   2206 +	if (wlloadfont(&dc.ibfont, pattern))
   2207  		die("st: can't open font %s\n", fontstr);
   2208  
   2209  	FcPatternDel(pattern, FC_SLANT);
   2210  	FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN);
   2211 -	if (xloadfont(&dc.bfont, pattern))
   2212 +	if (wlloadfont(&dc.bfont, pattern))
   2213  		die("st: can't open font %s\n", fontstr);
   2214  
   2215  	FcPatternDestroy(pattern);
   2216  }
   2217  
   2218  void
   2219 -xunloadfont(Font *f)
   2220 +wlunloadfont(Font *f)
   2221  {
   2222 -	XftFontClose(xw.dpy, f->match);
   2223 +	wld_font_close(f->match);
   2224  	FcPatternDestroy(f->pattern);
   2225  	if (f->set)
   2226  		FcFontSetDestroy(f->set);
   2227  }
   2228  
   2229  void
   2230 -xunloadfonts(void)
   2231 +wlunloadfonts(void)
   2232  {
   2233  	/* Free the loaded fonts in the font cache.  */
   2234  	while (frclen > 0)
   2235 -		XftFontClose(xw.dpy, frc[--frclen].font);
   2236 +		wld_font_close(frc[--frclen].font);
   2237  
   2238 -	xunloadfont(&dc.font);
   2239 -	xunloadfont(&dc.bfont);
   2240 -	xunloadfont(&dc.ifont);
   2241 -	xunloadfont(&dc.ibfont);
   2242 +	wlunloadfont(&dc.font);
   2243 +	wlunloadfont(&dc.bfont);
   2244 +	wlunloadfont(&dc.ifont);
   2245 +	wlunloadfont(&dc.ibfont);
   2246  }
   2247  
   2248  void
   2249 -xzoom(const Arg *arg)
   2250 +wlzoom(const Arg *arg)
   2251  {
   2252  	Arg larg;
   2253  
   2254  	larg.f = usedfontsize + arg->f;
   2255 -	xzoomabs(&larg);
   2256 +	wlzoomabs(&larg);
   2257  }
   2258  
   2259  void
   2260 -xzoomabs(const Arg *arg)
   2261 +wlzoomabs(const Arg *arg)
   2262  {
   2263 -	xunloadfonts();
   2264 -	xloadfonts(usedfont, arg->f);
   2265 +	wlunloadfonts();
   2266 +	wlloadfonts(usedfont, arg->f);
   2267  	cresize(0, 0);
   2268  	ttyresize();
   2269  	redraw();
   2270 -	xhints();
   2271 +	/* XXX: Should the window size be updated here because wayland doesn't
   2272 +	 * have a notion of hints?
   2273 +	 * xhints();
   2274 +	 */
   2275  }
   2276  
   2277  void
   2278 -xzoomreset(const Arg *arg)
   2279 +wlzoomreset(const Arg *arg)
   2280  {
   2281  	Arg larg;
   2282  
   2283  	if (defaultfontsize > 0) {
   2284  		larg.f = defaultfontsize;
   2285 -		xzoomabs(&larg);
   2286 +		wlzoomabs(&larg);
   2287  	}
   2288  }
   2289  
   2290  void
   2291 -xinit(void)
   2292 +wlinit(void)
   2293  {
   2294 -	XGCValues gcvalues;
   2295 -	Cursor cursor;
   2296 -	Window parent;
   2297 -	pid_t thispid = getpid();
   2298 -	XColor xmousefg, xmousebg;
   2299 +	struct wl_registry *registry;
   2300  
   2301 -	if (!(xw.dpy = XOpenDisplay(NULL)))
   2302 +	if (!(wl.dpy = wl_display_connect(NULL)))
   2303  		die("Can't open display\n");
   2304 -	xw.scr = XDefaultScreen(xw.dpy);
   2305 -	xw.vis = XDefaultVisual(xw.dpy, xw.scr);
   2306 +
   2307 +	registry = wl_display_get_registry(wl.dpy);
   2308 +	wl_registry_add_listener(registry, &reglistener, NULL);
   2309 +	wld.ctx = wld_wayland_create_context(wl.dpy, WLD_ANY);
   2310 +	wld.renderer = wld_create_renderer(wld.ctx);
   2311 +
   2312 +	wl_display_roundtrip(wl.dpy);
   2313 +
   2314 +	if (!wl.shm)
   2315 +		die("Display has no SHM\n");
   2316 +	if (!wl.seat)
   2317 +		die("Display has no seat\n");
   2318 +	if (!wl.datadevmanager)
   2319 +		die("Display has no data device manager\n");
   2320 +	if (!wl.wm)
   2321 +		die("Display has no window manager\n");
   2322 +
   2323 +	wl.keyboard = wl_seat_get_keyboard(wl.seat);
   2324 +	wl_keyboard_add_listener(wl.keyboard, &kbdlistener, NULL);
   2325 +	wl.pointer = wl_seat_get_pointer(wl.seat);
   2326 +	wl_pointer_add_listener(wl.pointer, &ptrlistener, NULL);
   2327 +	wl.datadev = wl_data_device_manager_get_data_device(wl.datadevmanager,
   2328 +			wl.seat);
   2329 +	wl_data_device_add_listener(wl.datadev, &datadevlistener, NULL);
   2330  
   2331  	/* font */
   2332  	if (!FcInit())
   2333  		die("Could not init fontconfig.\n");
   2334  
   2335  	usedfont = (opt_font == NULL)? font : opt_font;
   2336 -	xloadfonts(usedfont, 0);
   2337 -
   2338 -	/* colors */
   2339 -	xw.cmap = XDefaultColormap(xw.dpy, xw.scr);
   2340 -	xloadcols();
   2341 -
   2342 -	/* adjust fixed window geometry */
   2343 -	xw.w = 2 * borderpx + term.col * xw.cw;
   2344 -	xw.h = 2 * borderpx + term.row * xw.ch;
   2345 -	if (xw.gm & XNegative)
   2346 -		xw.l += DisplayWidth(xw.dpy, xw.scr) - xw.w - 2;
   2347 -	if (xw.gm & YNegative)
   2348 -		xw.t += DisplayHeight(xw.dpy, xw.scr) - xw.h - 2;
   2349 -
   2350 -	/* Events */
   2351 -	xw.attrs.background_pixel = dc.col[defaultbg].pixel;
   2352 -	xw.attrs.border_pixel = dc.col[defaultbg].pixel;
   2353 -	xw.attrs.bit_gravity = NorthWestGravity;
   2354 -	xw.attrs.event_mask = FocusChangeMask | KeyPressMask
   2355 -		| ExposureMask | VisibilityChangeMask | StructureNotifyMask
   2356 -		| ButtonMotionMask | ButtonPressMask | ButtonReleaseMask;
   2357 -	xw.attrs.colormap = xw.cmap;
   2358 -
   2359 -	if (!(opt_embed && (parent = strtol(opt_embed, NULL, 0))))
   2360 -		parent = XRootWindow(xw.dpy, xw.scr);
   2361 -	xw.win = XCreateWindow(xw.dpy, parent, xw.l, xw.t,
   2362 -			xw.w, xw.h, 0, XDefaultDepth(xw.dpy, xw.scr), InputOutput,
   2363 -			xw.vis, CWBackPixel | CWBorderPixel | CWBitGravity
   2364 -			| CWEventMask | CWColormap, &xw.attrs);
   2365 -
   2366 -	memset(&gcvalues, 0, sizeof(gcvalues));
   2367 -	gcvalues.graphics_exposures = False;
   2368 -	dc.gc = XCreateGC(xw.dpy, parent, GCGraphicsExposures,
   2369 -			&gcvalues);
   2370 -	xw.buf = XCreatePixmap(xw.dpy, xw.win, xw.w, xw.h,
   2371 -			DefaultDepth(xw.dpy, xw.scr));
   2372 -	XSetForeground(xw.dpy, dc.gc, dc.col[defaultbg].pixel);
   2373 -	XFillRectangle(xw.dpy, xw.buf, dc.gc, 0, 0, xw.w, xw.h);
   2374 -
   2375 -	/* Xft rendering context */
   2376 -	xw.draw = XftDrawCreate(xw.dpy, xw.buf, xw.vis, xw.cmap);
   2377 -
   2378 -	/* input methods */
   2379 -	if ((xw.xim = XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) {
   2380 -		XSetLocaleModifiers("@im=local");
   2381 -		if ((xw.xim =  XOpenIM(xw.dpy, NULL, NULL, NULL)) == NULL) {
   2382 -			XSetLocaleModifiers("@im=");
   2383 -			if ((xw.xim = XOpenIM(xw.dpy,
   2384 -					NULL, NULL, NULL)) == NULL) {
   2385 -				die("XOpenIM failed. Could not open input"
   2386 -					" device.\n");
   2387 -			}
   2388 -		}
   2389 -	}
   2390 -	xw.xic = XCreateIC(xw.xim, XNInputStyle, XIMPreeditNothing
   2391 -					   | XIMStatusNothing, XNClientWindow, xw.win,
   2392 -					   XNFocusWindow, xw.win, NULL);
   2393 -	if (xw.xic == NULL)
   2394 -		die("XCreateIC failed. Could not obtain input method.\n");
   2395 -
   2396 -	/* white cursor, black outline */
   2397 -	cursor = XCreateFontCursor(xw.dpy, mouseshape);
   2398 -	XDefineCursor(xw.dpy, xw.win, cursor);
   2399 -
   2400 -	if (XParseColor(xw.dpy, xw.cmap, colorname[mousefg], &xmousefg) == 0) {
   2401 -		xmousefg.red   = 0xffff;
   2402 -		xmousefg.green = 0xffff;
   2403 -		xmousefg.blue  = 0xffff;
   2404 -	}
   2405 +	wld.fontctx = wld_font_create_context();
   2406 +	wlloadfonts(usedfont, 0);
   2407  
   2408 -	if (XParseColor(xw.dpy, xw.cmap, colorname[mousebg], &xmousebg) == 0) {
   2409 -		xmousebg.red   = 0x0000;
   2410 -		xmousebg.green = 0x0000;
   2411 -		xmousebg.blue  = 0x0000;
   2412 -	}
   2413 +	wlloadcols();
   2414 +	wlloadcursor();
   2415  
   2416 -	XRecolorCursor(xw.dpy, cursor, &xmousefg, &xmousebg);
   2417 +	wl.vis = 0;
   2418 +	wl.h = 2 * borderpx + term.row * wl.ch;
   2419 +	wl.w = 2 * borderpx + term.col * wl.cw;
   2420  
   2421 -	xw.xembed = XInternAtom(xw.dpy, "_XEMBED", False);
   2422 -	xw.wmdeletewin = XInternAtom(xw.dpy, "WM_DELETE_WINDOW", False);
   2423 -	xw.netwmname = XInternAtom(xw.dpy, "_NET_WM_NAME", False);
   2424 -	XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1);
   2425 +	wl.surface = wl_compositor_create_surface(wl.cmp);
   2426 +	wl_surface_add_listener(wl.surface, &surflistener, NULL);
   2427  
   2428 -	xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False);
   2429 -	XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32,
   2430 -			PropModeReplace, (uchar *)&thispid, 1);
   2431 +	wl.xdgsurface = xdg_wm_base_get_xdg_surface(wl.wm, wl.surface);
   2432 +	xdg_surface_add_listener(wl.xdgsurface, &xdgsurflistener, NULL);
   2433 +	wl.toplevel = xdg_surface_get_toplevel(wl.xdgsurface);
   2434 +	xdg_toplevel_add_listener(wl.toplevel, &toplevellistener, NULL);
   2435 +	xdg_toplevel_set_app_id(wl.toplevel, opt_class ? opt_class : termname);
   2436 +	wl_surface_commit(wl.surface);
   2437  
   2438 -	xresettitle();
   2439 -	XMapWindow(xw.dpy, xw.win);
   2440 -	xhints();
   2441 -	XSync(xw.dpy, False);
   2442 +	wl.xkb.ctx = xkb_context_new(0);
   2443 +	wlresettitle();
   2444  }
   2445  
   2446 -int
   2447 -xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y)
   2448 +/*
   2449 + * TODO: Implement something like XftDrawGlyphFontSpec in wld, and then apply a
   2450 + * similar patch to ae1923d27533ff46400d93765e971558201ca1ee
   2451 + */
   2452 +
   2453 +void
   2454 +wldraws(char *s, Glyph base, int x, int y, int charlen, int bytelen)
   2455  {
   2456 -	float winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, xp, yp;
   2457 -	ushort mode, prevmode = USHRT_MAX;
   2458 +	int winx = borderpx + x * wl.cw, winy = borderpx + y * wl.ch,
   2459 +	    width = charlen * wl.cw, xp, i;
   2460 +	int frcflags, charexists;
   2461 +	int u8fl, u8fblen, u8cblen, doesexist;
   2462 +	char *u8c, *u8fs;
   2463 +	Rune unicodep;
   2464  	Font *font = &dc.font;
   2465 -	int frcflags = FRC_NORMAL;
   2466 -	float runewidth = xw.cw;
   2467 -	Rune rune;
   2468 -	FT_UInt glyphidx;
   2469  	FcResult fcres;
   2470  	FcPattern *fcpattern, *fontpattern;
   2471  	FcFontSet *fcsets[] = { NULL };
   2472  	FcCharSet *fccharset;
   2473 -	int i, f, numspecs = 0;
   2474 +	uint32_t fg, bg, temp;
   2475 +	int oneatatime;
   2476  
   2477 -	for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) {
   2478 -		/* Fetch rune and mode for current glyph. */
   2479 -		rune = glyphs[i].u;
   2480 -		mode = glyphs[i].mode;
   2481 +	frcflags = FRC_NORMAL;
   2482  
   2483 -		/* Skip dummy wide-character spacing. */
   2484 -		if (mode == ATTR_WDUMMY)
   2485 -			continue;
   2486 +	/* Fallback on color display for attributes not supported by the font */
   2487 +	if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) {
   2488 +		if (dc.ibfont.badslant || dc.ibfont.badweight)
   2489 +			base.fg = defaultattr;
   2490 +		font = &dc.ibfont;
   2491 +		frcflags = FRC_ITALICBOLD;
   2492 +	} else if (base.mode & ATTR_ITALIC) {
   2493 +		if (dc.ifont.badslant)
   2494 +			base.fg = defaultattr;
   2495 +		font = &dc.ifont;
   2496 +		frcflags = FRC_ITALIC;
   2497 +	} else if (base.mode & ATTR_BOLD) {
   2498 +		if (dc.bfont.badweight)
   2499 +			base.fg = defaultattr;
   2500 +		font = &dc.ifont;
   2501 +		frcflags = FRC_BOLD;
   2502 +	}
   2503  
   2504 -		/* Determine font for glyph if different from previous glyph. */
   2505 -		if (prevmode != mode) {
   2506 -			prevmode = mode;
   2507 -			font = &dc.font;
   2508 -			frcflags = FRC_NORMAL;
   2509 -			runewidth = xw.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f);
   2510 -			if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) {
   2511 -				font = &dc.ibfont;
   2512 -				frcflags = FRC_ITALICBOLD;
   2513 -			} else if (mode & ATTR_ITALIC) {
   2514 -				font = &dc.ifont;
   2515 -				frcflags = FRC_ITALIC;
   2516 -			} else if (mode & ATTR_BOLD) {
   2517 -				font = &dc.bfont;
   2518 -				frcflags = FRC_BOLD;
   2519 -			}
   2520 -			yp = winy + font->ascent;
   2521 +	if (IS_TRUECOL(base.fg)) {
   2522 +		fg = base.fg | 0xff000000;
   2523 +	} else {
   2524 +		fg = dc.col[base.fg];
   2525 +	}
   2526 +
   2527 +	if (IS_TRUECOL(base.bg)) {
   2528 +		bg = base.bg | 0xff000000;
   2529 +	} else {
   2530 +		bg = dc.col[base.bg];
   2531 +	}
   2532 +
   2533 +	if (base.mode & ATTR_BOLD) {
   2534 +		/*
   2535 +		 * change basic system colors [0-7]
   2536 +		 * to bright system colors [8-15]
   2537 +		 */
   2538 +		if (BETWEEN(base.fg, 0, 7) && !(base.mode & ATTR_FAINT))
   2539 +			fg = dc.col[base.fg + 8];
   2540 +
   2541 +		if (base.mode & ATTR_ITALIC) {
   2542 +			font = &dc.ibfont;
   2543 +			frcflags = FRC_ITALICBOLD;
   2544 +		} else {
   2545 +			font = &dc.bfont;
   2546 +			frcflags = FRC_BOLD;
   2547  		}
   2548 +	}
   2549  
   2550 -		/* Lookup character index with default font. */
   2551 -		glyphidx = XftCharIndex(xw.dpy, font->match, rune);
   2552 -		if (glyphidx) {
   2553 -			specs[numspecs].font = font->match;
   2554 -			specs[numspecs].glyph = glyphidx;
   2555 -			specs[numspecs].x = (short)xp;
   2556 -			specs[numspecs].y = (short)yp;
   2557 -			xp += runewidth;
   2558 -			numspecs++;
   2559 -			continue;
   2560 +	if (IS_SET(MODE_REVERSE)) {
   2561 +		if (fg == dc.col[defaultfg]) {
   2562 +			fg = dc.col[defaultbg];
   2563 +		} else {
   2564 +			fg = ~(fg & 0xffffff);
   2565  		}
   2566  
   2567 -		/* Fallback on font cache, search the font cache for match. */
   2568 -		for (f = 0; f < frclen; f++) {
   2569 -			glyphidx = XftCharIndex(xw.dpy, frc[f].font, rune);
   2570 -			/* Everything correct. */
   2571 -			if (glyphidx && frc[f].flags == frcflags)
   2572 -				break;
   2573 -			/* We got a default font for a not found glyph. */
   2574 -			if (!glyphidx && frc[f].flags == frcflags
   2575 -					&& frc[f].unicodep == rune) {
   2576 -				break;
   2577 -			}
   2578 +		if (bg == dc.col[defaultbg]) {
   2579 +			bg = dc.col[defaultfg];
   2580 +		} else {
   2581 +			bg = ~(bg & 0xffffff);
   2582  		}
   2583 +	}
   2584  
   2585 -		/* Nothing was found. Use fontconfig to find matching font. */
   2586 -		if (f >= frclen) {
   2587 -			if (!font->set)
   2588 -				font->set = FcFontSort(0, font->pattern,
   2589 -				                       1, 0, &fcres);
   2590 -			fcsets[0] = font->set;
   2591 +	if (base.mode & ATTR_REVERSE) {
   2592 +		temp = fg;
   2593 +		fg = bg;
   2594 +		bg = temp;
   2595 +	}
   2596  
   2597 -			/*
   2598 -			 * Nothing was found in the cache. Now use
   2599 -			 * some dozen of Fontconfig calls to get the
   2600 -			 * font for one single character.
   2601 -			 *
   2602 -			 * Xft and fontconfig are design failures.
   2603 -			 */
   2604 -			fcpattern = FcPatternDuplicate(font->pattern);
   2605 -			fccharset = FcCharSetCreate();
   2606 +	if (base.mode & ATTR_FAINT && !(base.mode & ATTR_BOLD)) {
   2607 +		fg = (fg & (0xff << 24))
   2608 +			| ((((fg >> 16) & 0xff) / 2) << 16)
   2609 +			| ((((fg >> 8) & 0xff) / 2) << 8)
   2610 +			| ((fg & 0xff) / 2);
   2611 +	}
   2612  
   2613 -			FcCharSetAddChar(fccharset, rune);
   2614 -			FcPatternAddCharSet(fcpattern, FC_CHARSET,
   2615 -					fccharset);
   2616 -			FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
   2617 +	if (base.mode & ATTR_BLINK && term.mode & MODE_BLINK)
   2618 +		fg = bg;
   2619 +
   2620 +	if (base.mode & ATTR_INVISIBLE)
   2621 +		fg = bg;
   2622 +
   2623 +	/* Intelligent cleaning up of the borders. */
   2624 +	if (x == 0) {
   2625 +		wlclear(0, (y == 0)? 0 : winy, borderpx,
   2626 +			((y >= term.row-1)? wl.h : (winy + wl.ch)));
   2627 +	}
   2628 +	if (x + charlen >= term.col) {
   2629 +		wlclear(winx + width, (y == 0)? 0 : winy, wl.w,
   2630 +			((y >= term.row-1)? wl.h : (winy + wl.ch)));
   2631 +	}
   2632 +	if (y == 0)
   2633 +		wlclear(winx, 0, winx + width, borderpx);
   2634 +	if (y == term.row-1)
   2635 +		wlclear(winx, winy + wl.ch, winx + width, wl.h);
   2636 +
   2637 +	/* Clean up the region we want to draw to. */
   2638 +	wld_fill_rectangle(wld.renderer, bg, winx, winy, width, wl.ch);
   2639 +
   2640 +	for (xp = winx; bytelen > 0;) {
   2641 +		/*
   2642 +		 * Search for the range in the to be printed string of glyphs
   2643 +		 * that are in the main font. Then print that range. If
   2644 +		 * some glyph is found that is not in the font, do the
   2645 +		 * fallback dance.
   2646 +		 */
   2647 +		u8fs = s;
   2648 +		u8fblen = 0;
   2649 +		u8fl = 0;
   2650 +		oneatatime = font->width != wl.cw;
   2651 +		for (;;) {
   2652 +			u8c = s;
   2653 +			u8cblen = utf8decode(s, &unicodep, UTF_SIZ);
   2654 +			s += u8cblen;
   2655 +			bytelen -= u8cblen;
   2656 +
   2657 +			doesexist = wld_font_ensure_char(font->match, unicodep);
   2658 +			if (doesexist) {
   2659 +					u8fl++;
   2660 +					u8fblen += u8cblen;
   2661 +					if (!oneatatime && bytelen > 0)
   2662 +							continue;
   2663 +			}
   2664 +
   2665 +			if (u8fl > 0) {
   2666 +				wld_draw_text(wld.renderer,
   2667 +						font->match, fg, xp,
   2668 +						winy + font->ascent,
   2669 +						u8fs, u8fblen, NULL);
   2670 +				xp += wl.cw * u8fl;
   2671 +			}
   2672 +			break;
   2673 +		}
   2674 +		if (doesexist) {
   2675 +			if (oneatatime)
   2676 +				continue;
   2677 +			break;
   2678 +		}
   2679 +
   2680 +		/* Search the font cache. */
   2681 +		for (i = 0; i < frclen; i++) {
   2682 +			charexists = wld_font_ensure_char(frc[i].font, unicodep);
   2683 +			/* Everything correct. */
   2684 +			if (charexists && frc[i].flags == frcflags)
   2685 +				break;
   2686 +			/* We got a default font for a not found glyph. */
   2687 +			if (!charexists && frc[i].flags == frcflags \
   2688 +					&& frc[i].unicodep == unicodep) {
   2689 +				break;
   2690 +			}
   2691 +		}
   2692 +
   2693 +		/* Nothing was found. */
   2694 +		if (i >= frclen) {
   2695 +			if (!font->set)
   2696 +				font->set = FcFontSort(0, font->pattern,
   2697 +				                       1, 0, &fcres);
   2698 +			fcsets[0] = font->set;
   2699 +
   2700 +			/*
   2701 +			 * Nothing was found in the cache. Now use
   2702 +			 * some dozen of Fontconfig calls to get the
   2703 +			 * font for one single character.
   2704 +			 *
   2705 +			 * Xft and fontconfig are design failures.
   2706 +			 */
   2707 +			fcpattern = FcPatternDuplicate(font->pattern);
   2708 +			fccharset = FcCharSetCreate();
   2709 +
   2710 +			FcCharSetAddChar(fccharset, unicodep);
   2711 +			FcPatternAddCharSet(fcpattern, FC_CHARSET,
   2712 +					fccharset);
   2713 +			FcPatternAddBool(fcpattern, FC_SCALABLE, 1);
   2714  
   2715  			FcConfigSubstitute(0, fcpattern,
   2716  					FcMatchPattern);
   2717 @@ -3783,186 +3632,58 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x
   2718  			 */
   2719  			if (frclen >= LEN(frc)) {
   2720  				frclen = LEN(frc) - 1;
   2721 -				XftFontClose(xw.dpy, frc[frclen].font);
   2722 +				wld_font_close(frc[frclen].font);
   2723  				frc[frclen].unicodep = 0;
   2724  			}
   2725  
   2726 -			frc[frclen].font = XftFontOpenPattern(xw.dpy,
   2727 +			frc[frclen].font = wld_font_open_pattern(wld.fontctx,
   2728  					fontpattern);
   2729  			frc[frclen].flags = frcflags;
   2730 -			frc[frclen].unicodep = rune;
   2731 -
   2732 -			glyphidx = XftCharIndex(xw.dpy, frc[frclen].font, rune);
   2733 +			frc[frclen].unicodep = unicodep;
   2734  
   2735 -			f = frclen;
   2736 +			i = frclen;
   2737  			frclen++;
   2738  
   2739  			FcPatternDestroy(fcpattern);
   2740  			FcCharSetDestroy(fccharset);
   2741  		}
   2742  
   2743 -		specs[numspecs].font = frc[f].font;
   2744 -		specs[numspecs].glyph = glyphidx;
   2745 -		specs[numspecs].x = (short)xp;
   2746 -		specs[numspecs].y = (short)yp;
   2747 -		xp += runewidth;
   2748 -		numspecs++;
   2749 -	}
   2750 -
   2751 -	return numspecs;
   2752 -}
   2753 -
   2754 -void
   2755 -xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, int y)
   2756 -{
   2757 -	int charlen = len * ((base.mode & ATTR_WIDE) ? 2 : 1);
   2758 -	int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch,
   2759 -	    width = charlen * xw.cw;
   2760 -	Color *fg, *bg, *temp, revfg, revbg, truefg, truebg;
   2761 -	XRenderColor colfg, colbg;
   2762 -	XRectangle r;
   2763 -
   2764 -	/* Fallback on color display for attributes not supported by the font */
   2765 -	if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) {
   2766 -		if (dc.ibfont.badslant || dc.ibfont.badweight)
   2767 -			base.fg = defaultattr;
   2768 -	} else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) ||
   2769 -	    (base.mode & ATTR_BOLD && dc.bfont.badweight)) {
   2770 -		base.fg = defaultattr;
   2771 -	}
   2772 -
   2773 -	if (IS_TRUECOL(base.fg)) {
   2774 -		colfg.alpha = 0xffff;
   2775 -		colfg.red = TRUERED(base.fg);
   2776 -		colfg.green = TRUEGREEN(base.fg);
   2777 -		colfg.blue = TRUEBLUE(base.fg);
   2778 -		XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &truefg);
   2779 -		fg = &truefg;
   2780 -	} else {
   2781 -		fg = &dc.col[base.fg];
   2782 -	}
   2783 -
   2784 -	if (IS_TRUECOL(base.bg)) {
   2785 -		colbg.alpha = 0xffff;
   2786 -		colbg.green = TRUEGREEN(base.bg);
   2787 -		colbg.red = TRUERED(base.bg);
   2788 -		colbg.blue = TRUEBLUE(base.bg);
   2789 -		XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg, &truebg);
   2790 -		bg = &truebg;
   2791 -	} else {
   2792 -		bg = &dc.col[base.bg];
   2793 -	}
   2794 -
   2795 -	/* Change basic system colors [0-7] to bright system colors [8-15] */
   2796 -	if ((base.mode & ATTR_BOLD_FAINT) == ATTR_BOLD && BETWEEN(base.fg, 0, 7))
   2797 -		fg = &dc.col[base.fg + 8];
   2798 -
   2799 -	if (IS_SET(MODE_REVERSE)) {
   2800 -		if (fg == &dc.col[defaultfg]) {
   2801 -			fg = &dc.col[defaultbg];
   2802 -		} else {
   2803 -			colfg.red = ~fg->color.red;
   2804 -			colfg.green = ~fg->color.green;
   2805 -			colfg.blue = ~fg->color.blue;
   2806 -			colfg.alpha = fg->color.alpha;
   2807 -			XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg,
   2808 -					&revfg);
   2809 -			fg = &revfg;
   2810 -		}
   2811 -
   2812 -		if (bg == &dc.col[defaultbg]) {
   2813 -			bg = &dc.col[defaultfg];
   2814 -		} else {
   2815 -			colbg.red = ~bg->color.red;
   2816 -			colbg.green = ~bg->color.green;
   2817 -			colbg.blue = ~bg->color.blue;
   2818 -			colbg.alpha = bg->color.alpha;
   2819 -			XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colbg,
   2820 -					&revbg);
   2821 -			bg = &revbg;
   2822 -		}
   2823 -	}
   2824 -
   2825 -	if (base.mode & ATTR_REVERSE) {
   2826 -		temp = fg;
   2827 -		fg = bg;
   2828 -		bg = temp;
   2829 -	}
   2830 -
   2831 -	if ((base.mode & ATTR_BOLD_FAINT) == ATTR_FAINT) {
   2832 -		colfg.red = fg->color.red / 2;
   2833 -		colfg.green = fg->color.green / 2;
   2834 -		colfg.blue = fg->color.blue / 2;
   2835 -		XftColorAllocValue(xw.dpy, xw.vis, xw.cmap, &colfg, &revfg);
   2836 -		fg = &revfg;
   2837 -	}
   2838 -
   2839 -	if (base.mode & ATTR_BLINK && term.mode & MODE_BLINK)
   2840 -		fg = bg;
   2841 -
   2842 -	if (base.mode & ATTR_INVISIBLE)
   2843 -		fg = bg;
   2844 +		wld_draw_text(wld.renderer, frc[i].font, fg,
   2845 +				xp, winy + frc[i].font->ascent,
   2846 +				u8c, u8cblen, NULL);
   2847  
   2848 -	/* Intelligent cleaning up of the borders. */
   2849 -	if (x == 0) {
   2850 -		xclear(0, (y == 0)? 0 : winy, borderpx,
   2851 -			winy + xw.ch + ((y >= term.row-1)? xw.h : 0));
   2852 -	}
   2853 -	if (x + charlen >= term.col) {
   2854 -		xclear(winx + width, (y == 0)? 0 : winy, xw.w,
   2855 -			((y >= term.row-1)? xw.h : (winy + xw.ch)));
   2856 +		xp += wl.cw * wcwidth(unicodep);
   2857  	}
   2858 -	if (y == 0)
   2859 -		xclear(winx, 0, winx + width, borderpx);
   2860 -	if (y == term.row-1)
   2861 -		xclear(winx, winy + xw.ch, winx + width, xw.h);
   2862  
   2863 -	/* Clean up the region we want to draw to. */
   2864 -	XftDrawRect(xw.draw, bg, winx, winy, width, xw.ch);
   2865 -
   2866 -	/* Set the clip region because Xft is sometimes dirty. */
   2867 -	r.x = 0;
   2868 -	r.y = 0;
   2869 -	r.height = xw.ch;
   2870 -	r.width = width;
   2871 -	XftDrawSetClipRectangles(xw.draw, winx, winy, &r, 1);
   2872 -
   2873 -	/* Render the glyphs. */
   2874 -	XftDrawGlyphFontSpec(xw.draw, fg, specs, len);
   2875 -
   2876 -	/* Render underline and strikethrough. */
   2877  	if (base.mode & ATTR_UNDERLINE) {
   2878 -		XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent + 1,
   2879 +		wld_fill_rectangle(wld.renderer, fg, winx, winy + font->ascent + 1,
   2880  				width, 1);
   2881  	}
   2882  
   2883  	if (base.mode & ATTR_STRUCK) {
   2884 -		XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent / 3,
   2885 +		wld_fill_rectangle(wld.renderer, fg, winx, winy + 2 * font->ascent / 3,
   2886  				width, 1);
   2887  	}
   2888 -
   2889 -	/* Reset clip to none. */
   2890 -	XftDrawSetClip(xw.draw, 0);
   2891  }
   2892  
   2893  void
   2894 -xdrawglyph(Glyph g, int x, int y)
   2895 +wldrawglyph(Glyph g, int x, int y)
   2896  {
   2897 -	int numspecs;
   2898 -	XftGlyphFontSpec spec;
   2899 +	static char buf[UTF_SIZ];
   2900 +	size_t len = utf8encode(g.u, buf);
   2901 +	int width = g.mode & ATTR_WIDE ? 2 : 1;
   2902  
   2903 -	numspecs = xmakeglyphfontspecs(&spec, &g, 1, x, y);
   2904 -	xdrawglyphfontspecs(&spec, g, numspecs, x, y);
   2905 +	wldraws(buf, g, x, y, width, len);
   2906  }
   2907  
   2908  void
   2909 -xdrawcursor(void)
   2910 +wldrawcursor(void)
   2911  {
   2912  	static int oldx = 0, oldy = 0;
   2913  	int curx;
   2914  	Glyph g = {' ', ATTR_NULL, defaultbg, defaultcs}, og;
   2915  	int ena_sel = sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN);
   2916 -	Color drawcol;
   2917 +	uint32_t drawcol;
   2918  
   2919  	LIMIT(oldx, 0, term.col-1);
   2920  	LIMIT(oldy, 0, term.row-1);
   2921 @@ -3979,7 +3700,11 @@ xdrawcursor(void)
   2922  	og = term.line[oldy][oldx];
   2923  	if (ena_sel && selected(oldx, oldy))
   2924  		og.mode ^= ATTR_REVERSE;
   2925 -	xdrawglyph(og, oldx, oldy);
   2926 +	wldrawglyph(og, oldx, oldy);
   2927 +	if (oldx != curx || oldy != term.c.y) {
   2928 +		wl_surface_damage(wl.surface, borderpx + oldx * wl.cw,
   2929 +				borderpx + oldy * wl.ch, wl.cw, wl.ch);
   2930 +	}
   2931  
   2932  	g.u = term.line[term.c.y][term.c.x].u;
   2933  
   2934 @@ -4010,198 +3735,152 @@ xdrawcursor(void)
   2935  		return;
   2936  
   2937  	/* draw the new one */
   2938 -	if (xw.state & WIN_FOCUSED) {
   2939 -		switch (xw.cursor) {
   2940 +	if (wl.state & WIN_FOCUSED) {
   2941 +		switch (wl.cursor) {
   2942  		case 7: /* st extension: snowman */
   2943  			utf8decode("☃", &g.u, UTF_SIZ);
   2944  		case 0: /* Blinking Block */
   2945  		case 1: /* Blinking Block (Default) */
   2946  		case 2: /* Steady Block */
   2947  			g.mode |= term.line[term.c.y][curx].mode & ATTR_WIDE;
   2948 -			xdrawglyph(g, term.c.x, term.c.y);
   2949 +			wldrawglyph(g, term.c.x, term.c.y);
   2950  			break;
   2951  		case 3: /* Blinking Underline */
   2952  		case 4: /* Steady Underline */
   2953 -			XftDrawRect(xw.draw, &drawcol,
   2954 -					borderpx + curx * xw.cw,
   2955 -					borderpx + (term.c.y + 1) * xw.ch - \
   2956 +			wld_fill_rectangle(wld.renderer, drawcol,
   2957 +					borderpx + curx * wl.cw,
   2958 +					borderpx + (term.c.y + 1) * wl.ch - \
   2959  						cursorthickness,
   2960 -					xw.cw, cursorthickness);
   2961 +					wl.cw, cursorthickness);
   2962  			break;
   2963  		case 5: /* Blinking bar */
   2964  		case 6: /* Steady bar */
   2965 -			XftDrawRect(xw.draw, &drawcol,
   2966 -					borderpx + curx * xw.cw,
   2967 -					borderpx + term.c.y * xw.ch,
   2968 -					cursorthickness, xw.ch);
   2969 +			wld_fill_rectangle(wld.renderer, drawcol,
   2970 +					borderpx + curx * wl.cw,
   2971 +					borderpx + term.c.y * wl.ch,
   2972 +					cursorthickness, wl.ch);
   2973  			break;
   2974  		}
   2975  	} else {
   2976 -		XftDrawRect(xw.draw, &drawcol,
   2977 -				borderpx + curx * xw.cw,
   2978 -				borderpx + term.c.y * xw.ch,
   2979 -				xw.cw - 1, 1);
   2980 -		XftDrawRect(xw.draw, &drawcol,
   2981 -				borderpx + curx * xw.cw,
   2982 -				borderpx + term.c.y * xw.ch,
   2983 -				1, xw.ch - 1);
   2984 -		XftDrawRect(xw.draw, &drawcol,
   2985 -				borderpx + (curx + 1) * xw.cw - 1,
   2986 -				borderpx + term.c.y * xw.ch,
   2987 -				1, xw.ch - 1);
   2988 -		XftDrawRect(xw.draw, &drawcol,
   2989 -				borderpx + curx * xw.cw,
   2990 -				borderpx + (term.c.y + 1) * xw.ch - 1,
   2991 -				xw.cw, 1);
   2992 +		wld_fill_rectangle(wld.renderer, drawcol,
   2993 +				borderpx + curx * wl.cw,
   2994 +				borderpx + term.c.y * wl.ch,
   2995 +				wl.cw - 1, 1);
   2996 +		wld_fill_rectangle(wld.renderer, drawcol,
   2997 +				borderpx + curx * wl.cw,
   2998 +				borderpx + term.c.y * wl.ch,
   2999 +				1, wl.ch - 1);
   3000 +		wld_fill_rectangle(wld.renderer, drawcol,
   3001 +				borderpx + (curx + 1) * wl.cw - 1,
   3002 +				borderpx + term.c.y * wl.ch,
   3003 +				1, wl.ch - 1);
   3004 +		wld_fill_rectangle(wld.renderer, drawcol,
   3005 +				borderpx + curx * wl.cw,
   3006 +				borderpx + (term.c.y + 1) * wl.ch - 1,
   3007 +				wl.cw, 1);
   3008  	}
   3009 +	wl_surface_damage(wl.surface, borderpx + curx * wl.cw,
   3010 +			borderpx + term.c.y * wl.ch, wl.cw, wl.ch);
   3011  	oldx = curx, oldy = term.c.y;
   3012  }
   3013  
   3014 -
   3015  void
   3016 -xsettitle(char *p)
   3017 +wlsettitle(char *title)
   3018  {
   3019 -	XTextProperty prop;
   3020 -
   3021 -	Xutf8TextListToTextProperty(xw.dpy, &p, 1, XUTF8StringStyle,
   3022 -			&prop);
   3023 -	XSetWMName(xw.dpy, xw.win, &prop);
   3024 -	XSetTextProperty(xw.dpy, xw.win, &prop, xw.netwmname);
   3025 -	XFree(prop.value);
   3026 +	xdg_toplevel_set_title(wl.toplevel, title);
   3027  }
   3028  
   3029  void
   3030 -xresettitle(void)
   3031 +wlresettitle(void)
   3032  {
   3033 -	xsettitle(opt_title ? opt_title : "st");
   3034 +	wlsettitle(opt_title ? opt_title : "st");
   3035  }
   3036  
   3037  void
   3038  redraw(void)
   3039  {
   3040  	tfulldirt();
   3041 -	draw();
   3042  }
   3043  
   3044  void
   3045  draw(void)
   3046  {
   3047 +	int y, y0;
   3048 +
   3049 +	for (y = 0; y <= term.bot; ++y) {
   3050 +		if (!term.dirty[y])
   3051 +			continue;
   3052 +		for (y0 = y; y <= term.bot && term.dirty[y]; ++y);
   3053 +		wl_surface_damage(wl.surface, 0, borderpx + y0 * wl.ch,
   3054 +				wl.w, (y - y0) * wl.ch);
   3055 +	}
   3056 +
   3057 +	wld_set_target_buffer(wld.renderer, wld.buffer);
   3058  	drawregion(0, 0, term.col, term.row);
   3059 -	XCopyArea(xw.dpy, xw.buf, xw.win, dc.gc, 0, 0, xw.w,
   3060 -			xw.h, 0, 0);
   3061 -	XSetForeground(xw.dpy, dc.gc,
   3062 -			dc.col[IS_SET(MODE_REVERSE)?
   3063 -				defaultfg : defaultbg].pixel);
   3064 +	wl.framecb = wl_surface_frame(wl.surface);
   3065 +	wl_callback_add_listener(wl.framecb, &framelistener, NULL);
   3066 +	wld_flush(wld.renderer);
   3067 +	wl_surface_attach(wl.surface, wl.buffer, 0, 0);
   3068 +	wl_surface_commit(wl.surface);
   3069 +	/* need to wait to destroy the old buffer until we commit the new
   3070 +	 * buffer */
   3071 +	if (wld.oldbuffer) {
   3072 +		wld_buffer_unreference(wld.oldbuffer);
   3073 +		wld.oldbuffer = 0;
   3074 +	}
   3075 +	needdraw = false;
   3076  }
   3077  
   3078  void
   3079  drawregion(int x1, int y1, int x2, int y2)
   3080  {
   3081 -	int i, x, y, ox, numspecs;
   3082 +	int ic, ib, x, y, ox;
   3083  	Glyph base, new;
   3084 -	XftGlyphFontSpec *specs;
   3085 +	char buf[DRAW_BUF_SIZ];
   3086  	int ena_sel = sel.ob.x != -1 && sel.alt == IS_SET(MODE_ALTSCREEN);
   3087  
   3088 -	if (!(xw.state & WIN_VISIBLE))
   3089 -		return;
   3090 -
   3091  	for (y = y1; y < y2; y++) {
   3092  		if (!term.dirty[y])
   3093  			continue;
   3094  
   3095  		term.dirty[y] = 0;
   3096 -
   3097 -		specs = term.specbuf;
   3098 -		numspecs = xmakeglyphfontspecs(specs, &term.line[y][x1], x2 - x1, x1, y);
   3099 -
   3100 -		i = ox = 0;
   3101 -		for (x = x1; x < x2 && i < numspecs; x++) {
   3102 +		base = term.line[y][0];
   3103 +		ic = ib = ox = 0;
   3104 +		for (x = x1; x < x2; x++) {
   3105  			new = term.line[y][x];
   3106  			if (new.mode == ATTR_WDUMMY)
   3107  				continue;
   3108  			if (ena_sel && selected(x, y))
   3109  				new.mode ^= ATTR_REVERSE;
   3110 -			if (i > 0 && ATTRCMP(base, new)) {
   3111 -				xdrawglyphfontspecs(specs, base, i, ox, y);
   3112 -				specs += i;
   3113 -				numspecs -= i;
   3114 -				i = 0;
   3115 +			if (ib > 0 && (ATTRCMP(base, new)
   3116 +					|| ib >= DRAW_BUF_SIZ-UTF_SIZ)) {
   3117 +				wldraws(buf, base, ox, y, ic, ib);
   3118 +				ic = ib = 0;
   3119  			}
   3120 -			if (i == 0) {
   3121 +			if (ib == 0) {
   3122  				ox = x;
   3123  				base = new;
   3124  			}
   3125 -			i++;
   3126 +
   3127 +			ib += utf8encode(new.u, buf+ib);
   3128 +			ic += (new.mode & ATTR_WIDE)? 2 : 1;
   3129  		}
   3130 -		if (i > 0)
   3131 -			xdrawglyphfontspecs(specs, base, i, ox, y);
   3132 +		if (ib > 0)
   3133 +			wldraws(buf, base, ox, y, ic, ib);
   3134  	}
   3135 -	xdrawcursor();
   3136 -}
   3137 -
   3138 -void
   3139 -expose(XEvent *ev)
   3140 -{
   3141 -	redraw();
   3142 -}
   3143 -
   3144 -void
   3145 -visibility(XEvent *ev)
   3146 -{
   3147 -	XVisibilityEvent *e = &ev->xvisibility;
   3148 -
   3149 -	MODBIT(xw.state, e->state != VisibilityFullyObscured, WIN_VISIBLE);
   3150 -}
   3151 -
   3152 -void
   3153 -unmap(XEvent *ev)
   3154 -{
   3155 -	xw.state &= ~WIN_VISIBLE;
   3156 -}
   3157 -
   3158 -void
   3159 -xsetpointermotion(int set)
   3160 -{
   3161 -	MODBIT(xw.attrs.event_mask, set, PointerMotionMask);
   3162 -	XChangeWindowAttributes(xw.dpy, xw.win, CWEventMask, &xw.attrs);
   3163 +	wldrawcursor();
   3164  }
   3165  
   3166  void
   3167 -xseturgency(int add)
   3168 +wlseturgency(int add)
   3169  {
   3170 -	XWMHints *h = XGetWMHints(xw.dpy, xw.win);
   3171 -
   3172 -	MODBIT(h->flags, add, XUrgencyHint);
   3173 -	XSetWMHints(xw.dpy, xw.win, h);
   3174 -	XFree(h);
   3175 -}
   3176 -
   3177 -void
   3178 -focus(XEvent *ev)
   3179 -{
   3180 -	XFocusChangeEvent *e = &ev->xfocus;
   3181 -
   3182 -	if (e->mode == NotifyGrab)
   3183 -		return;
   3184 -
   3185 -	if (ev->type == FocusIn) {
   3186 -		XSetICFocus(xw.xic);
   3187 -		xw.state |= WIN_FOCUSED;
   3188 -		xseturgency(0);
   3189 -		if (IS_SET(MODE_FOCUS))
   3190 -			ttywrite("\033[I", 3);
   3191 -	} else {
   3192 -		XUnsetICFocus(xw.xic);
   3193 -		xw.state &= ~WIN_FOCUSED;
   3194 -		if (IS_SET(MODE_FOCUS))
   3195 -			ttywrite("\033[O", 3);
   3196 -	}
   3197 +	/* XXX: no urgency equivalent yet in wayland */
   3198  }
   3199  
   3200  int
   3201  match(uint mask, uint state)
   3202  {
   3203 -	return mask == XK_ANY_MOD || mask == (state & ~ignoremod);
   3204 +	return mask == MOD_MASK_ANY || mask == (state & ~(ignoremod));
   3205  }
   3206  
   3207  void
   3208 @@ -4211,7 +3890,7 @@ numlock(const Arg *dummy)
   3209  }
   3210  
   3211  char*
   3212 -kmap(KeySym k, uint state)
   3213 +kmap(xkb_keysym_t k, uint state)
   3214  {
   3215  	Key *kp;
   3216  	int i;
   3217 @@ -4251,38 +3930,176 @@ kmap(KeySym k, uint state)
   3218  }
   3219  
   3220  void
   3221 -kpress(XEvent *ev)
   3222 +cresize(int width, int height)
   3223 +{
   3224 +	int col, row;
   3225 +
   3226 +	if (width != 0)
   3227 +		wl.w = width;
   3228 +	if (height != 0)
   3229 +		wl.h = height;
   3230 +
   3231 +	col = (wl.w - 2 * borderpx) / wl.cw;
   3232 +	row = (wl.h - 2 * borderpx) / wl.ch;
   3233 +
   3234 +	tresize(col, row);
   3235 +	wlresize(col, row);
   3236 +}
   3237 +
   3238 +void
   3239 +regglobal(void *data, struct wl_registry *registry, uint32_t name,
   3240 +          const char *interface, uint32_t version)
   3241 +{
   3242 +	if (strcmp(interface, "wl_compositor") == 0) {
   3243 +		wl.cmp = wl_registry_bind(registry, name,
   3244 +				&wl_compositor_interface, 3);
   3245 +	} else if (strcmp(interface, "xdg_wm_base") == 0) {
   3246 +		wl.wm = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
   3247 +		xdg_wm_base_add_listener(wl.wm, &wmlistener, NULL);
   3248 +	} else if (strcmp(interface, "wl_shm") == 0) {
   3249 +		wl.shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
   3250 +	} else if (strcmp(interface, "wl_seat") == 0) {
   3251 +		wl.seat = wl_registry_bind(registry, name,
   3252 +				&wl_seat_interface, 4);
   3253 +	} else if (strcmp(interface, "wl_data_device_manager") == 0) {
   3254 +		wl.datadevmanager = wl_registry_bind(registry, name,
   3255 +				&wl_data_device_manager_interface, 1);
   3256 +	} else if (strcmp(interface, "wl_output") == 0) {
   3257 +		/* bind to outputs so we can get surface enter events */
   3258 +		wl_registry_bind(registry, name, &wl_output_interface, 2);
   3259 +	}
   3260 +}
   3261 +
   3262 +void
   3263 +regglobalremove(void *data, struct wl_registry *registry, uint32_t name)
   3264 +{
   3265 +}
   3266 +
   3267 +void
   3268 +surfenter(void *data, struct wl_surface *surface, struct wl_output *output)
   3269 +{
   3270 +	wl.vis++;
   3271 +	if (!(wl.state & WIN_VISIBLE))
   3272 +		wl.state |= WIN_VISIBLE;
   3273 +}
   3274 +
   3275 +void
   3276 +surfleave(void *data, struct wl_surface *surface, struct wl_output *output)
   3277 +{
   3278 +	if (--wl.vis == 0)
   3279 +		wl.state &= ~WIN_VISIBLE;
   3280 +}
   3281 +
   3282 +void
   3283 +framedone(void *data, struct wl_callback *callback, uint32_t msecs)
   3284 +{
   3285 +	wl_callback_destroy(callback);
   3286 +	wl.framecb = NULL;
   3287 +	if (needdraw && wl.state & WIN_VISIBLE) {
   3288 +		draw();
   3289 +	}
   3290 +}
   3291 +
   3292 +void
   3293 +kbdkeymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd,
   3294 +          uint32_t size)
   3295  {
   3296 -	XKeyEvent *e = &ev->xkey;
   3297 -	KeySym ksym;
   3298 -	char buf[32], *customkey;
   3299 +	char *string;
   3300 +
   3301 +	if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
   3302 +		close(fd);
   3303 +		return;
   3304 +	}
   3305 +
   3306 +	string = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
   3307 +
   3308 +	if (string == MAP_FAILED) {
   3309 +		close(fd);
   3310 +		return;
   3311 +	}
   3312 +
   3313 +	wl.xkb.keymap = xkb_keymap_new_from_string(wl.xkb.ctx, string,
   3314 +			XKB_KEYMAP_FORMAT_TEXT_V1, 0);
   3315 +	munmap(string, size);
   3316 +	close(fd);
   3317 +	wl.xkb.state = xkb_state_new(wl.xkb.keymap);
   3318 +
   3319 +	wl.xkb.ctrl = xkb_keymap_mod_get_index(wl.xkb.keymap, XKB_MOD_NAME_CTRL);
   3320 +	wl.xkb.alt = xkb_keymap_mod_get_index(wl.xkb.keymap, XKB_MOD_NAME_ALT);
   3321 +	wl.xkb.shift = xkb_keymap_mod_get_index(wl.xkb.keymap, XKB_MOD_NAME_SHIFT);
   3322 +	wl.xkb.logo = xkb_keymap_mod_get_index(wl.xkb.keymap, XKB_MOD_NAME_LOGO);
   3323 +
   3324 +	wl.xkb.mods = 0;
   3325 +}
   3326 +
   3327 +void
   3328 +kbdenter(void *data, struct wl_keyboard *keyboard, uint32_t serial,
   3329 +         struct wl_surface *surface, struct wl_array *keys)
   3330 +{
   3331 +	wl.state |= WIN_FOCUSED;
   3332 +	if (IS_SET(MODE_FOCUS))
   3333 +		ttywrite("\033[I", 3);
   3334 +	/* need to redraw the cursor */
   3335 +	needdraw = true;
   3336 +}
   3337 +
   3338 +void
   3339 +kbdleave(void *data, struct wl_keyboard *keyboard, uint32_t serial,
   3340 +	 struct wl_surface *surface)
   3341 +{
   3342 +	/* selection offers are invalidated when we lose keyboard focus */
   3343 +	wl.seloffer = NULL;
   3344 +	wl.state &= ~WIN_FOCUSED;
   3345 +	if (IS_SET(MODE_FOCUS))
   3346 +		ttywrite("\033[O", 3);
   3347 +	/* need to redraw the cursor */
   3348 +	needdraw = true;
   3349 +	/* disable key repeat */
   3350 +	repeat.len = 0;
   3351 +}
   3352 +
   3353 +void
   3354 +kbdkey(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time,
   3355 +       uint32_t key, uint32_t state)
   3356 +{
   3357 +	xkb_keysym_t ksym;
   3358 +	char buf[32], *str;
   3359  	int len;
   3360  	Rune c;
   3361 -	Status status;
   3362  	Shortcut *bp;
   3363  
   3364  	if (IS_SET(MODE_KBDLOCK))
   3365  		return;
   3366  
   3367 -	len = XmbLookupString(xw.xic, e, buf, sizeof buf, &ksym, &status);
   3368 +	if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
   3369 +		if (repeat.key == key)
   3370 +			repeat.len = 0;
   3371 +		return;
   3372 +	}
   3373 +
   3374 +	ksym = xkb_state_key_get_one_sym(wl.xkb.state, key + 8);
   3375 +	len = xkb_keysym_to_utf8(ksym, buf, sizeof buf);
   3376 +	if (len > 0)
   3377 +	    --len;
   3378 +
   3379  	/* 1. shortcuts */
   3380  	for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
   3381 -		if (ksym == bp->keysym && match(bp->mod, e->state)) {
   3382 +		if (ksym == bp->keysym && match(bp->mod, wl.xkb.mods)) {
   3383  			bp->func(&(bp->arg));
   3384  			return;
   3385  		}
   3386  	}
   3387  
   3388  	/* 2. custom keys from config.h */
   3389 -	if ((customkey = kmap(ksym, e->state))) {
   3390 -		ttysend(customkey, strlen(customkey));
   3391 -		return;
   3392 +	if ((str = kmap(ksym, wl.xkb.mods))) {
   3393 +		len = strlen(str);
   3394 +		goto send;
   3395  	}
   3396  
   3397  	/* 3. composed string from input method */
   3398  	if (len == 0)
   3399  		return;
   3400 -	if (len == 1 && e->state & Mod1Mask) {
   3401 +	if (len == 1 && wl.xkb.mods & MOD_MASK_ALT) {
   3402  		if (IS_SET(MODE_8BIT)) {
   3403  			if (*buf < 0177) {
   3404  				c = *buf | 0x80;
   3405 @@ -4294,101 +4111,334 @@ kpress(XEvent *ev)
   3406  			len = 2;
   3407  		}
   3408  	}
   3409 -	ttysend(buf, len);
   3410 +	/* convert character to control character */
   3411 +	else if (len == 1 && wl.xkb.mods & MOD_MASK_CTRL) {
   3412 +		if ((*buf >= '@' && *buf < '\177') || *buf == ' ')
   3413 +			*buf &= 0x1F;
   3414 +		else if (*buf == '2') *buf = '\000';
   3415 +		else if (*buf >= '3' && *buf <= '7')
   3416 +			*buf -= ('3' - '\033');
   3417 +		else if (*buf == '8') *buf = '\177';
   3418 +		else if (*buf == '/') *buf = '_' & 0x1F;
   3419 +	}
   3420 +
   3421 +	str = buf;
   3422 +
   3423 +send:
   3424 +	memcpy(repeat.str, str, len);
   3425 +	repeat.key = key;
   3426 +	repeat.len = len;
   3427 +	repeat.started = false;
   3428 +	clock_gettime(CLOCK_MONOTONIC, &repeat.last);
   3429 +	ttysend(str, len);
   3430  }
   3431  
   3432 +void
   3433 +kbdmodifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial,
   3434 +             uint32_t dep, uint32_t lat, uint32_t lck, uint32_t group)
   3435 +{
   3436 +	xkb_mod_mask_t mod_mask;
   3437 +
   3438 +	xkb_state_update_mask(wl.xkb.state, dep, lat, lck, group, 0, 0);
   3439 +
   3440 +	mod_mask = xkb_state_serialize_mods(wl.xkb.state, XKB_STATE_MODS_EFFECTIVE);
   3441 +	wl.xkb.mods = 0;
   3442 +
   3443 +	if (mod_mask & (1 << wl.xkb.ctrl))
   3444 +		wl.xkb.mods |= MOD_MASK_CTRL;
   3445 +	if (mod_mask & (1 << wl.xkb.alt))
   3446 +		wl.xkb.mods |= MOD_MASK_ALT;
   3447 +	if (mod_mask & (1 << wl.xkb.shift))
   3448 +		wl.xkb.mods |= MOD_MASK_SHIFT;
   3449 +	if (mod_mask & (1 << wl.xkb.logo))
   3450 +		wl.xkb.mods |= MOD_MASK_LOGO;
   3451 +}
   3452  
   3453  void
   3454 -cmessage(XEvent *e)
   3455 +kbdrepeatinfo(void *data, struct wl_keyboard *keyboard, int32_t rate,
   3456 +              int32_t delay)
   3457  {
   3458 -	/*
   3459 -	 * See xembed specs
   3460 -	 *  http://standards.freedesktop.org/xembed-spec/xembed-spec-latest.html
   3461 -	 */
   3462 -	if (e->xclient.message_type == xw.xembed && e->xclient.format == 32) {
   3463 -		if (e->xclient.data.l[1] == XEMBED_FOCUS_IN) {
   3464 -			xw.state |= WIN_FOCUSED;
   3465 -			xseturgency(0);
   3466 -		} else if (e->xclient.data.l[1] == XEMBED_FOCUS_OUT) {
   3467 -			xw.state &= ~WIN_FOCUSED;
   3468 +	keyrepeatdelay = delay;
   3469 +	keyrepeatinterval = 1000 / rate;
   3470 +}
   3471 +
   3472 +void
   3473 +ptrenter(void *data, struct wl_pointer *pointer, uint32_t serial,
   3474 +         struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
   3475 +{
   3476 +	struct wl_cursor_image *img = cursor.cursor->images[0];
   3477 +	struct wl_buffer *buffer;
   3478 +
   3479 +	wl_pointer_set_cursor(pointer, serial, cursor.surface,
   3480 +			img->hotspot_x, img->hotspot_y);
   3481 +	buffer = wl_cursor_image_get_buffer(img);
   3482 +	wl_surface_attach(cursor.surface, buffer, 0, 0);
   3483 +	wl_surface_damage(cursor.surface, 0, 0, img->width, img->height);
   3484 +	wl_surface_commit(cursor.surface);
   3485 +}
   3486 +
   3487 +void
   3488 +ptrleave(void *data, struct wl_pointer *pointer, uint32_t serial,
   3489 +         struct wl_surface *surface)
   3490 +{
   3491 +}
   3492 +
   3493 +void
   3494 +ptrmotion(void *data, struct wl_pointer * pointer, uint32_t serial,
   3495 +          wl_fixed_t x, wl_fixed_t y)
   3496 +{
   3497 +	int oldey, oldex, oldsby, oldsey;
   3498 +
   3499 +	if (IS_SET(MODE_MOUSE)) {
   3500 +		wlmousereportmotion(x, y);
   3501 +		return;
   3502 +	}
   3503 +
   3504 +	wl.px = wl_fixed_to_int(x);
   3505 +	wl.py = wl_fixed_to_int(y);
   3506 +
   3507 +	if (!sel.mode)
   3508 +		return;
   3509 +
   3510 +	sel.mode = SEL_READY;
   3511 +	oldey = sel.oe.y;
   3512 +	oldex = sel.oe.x;
   3513 +	oldsby = sel.nb.y;
   3514 +	oldsey = sel.ne.y;
   3515 +	getbuttoninfo();
   3516 +
   3517 +	if (oldey != sel.oe.y || oldex != sel.oe.x)
   3518 +		tsetdirt(MIN(sel.nb.y, oldsby), MAX(sel.ne.y, oldsey));
   3519 +}
   3520 +
   3521 +void
   3522 +ptrbutton(void * data, struct wl_pointer * pointer, uint32_t serial,
   3523 +          uint32_t time, uint32_t button, uint32_t state)
   3524 +{
   3525 +	MouseShortcut *ms;
   3526 +
   3527 +	if (IS_SET(MODE_MOUSE) && !(wl.xkb.mods & forceselmod)) {
   3528 +		wlmousereportbutton(button, state);
   3529 +		return;
   3530 +	}
   3531 +
   3532 +	switch (state) {
   3533 +	case WL_POINTER_BUTTON_STATE_RELEASED:
   3534 +		if (button == BTN_MIDDLE) {
   3535 +			selpaste(NULL);
   3536 +		} else if (button == BTN_LEFT) {
   3537 +			if (sel.mode == SEL_READY) {
   3538 +				getbuttoninfo();
   3539 +				selcopy(serial);
   3540 +			} else
   3541 +				selclear();
   3542 +			sel.mode = SEL_IDLE;
   3543 +			tsetdirt(sel.nb.y, sel.ne.y);
   3544  		}
   3545 -	} else if (e->xclient.data.l[0] == xw.wmdeletewin) {
   3546 -		/* Send SIGHUP to shell */
   3547 -		kill(pid, SIGHUP);
   3548 -		exit(0);
   3549 +		break;
   3550 +
   3551 +	case WL_POINTER_BUTTON_STATE_PRESSED:
   3552 +		for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) {
   3553 +			if (button == ms->b && match(ms->mask, wl.xkb.mods)) {
   3554 +				ttysend(ms->s, strlen(ms->s));
   3555 +				return;
   3556 +			}
   3557 +		}
   3558 +
   3559 +		if (button == BTN_LEFT) {
   3560 +			/* Clear previous selection, logically and visually. */
   3561 +			selclear();
   3562 +			sel.mode = SEL_EMPTY;
   3563 +			sel.type = SEL_REGULAR;
   3564 +			sel.oe.x = sel.ob.x = x2col(wl.px);
   3565 +			sel.oe.y = sel.ob.y = y2row(wl.py);
   3566 +
   3567 +			/*
   3568 +			 * If the user clicks below predefined timeouts
   3569 +			 * specific snapping behaviour is exposed.
   3570 +			 */
   3571 +			if (time - sel.tclick2 <= tripleclicktimeout) {
   3572 +				sel.snap = SNAP_LINE;
   3573 +			} else if (time - sel.tclick1 <= doubleclicktimeout) {
   3574 +				sel.snap = SNAP_WORD;
   3575 +			} else {
   3576 +				sel.snap = 0;
   3577 +			}
   3578 +			selnormalize();
   3579 +
   3580 +			if (sel.snap != 0)
   3581 +				sel.mode = SEL_READY;
   3582 +			tsetdirt(sel.nb.y, sel.ne.y);
   3583 +			sel.tclick2 = sel.tclick1;
   3584 +			sel.tclick1 = time;
   3585 +		}
   3586 +		break;
   3587  	}
   3588  }
   3589  
   3590  void
   3591 -cresize(int width, int height)
   3592 +ptraxis(void * data, struct wl_pointer * pointer, uint32_t time, uint32_t axis,
   3593 +        wl_fixed_t value)
   3594  {
   3595 -	int col, row;
   3596 +	Axiskey *ak;
   3597 +	int dir = value > 0 ? +1 : -1;
   3598  
   3599 -	if (width != 0)
   3600 -		xw.w = width;
   3601 -	if (height != 0)
   3602 -		xw.h = height;
   3603 +	if (IS_SET(MODE_MOUSE) && !(wl.xkb.mods & forceselmod)) {
   3604 +		wlmousereportaxis(axis, value);
   3605 +		return;
   3606 +	}
   3607  
   3608 -	col = (xw.w - 2 * borderpx) / xw.cw;
   3609 -	row = (xw.h - 2 * borderpx) / xw.ch;
   3610 +	for (ak = ashortcuts; ak < ashortcuts + LEN(ashortcuts); ak++) {
   3611 +		if (axis == ak->axis && dir == ak->dir
   3612 +				&& match(ak->mask, wl.xkb.mods)) {
   3613 +			ttysend(ak->s, strlen(ak->s));
   3614 +			return;
   3615 +		}
   3616 +	}
   3617 +}
   3618  
   3619 -	tresize(col, row);
   3620 -	xresize(col, row);
   3621 +void
   3622 +wmping(void *data, struct xdg_wm_base *wm, uint32_t serial)
   3623 +{
   3624 +	xdg_wm_base_pong(wm, serial);
   3625 +}
   3626 +
   3627 +void
   3628 +xdgsurfconfigure(void *data, struct xdg_surface *surf, uint32_t serial)
   3629 +{
   3630 +	xdg_surface_ack_configure(surf, serial);
   3631  }
   3632  
   3633  void
   3634 -resize(XEvent *e)
   3635 +toplevelconfigure(void *data, struct xdg_toplevel *toplevel, int32_t w, int32_t h,
   3636 +                  struct wl_array *states)
   3637  {
   3638 -	if (e->xconfigure.width == xw.w && e->xconfigure.height == xw.h)
   3639 +	if (w == wl.w && h == wl.h)
   3640  		return;
   3641 +	cresize(w, h);
   3642 +	if (wl.configured)
   3643 +		ttyresize();
   3644 +	else
   3645 +		wl.configured = true;
   3646 +}
   3647  
   3648 -	cresize(e->xconfigure.width, e->xconfigure.height);
   3649 -	ttyresize();
   3650 +void
   3651 +toplevelclose(void *data, struct xdg_toplevel *toplevel)
   3652 +{
   3653 +	/* Send SIGHUP to shell */
   3654 +	kill(pid, SIGHUP);
   3655 +	exit(0);
   3656 +}
   3657 +
   3658 +void
   3659 +datadevoffer(void *data, struct wl_data_device *datadev,
   3660 +             struct wl_data_offer *offer)
   3661 +{
   3662 +	wl_data_offer_add_listener(offer, &dataofferlistener, NULL);
   3663 +}
   3664 +
   3665 +void
   3666 +datadeventer(void *data, struct wl_data_device *datadev, uint32_t serial,
   3667 +		struct wl_surface *surf, wl_fixed_t x, wl_fixed_t y,
   3668 +		struct wl_data_offer *offer)
   3669 +{
   3670 +}
   3671 +
   3672 +void
   3673 +datadevleave(void *data, struct wl_data_device *datadev)
   3674 +{
   3675 +}
   3676 +
   3677 +void
   3678 +datadevmotion(void *data, struct wl_data_device *datadev, uint32_t time,
   3679 +              wl_fixed_t x, wl_fixed_t y)
   3680 +{
   3681 +}
   3682 +
   3683 +void
   3684 +datadevdrop(void *data, struct wl_data_device *datadev)
   3685 +{
   3686 +}
   3687 +
   3688 +void
   3689 +datadevselection(void *data, struct wl_data_device *datadev,
   3690 +                 struct wl_data_offer *offer)
   3691 +{
   3692 +	if (offer && (uintptr_t) wl_data_offer_get_user_data(offer) == 1)
   3693 +		wl.seloffer = offer;
   3694 +	else
   3695 +		wl.seloffer = NULL;
   3696 +}
   3697 +
   3698 +void
   3699 +dataofferoffer(void *data, struct wl_data_offer *offer, const char *mimetype)
   3700 +{
   3701 +	/* mark the offer as usable if it supports plain text */
   3702 +	if (strncmp(mimetype, "text/plain", 10) == 0)
   3703 +		wl_data_offer_set_user_data(offer, (void *)(uintptr_t) 1);
   3704 +}
   3705 +
   3706 +void
   3707 +datasrctarget(void *data, struct wl_data_source *source, const char *mimetype)
   3708 +{
   3709 +}
   3710 +
   3711 +void
   3712 +datasrcsend(void *data, struct wl_data_source *source, const char *mimetype,
   3713 +            int32_t fd)
   3714 +{
   3715 +	char *buf = sel.primary;
   3716 +	int len = strlen(sel.primary);
   3717 +	ssize_t ret;
   3718 +	while ((ret = write(fd, buf, MIN(len, BUFSIZ))) > 0) {
   3719 +		len -= ret;
   3720 +		buf += ret;
   3721 +	}
   3722 +	close(fd);
   3723 +}
   3724 +
   3725 +void
   3726 +datasrccancelled(void *data, struct wl_data_source *source)
   3727 +{
   3728 +	if (sel.source == source) {
   3729 +		sel.source = NULL;
   3730 +		selclear();
   3731 +	}
   3732 +	wl_data_source_destroy(source);
   3733  }
   3734  
   3735  void
   3736  run(void)
   3737  {
   3738 -	XEvent ev;
   3739 -	int w = xw.w, h = xw.h;
   3740  	fd_set rfd;
   3741 -	int xfd = XConnectionNumber(xw.dpy), xev, blinkset = 0, dodraw = 0;
   3742 +	int wlfd = wl_display_get_fd(wl.dpy), blinkset = 0;
   3743  	struct timespec drawtimeout, *tv = NULL, now, last, lastblink;
   3744 -	long deltatime;
   3745 +	ulong msecs;
   3746  
   3747 -	/* Waiting for window mapping */
   3748 -	do {
   3749 -		XNextEvent(xw.dpy, &ev);
   3750 -		/*
   3751 -		 * This XFilterEvent call is required because of XOpenIM. It
   3752 -		 * does filter out the key event and some client message for
   3753 -		 * the input method too.
   3754 -		 */
   3755 -		if (XFilterEvent(&ev, None))
   3756 -			continue;
   3757 -		if (ev.type == ConfigureNotify) {
   3758 -			w = ev.xconfigure.width;
   3759 -			h = ev.xconfigure.height;
   3760 -		}
   3761 -	} while (ev.type != MapNotify);
   3762 -
   3763 -	cresize(w, h);
   3764  	ttynew();
   3765 -	ttyresize();
   3766 +
   3767 +	/* Look for initial configure. */
   3768 +	wl_display_roundtrip(wl.dpy);
   3769 +	if (!wl.configured) {
   3770 +		cresize(wl.w, wl.h);
   3771 +		ttyresize();
   3772 +	}
   3773 +	draw();
   3774  
   3775  	clock_gettime(CLOCK_MONOTONIC, &last);
   3776  	lastblink = last;
   3777  
   3778 -	for (xev = actionfps;;) {
   3779 +	for (;;) {
   3780  		FD_ZERO(&rfd);
   3781  		FD_SET(cmdfd, &rfd);
   3782 -		FD_SET(xfd, &rfd);
   3783 +		FD_SET(wlfd, &rfd);
   3784  
   3785 -		if (pselect(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) {
   3786 +		if (pselect(MAX(wlfd, cmdfd)+1, &rfd, NULL, NULL, tv, NULL) < 0) {
   3787  			if (errno == EINTR)
   3788  				continue;
   3789  			die("select failed: %s\n", strerror(errno));
   3790  		}
   3791 +
   3792  		if (FD_ISSET(cmdfd, &rfd)) {
   3793  			ttyread();
   3794  			if (blinktimeout) {
   3795 @@ -4398,60 +4448,54 @@ run(void)
   3796  			}
   3797  		}
   3798  
   3799 -		if (FD_ISSET(xfd, &rfd))
   3800 -			xev = actionfps;
   3801 +		if (FD_ISSET(wlfd, &rfd)) {
   3802 +			if (wl_display_dispatch(wl.dpy) == -1)
   3803 +				die("Connection error\n");
   3804 +		}
   3805  
   3806  		clock_gettime(CLOCK_MONOTONIC, &now);
   3807 -		drawtimeout.tv_sec = 0;
   3808 -		drawtimeout.tv_nsec =  (1000 * 1E6)/ xfps;
   3809 -		tv = &drawtimeout;
   3810 -
   3811 -		dodraw = 0;
   3812 -		if (blinktimeout && TIMEDIFF(now, lastblink) > blinktimeout) {
   3813 -			tsetdirtattr(ATTR_BLINK);
   3814 -			term.mode ^= MODE_BLINK;
   3815 -			lastblink = now;
   3816 -			dodraw = 1;
   3817 +		msecs = -1;
   3818 +
   3819 +		if (blinkset && blinktimeout) {
   3820 +			if (TIMEDIFF(now, lastblink) >= blinktimeout) {
   3821 +				tsetdirtattr(ATTR_BLINK);
   3822 +				term.mode ^= MODE_BLINK;
   3823 +				lastblink = now;
   3824 +			} else {
   3825 +				msecs = MIN(msecs, blinktimeout - \
   3826 +						TIMEDIFF(now, lastblink));
   3827 +			}
   3828  		}
   3829 -		deltatime = TIMEDIFF(now, last);
   3830 -		if (deltatime > 1000 / (xev ? xfps : actionfps)) {
   3831 -			dodraw = 1;
   3832 -			last = now;
   3833 +		if (repeat.len > 0) {
   3834 +			if (TIMEDIFF(now, repeat.last) >= \
   3835 +				(repeat.started ? keyrepeatinterval : \
   3836 +					keyrepeatdelay)) {
   3837 +				repeat.started = true;
   3838 +				repeat.last = now;
   3839 +				ttysend(repeat.str, repeat.len);
   3840 +			} else {
   3841 +				msecs = MIN(msecs, (repeat.started ? \
   3842 +					keyrepeatinterval : keyrepeatdelay) - \
   3843 +					TIMEDIFF(now, repeat.last));
   3844 +			}
   3845  		}
   3846  
   3847 -		if (dodraw) {
   3848 -			while (XPending(xw.dpy)) {
   3849 -				XNextEvent(xw.dpy, &ev);
   3850 -				if (XFilterEvent(&ev, None))
   3851 -					continue;
   3852 -				if (handler[ev.type])
   3853 -					(handler[ev.type])(&ev);
   3854 +		if (needdraw && wl.state & WIN_VISIBLE) {
   3855 +			if (!wl.framecb) {
   3856 +				draw();
   3857  			}
   3858 +		}
   3859  
   3860 -			draw();
   3861 -			XFlush(xw.dpy);
   3862 -
   3863 -			if (xev && !FD_ISSET(xfd, &rfd))
   3864 -				xev--;
   3865 -			if (!FD_ISSET(cmdfd, &rfd) && !FD_ISSET(xfd, &rfd)) {
   3866 -				if (blinkset) {
   3867 -					if (TIMEDIFF(now, lastblink) \
   3868 -							> blinktimeout) {
   3869 -						drawtimeout.tv_nsec = 1000;
   3870 -					} else {
   3871 -						drawtimeout.tv_nsec = (1E6 * \
   3872 -							(blinktimeout - \
   3873 -							TIMEDIFF(now,
   3874 -								lastblink)));
   3875 -					}
   3876 -					drawtimeout.tv_sec = \
   3877 -					    drawtimeout.tv_nsec / 1E9;
   3878 -					drawtimeout.tv_nsec %= (long)1E9;
   3879 -				} else {
   3880 -					tv = NULL;
   3881 -				}
   3882 -			}
   3883 +		if (msecs == -1) {
   3884 +			tv = NULL;
   3885 +		} else {
   3886 +			drawtimeout.tv_nsec = 1E6 * msecs;
   3887 +			drawtimeout.tv_sec = 0;
   3888 +			tv = &drawtimeout;
   3889  		}
   3890 +
   3891 +		wl_display_dispatch_pending(wl.dpy);
   3892 +		wl_display_flush(wl.dpy);
   3893  	}
   3894  }
   3895  
   3896 @@ -4471,9 +4515,7 @@ usage(void)
   3897  int
   3898  main(int argc, char *argv[])
   3899  {
   3900 -	xw.l = xw.t = 0;
   3901 -	xw.isfixed = False;
   3902 -	xw.cursor = cursorshape;
   3903 +	wl.cursor = cursorshape;
   3904  
   3905  	ARGBEGIN {
   3906  	case 'a':
   3907 @@ -4489,13 +4531,6 @@ main(int argc, char *argv[])
   3908  	case 'f':
   3909  		opt_font = EARGF(usage());
   3910  		break;
   3911 -	case 'g':
   3912 -		xw.gm = XParseGeometry(EARGF(usage()),
   3913 -				&xw.l, &xw.t, &cols, &rows);
   3914 -		break;
   3915 -	case 'i':
   3916 -		xw.isfixed = 1;
   3917 -		break;
   3918  	case 'o':
   3919  		opt_io = EARGF(usage());
   3920  		break;
   3921 @@ -4527,9 +4562,8 @@ run:
   3922  			opt_title = basename(xstrdup(argv[0]));
   3923  	}
   3924  	setlocale(LC_CTYPE, "");
   3925 -	XSetLocaleModifiers("");
   3926  	tnew(MAX(cols, 1), MAX(rows, 1));
   3927 -	xinit();
   3928 +	wlinit();
   3929  	selinit();
   3930  	run();
   3931  
   3932 -- 
   3933 2.37.3
   3934