2 * uterm - Linux User-Space Terminal
4 * Copyright (c) 2011-2012 David Herrmann <dh.herrmann@googlemail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Linux User-Space Terminal
28 * Historically, terminals were implemented in kernel-space on linux. With the
29 * development of KMS and the linux input-API it is now possible to implement
30 * all we need in user-space. This allows to disable the in-kernel CONFIG_VT and
31 * similar options and reduce the kernel-overhead.
32 * This library provides an API to implement terminals in user-space. This is
33 * not limited to classic text-terminals but rather to all kind of applications
34 * that need graphical output (with OpenGL) or direct keyboard/mouse/etc. input
48 * Linux provides 2 famous ways to access the video hardware: fbdev and drm
49 * fbdev is the older one of both and is simply a mmap() of the framebuffer into
50 * main memory. It does not allow 3D acceleration and if you need 2D
51 * acceleration you should use libraries like cairo to draw into the framebuffer
52 * provided by this library.
53 * DRM is the new approach which provides 3D acceleration with mesa. It allows
54 * much more configuration as fbdev and is the recommended way to access video
55 * hardware on modern computers.
56 * Modern mesa provides 3D acceleration on fbdev, too. This is used in systems
57 * like Android. This will allow us to provide an fbdev backend here.
59 * Famous linux graphics systems like X.Org/X11 or Wayland use fbdev or DRM
60 * internally to access the video hardware. This API allows low-level access to
61 * fbdev and DRM without the need of X.Org/X11 or Wayland. If VT support is
62 * enabled in your kernel, each application can run on a different VT. For
63 * instance, X.Org may run on VT-7, Wayland on VT-8, your application on VT-9
64 * and default consoles on VT-1 to VT-6. You can switch between them with
66 * If VT support is not available (very unlikely) you need other ways to switch
67 * between applications.
69 * The main object by this API is uterm_video. This object attaches to a single
70 * graphics card via DRM or on a single frambuffer via fbdev. Many DRM drivers
71 * also provide an fbdev driver so you must go sure not to write to both
72 * simulatneously. Use "UTERM_VIDEO_DRM" to scan for DRM devices. Otherwise,
73 * fbdev is used. DRM is the recommended way. Use fbdev only on embedded devices
74 * which do not come with an DRM driver.
75 * The uterm_video object scans for graphic-cards and connected displays. Each
76 * display is represented as a uterm_display object. The uterm_video object is
77 * hotplug-capable so it reports if a display is connected or disconnected.
78 * Each uterm_display object can be activated/deactivated independently of the
79 * other displays. To draw to a display you need to create a uterm_screen object
80 * and add your display to the screen. The screen object allows to spread a
81 * single screen onto multiple displays. Currently, the uterm_screen object
82 * allows only one display per screen but we may extend this in the future.
84 * If you are using fbdev, you *must* correctly destroy your uterm_video object
85 * and also call uterm_video_segfault() if you abnormally abort your
86 * application. Otherwise your video device remains in undefined state and other
87 * applications might not display correctly.
88 * If you use DRM, the same operations are recommended but not required as the
89 * kernel can correctly reset video devices on its own.
97 enum uterm_display_state {
100 UTERM_DISPLAY_INACTIVE,
104 enum uterm_display_dpms {
112 enum uterm_video_type {
118 enum uterm_video_action {
125 struct uterm_video_hotplug {
126 struct uterm_display *display;
130 enum uterm_video_format {
135 struct uterm_video_buffer {
143 struct uterm_video_blend_req {
144 const struct uterm_video_buffer *buf;
155 typedef void (*uterm_video_cb) (struct uterm_video *video,
156 struct uterm_video_hotplug *arg,
161 const char *uterm_dpms_to_name(int dpms);
163 /* screen interface */
165 int uterm_screen_new_single(struct uterm_screen **out,
166 struct uterm_display *disp);
167 void uterm_screen_ref(struct uterm_screen *screen);
168 void uterm_screen_unref(struct uterm_screen *screen);
170 unsigned int uterm_screen_width(struct uterm_screen *screen);
171 unsigned int uterm_screen_height(struct uterm_screen *screen);
173 int uterm_screen_use(struct uterm_screen *screen);
174 int uterm_screen_swap(struct uterm_screen *screen);
175 int uterm_screen_blit(struct uterm_screen *screen,
176 const struct uterm_video_buffer *buf,
177 unsigned int x, unsigned int y);
178 int uterm_screen_blend(struct uterm_screen *screen,
179 const struct uterm_video_buffer *buf,
180 unsigned int x, unsigned int y,
181 uint8_t fr, uint8_t fg, uint8_t fb,
182 uint8_t br, uint8_t bg, uint8_t bb);
183 int uterm_screen_blendv(struct uterm_screen *screen,
184 const struct uterm_video_blend_req *req, size_t num);
185 int uterm_screen_fill(struct uterm_screen *screen,
186 uint8_t r, uint8_t g, uint8_t b,
187 unsigned int x, unsigned int y,
188 unsigned int width, unsigned int height);
190 /* display modes interface */
192 void uterm_mode_ref(struct uterm_mode *mode);
193 void uterm_mode_unref(struct uterm_mode *mode);
194 struct uterm_mode *uterm_mode_next(struct uterm_mode *mode);
196 const char *uterm_mode_get_name(const struct uterm_mode *mode);
197 unsigned int uterm_mode_get_width(const struct uterm_mode *mode);
198 unsigned int uterm_mode_get_height(const struct uterm_mode *mode);
200 /* display interface */
202 void uterm_display_ref(struct uterm_display *disp);
203 void uterm_display_unref(struct uterm_display *disp);
204 struct uterm_display *uterm_display_next(struct uterm_display *disp);
206 struct uterm_mode *uterm_display_get_modes(struct uterm_display *disp);
207 struct uterm_mode *uterm_display_get_current(struct uterm_display *disp);
208 struct uterm_mode *uterm_display_get_default(struct uterm_display *disp);
210 int uterm_display_get_state(struct uterm_display *disp);
211 int uterm_display_activate(struct uterm_display *disp, struct uterm_mode *mode);
212 void uterm_display_deactivate(struct uterm_display *disp);
213 int uterm_display_set_dpms(struct uterm_display *disp, int state);
214 int uterm_display_get_dpms(const struct uterm_display *disp);
216 int uterm_display_use(struct uterm_display *disp);
217 int uterm_display_swap(struct uterm_display *disp);
219 int uterm_display_fake_blend(struct uterm_display *disp,
220 const struct uterm_video_buffer *buf,
221 unsigned int x, unsigned int y,
222 uint8_t fr, uint8_t fg, uint8_t fb,
223 uint8_t br, uint8_t bg, uint8_t bb);
224 int uterm_display_fake_blendv(struct uterm_display *disp,
225 const struct uterm_video_blend_req *req,
228 /* video interface */
230 int uterm_video_new(struct uterm_video **out,
231 struct ev_eloop *eloop,
234 void uterm_video_ref(struct uterm_video *video);
235 void uterm_video_unref(struct uterm_video *video);
237 void uterm_video_segfault(struct uterm_video *video);
238 int uterm_video_use(struct uterm_video *video);
239 struct uterm_display *uterm_video_get_displays(struct uterm_video *video);
240 int uterm_video_register_cb(struct uterm_video *video, uterm_video_cb cb,
242 void uterm_video_unregister_cb(struct uterm_video *video, uterm_video_cb cb,
245 void uterm_video_sleep(struct uterm_video *video);
246 int uterm_video_wake_up(struct uterm_video *video);
247 bool uterm_video_is_awake(struct uterm_video *video);
248 void uterm_video_poll(struct uterm_video *video);
252 * This input object can combine multiple linux input devices into a single
253 * device and notifies the application about events. It has several different
254 * keyboard backends so the full XKB feature set is available.
259 /* keep in sync with shl_xkb_mods */
260 enum uterm_input_modifier {
261 UTERM_SHIFT_MASK = (1 << 0),
262 UTERM_LOCK_MASK = (1 << 1),
263 UTERM_CONTROL_MASK = (1 << 2),
264 UTERM_ALT_MASK = (1 << 3),
265 UTERM_LOGO_MASK = (1 << 4),
268 /* keep in sync with TSM_VTE_INVALID */
269 #define UTERM_INPUT_INVALID 0xffffffff
271 struct uterm_input_event {
272 bool handled; /* user-controlled, default is false */
273 uint16_t keycode; /* linux keycode - KEY_* - linux/input.h */
274 uint32_t ascii; /* ascii keysym for @keycode */
275 unsigned int mods; /* active modifiers - uterm_modifier mask */
277 unsigned int num_syms; /* number of keysyms */
278 uint32_t *keysyms; /* XKB-common keysym-array - XKB_KEY_* */
279 uint32_t *codepoints; /* ucs4 unicode value or UTERM_INPUT_INVALID */
282 #define UTERM_INPUT_HAS_MODS(_ev, _mods) (((_ev)->mods & (_mods)) == (_mods))
284 typedef void (*uterm_input_cb) (struct uterm_input *input,
285 struct uterm_input_event *ev,
288 int uterm_input_new(struct uterm_input **out, struct ev_eloop *eloop,
292 unsigned int repeat_delay,
293 unsigned int repeat_rate);
294 void uterm_input_ref(struct uterm_input *input);
295 void uterm_input_unref(struct uterm_input *input);
297 void uterm_input_add_dev(struct uterm_input *input, const char *node);
298 void uterm_input_remove_dev(struct uterm_input *input, const char *node);
300 int uterm_input_register_cb(struct uterm_input *input,
303 void uterm_input_unregister_cb(struct uterm_input *input,
307 void uterm_input_sleep(struct uterm_input *input);
308 void uterm_input_wake_up(struct uterm_input *input);
309 bool uterm_input_is_awake(struct uterm_input *input);
311 void uterm_input_keysym_to_string(struct uterm_input *input,
312 uint32_t keysym, char *str, size_t size);
313 int uterm_input_string_to_keysym(struct uterm_input *input, const char *n,
318 * Virtual terminals allow controlling multiple virtual terminals on one real
319 * terminal. It is multi-seat capable and fully asynchronous.
323 struct uterm_vt_master;
325 enum uterm_vt_action {
335 typedef int (*uterm_vt_cb) (struct uterm_vt *vt, unsigned int action,
338 int uterm_vt_master_new(struct uterm_vt_master **out,
339 struct ev_eloop *eloop);
340 void uterm_vt_master_ref(struct uterm_vt_master *vtm);
341 void uterm_vt_master_unref(struct uterm_vt_master *vtm);
343 int uterm_vt_master_activate_all(struct uterm_vt_master *vtm);
344 int uterm_vt_master_deactivate_all(struct uterm_vt_master *vtm);
346 int uterm_vt_allocate(struct uterm_vt_master *vt, struct uterm_vt **out,
347 const char *seat, struct uterm_input *input,
348 const char *vt_for_seat0, uterm_vt_cb cb, void *data);
349 void uterm_vt_deallocate(struct uterm_vt *vt);
350 void uterm_vt_ref(struct uterm_vt *vt);
351 void uterm_vt_unref(struct uterm_vt *vt);
353 int uterm_vt_activate(struct uterm_vt *vt);
354 int uterm_vt_deactivate(struct uterm_vt *vt);
358 * This watches the system for new seats, graphics devices or other devices that
359 * are used by terminals.
362 struct uterm_monitor;
363 struct uterm_monitor_seat;
364 struct uterm_monitor_dev;
366 enum uterm_monitor_event_type {
367 UTERM_MONITOR_NEW_SEAT,
368 UTERM_MONITOR_FREE_SEAT,
369 UTERM_MONITOR_NEW_DEV,
370 UTERM_MONITOR_FREE_DEV,
371 UTERM_MONITOR_HOTPLUG_DEV,
374 enum uterm_monitor_dev_type {
377 UTERM_MONITOR_FBDEV_DRM,
381 struct uterm_monitor_event {
384 struct uterm_monitor_seat *seat;
385 const char *seat_name;
388 struct uterm_monitor_dev *dev;
389 unsigned int dev_type;
390 const char *dev_node;
394 typedef void (*uterm_monitor_cb) (struct uterm_monitor *mon,
395 struct uterm_monitor_event *event,
398 int uterm_monitor_new(struct uterm_monitor **out,
399 struct ev_eloop *eloop,
402 void uterm_monitor_ref(struct uterm_monitor *mon);
403 void uterm_monitor_unref(struct uterm_monitor *mon);
404 void uterm_monitor_scan(struct uterm_monitor *mon);
406 void uterm_monitor_set_seat_data(struct uterm_monitor_seat *seat, void *data);
407 void uterm_monitor_set_dev_data(struct uterm_monitor_dev *dev, void *data);
409 #endif /* UTERM_UTERM_H */