4 * Copyright (c) 2011 David Herrmann <dh.herrmann@googlemail.com>
5 * Copyright (c) 2011 University of Tuebingen
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files
9 * (the "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * A terminal gets assigned an input stream and several output objects and then
30 * runs a fully functional terminal emulation on it.
49 struct term_out *next;
50 struct kmscon_output *output;
53 struct kmscon_terminal {
55 struct ev_eloop *eloop;
56 struct kmscon_compositor *comp;
58 struct term_out *outputs;
59 unsigned int max_height;
61 struct kmscon_console *console;
62 struct ev_idle *redraw;
63 struct kmscon_vte *vte;
64 struct kmscon_pty *pty;
66 kmscon_terminal_closed_cb closed_cb;
70 static void draw_all(struct ev_idle *idle, void *data)
72 struct kmscon_terminal *term = data;
73 struct term_out *iter;
74 struct kmscon_output *output;
75 struct kmscon_context *ctx;
78 ctx = kmscon_compositor_get_context(term->comp);
79 ev_eloop_rm_idle(idle);
82 for (; iter; iter = iter->next) {
83 output = iter->output;
84 if (!kmscon_output_is_awake(output))
87 ret = kmscon_output_use(output);
91 kmscon_context_clear(ctx);
92 kmscon_console_map(term->console);
93 kmscon_output_swap(output);
97 static void schedule_redraw(struct kmscon_terminal *term)
101 if (!term || !term->eloop)
104 ret = ev_eloop_add_idle(term->eloop, term->redraw, draw_all, term);
105 if (ret && ret != -EALREADY)
106 log_warn("terminal: cannot schedule redraw\n");
109 static void pty_input(struct kmscon_pty *pty, const char *u8, size_t len,
112 struct kmscon_terminal *term = data;
116 term->closed_cb(term, term->closed_data);
118 kmscon_vte_input(term->vte, u8, len);
119 schedule_redraw(term);
123 int kmscon_terminal_new(struct kmscon_terminal **out,
124 struct ev_eloop *loop, struct kmscon_font_factory *ff,
125 struct kmscon_compositor *comp, struct kmscon_symbol_table *st)
127 struct kmscon_terminal *term;
133 log_debug("terminal: new terminal object\n");
135 term = malloc(sizeof(*term));
139 memset(term, 0, sizeof(*term));
144 ret = ev_idle_new(&term->redraw);
148 ret = kmscon_console_new(&term->console, ff, comp);
152 ret = kmscon_vte_new(&term->vte, st);
155 kmscon_vte_bind(term->vte, term->console);
157 ret = kmscon_pty_new(&term->pty, term->eloop, pty_input, term);
161 ev_eloop_ref(term->eloop);
162 kmscon_compositor_ref(term->comp);
168 kmscon_vte_unref(term->vte);
170 kmscon_console_unref(term->console);
172 ev_idle_unref(term->redraw);
178 void kmscon_terminal_ref(struct kmscon_terminal *term)
186 void kmscon_terminal_unref(struct kmscon_terminal *term)
188 if (!term || !term->ref)
194 kmscon_terminal_close(term);
195 kmscon_terminal_rm_all_outputs(term);
196 kmscon_pty_unref(term->pty);
197 kmscon_vte_unref(term->vte);
198 kmscon_console_unref(term->console);
199 ev_idle_unref(term->redraw);
200 kmscon_compositor_unref(term->comp);
201 ev_eloop_unref(term->eloop);
203 log_debug("terminal: destroying terminal object\n");
206 int kmscon_terminal_open(struct kmscon_terminal *term,
207 kmscon_terminal_closed_cb closed_cb, void *data)
210 unsigned short width, height;
215 width = kmscon_console_get_width(term->console);
216 height = kmscon_console_get_height(term->console);
217 ret = kmscon_pty_open(term->pty, width, height);
221 term->closed_cb = closed_cb;
222 term->closed_data = data;
226 void kmscon_terminal_close(struct kmscon_terminal *term)
231 kmscon_pty_close(term->pty);
232 term->closed_data = NULL;
233 term->closed_cb = NULL;
236 int kmscon_terminal_add_output(struct kmscon_terminal *term,
237 struct kmscon_output *output)
239 struct term_out *out;
241 struct kmscon_mode *mode;
243 if (!term || !output)
246 mode = kmscon_output_get_current(output);
248 log_warn("terminal: invalid output added to terminal\n");
252 out = malloc(sizeof(*out));
256 memset(out, 0, sizeof(*out));
257 kmscon_output_ref(output);
258 out->output = output;
259 out->next = term->outputs;
262 height = kmscon_mode_get_height(mode);
263 if (term->max_height < height) {
264 term->max_height = height;
265 kmscon_console_resize(term->console, 0, 0, term->max_height);
268 schedule_redraw(term);
273 void kmscon_terminal_rm_all_outputs(struct kmscon_terminal *term)
275 struct term_out *tmp;
280 while (term->outputs) {
282 term->outputs = tmp->next;
283 kmscon_output_unref(tmp->output);
288 int kmscon_terminal_input(struct kmscon_terminal *term,
289 const struct kmscon_input_event *ev)
298 ret = kmscon_vte_handle_keyboard(term->vte, ev, &u8, &len);
300 case KMSCON_VTE_SEND:
301 ret = kmscon_pty_write(term->pty, u8, len);
305 case KMSCON_VTE_DROP: