source: mainline/uspace/lib/ui/src/ui.c@ 760a392

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 760a392 was 9c7dc8e, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Print text as text in textmode UI. Make calculator smaller in text mode.

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 * Copyright (c) 2021 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libui
30 * @{
31 */
32/**
33 * @file User interface
34 */
35
36#include <ctype.h>
37#include <display.h>
38#include <errno.h>
39#include <fibril.h>
40#include <io/console.h>
41#include <stdlib.h>
42#include <str.h>
43#include <task.h>
44#include <ui/ui.h>
45#include <ui/wdecor.h>
46#include "../private/window.h"
47#include "../private/ui.h"
48
49/** Parse output specification.
50 *
51 * Output specification has the form <proto>@<service> where proto is
52 * eiher 'disp' for display service or 'cons' for console. Service
53 * is a location ID service name (e.g. hid/display).
54 *
55 * @param ospec Output specification
56 * @param ws Place to store window system type (protocol)
57 * @param osvc Place to store pointer to output service name
58 */
59static void ui_ospec_parse(const char *ospec, ui_winsys_t *ws,
60 const char **osvc)
61{
62 const char *cp;
63
64 if (ospec == UI_DISPLAY_DEFAULT) {
65 *ws = ui_ws_display;
66 *osvc = DISPLAY_DEFAULT;
67 return;
68 }
69
70 cp = ospec;
71 while (isalpha(*cp))
72 ++cp;
73
74 if (*cp == '@') {
75 if (str_lcmp(ospec, "disp@", str_length("disp@")) == 0) {
76 *ws = ui_ws_display;
77 } else if (str_lcmp(ospec, "cons@", str_length("cons@")) == 0) {
78 *ws = ui_ws_console;
79 } else {
80 *ws = ui_ws_unknown;
81 }
82
83 if (cp[1] != '\0')
84 *osvc = cp + 1;
85 else
86 *osvc = NULL;
87 } else {
88 *ws = ui_ws_display;
89 *osvc = ospec;
90 }
91}
92
93/** Create new user interface.
94 *
95 * @param ospec Output specification or @c UI_DISPLAY_DEFAULT to use
96 * the default output
97 * @param rui Place to store pointer to new UI
98 * @return EOK on success or an error code
99 */
100errno_t ui_create(const char *ospec, ui_t **rui)
101{
102 errno_t rc;
103 display_t *display;
104 console_ctrl_t *console;
105 ui_winsys_t ws;
106 const char *osvc;
107 ui_t *ui;
108
109 ui_ospec_parse(ospec, &ws, &osvc);
110
111 if (ws == ui_ws_display) {
112 rc = display_open(osvc, &display);
113 if (rc != EOK)
114 return rc;
115
116 rc = ui_create_disp(display, &ui);
117 if (rc != EOK) {
118 display_close(display);
119 return rc;
120 }
121 } else if (ws == ui_ws_console) {
122 console = console_init(stdin, stdout);
123 if (console == NULL)
124 return EIO;
125
126 /* ws == ui_ws_console */
127 rc = ui_create_cons(console, &ui);
128 if (rc != EOK) {
129 console_done(console);
130 return rc;
131 }
132 } else {
133 return EINVAL;
134 }
135
136 ui->myoutput = true;
137 *rui = ui;
138 return EOK;
139}
140
141/** Create new user interface using console service.
142 *
143 * @param rui Place to store pointer to new UI
144 * @return EOK on success or an error code
145 */
146errno_t ui_create_cons(console_ctrl_t *console, ui_t **rui)
147{
148 ui_t *ui;
149
150 ui = calloc(1, sizeof(ui_t));
151 if (ui == NULL)
152 return ENOMEM;
153
154 ui->console = console;
155 *rui = ui;
156 return EOK;
157}
158
159/** Create new user interface using display service.
160 *
161 * @param disp Display
162 * @param rui Place to store pointer to new UI
163 * @return EOK on success or an error code
164 */
165errno_t ui_create_disp(display_t *disp, ui_t **rui)
166{
167 ui_t *ui;
168
169 ui = calloc(1, sizeof(ui_t));
170 if (ui == NULL)
171 return ENOMEM;
172
173 ui->display = disp;
174 *rui = ui;
175 return EOK;
176}
177
178/** Destroy user interface.
179 *
180 * @param ui User interface or @c NULL
181 */
182void ui_destroy(ui_t *ui)
183{
184 if (ui == NULL)
185 return;
186
187 if (ui->myoutput) {
188 if (ui->console != NULL)
189 console_done(ui->console);
190 if (ui->display != NULL)
191 display_close(ui->display);
192 }
193
194 free(ui);
195}
196
197static void ui_cons_event_process(ui_t *ui, cons_event_t *event)
198{
199 if (ui->root_wnd == NULL)
200 return;
201
202 switch (event->type) {
203 case CEV_KEY:
204 ui_window_send_kbd(ui->root_wnd, &event->ev.key);
205 break;
206 case CEV_POS:
207 ui_wdecor_pos_event(ui->root_wnd->wdecor, &event->ev.pos);
208 ui_window_send_pos(ui->root_wnd, &event->ev.pos);
209 break;
210 }
211}
212
213/** Execute user interface.
214 *
215 * Return task exit code of zero and block unitl the application starts
216 * the termination process by calling ui_quit(@a ui).
217 *
218 * @param ui User interface
219 */
220void ui_run(ui_t *ui)
221{
222 bool have_event;
223 cons_event_t event;
224 usec_t timeout;
225
226 /* Only return command prompt if we are running in a separate window */
227 if (ui->display != NULL)
228 task_retval(0);
229
230 while (!ui->quit) {
231 if (ui->console != NULL) {
232 timeout = 100000;
233 have_event = console_get_event_timeout(ui->console,
234 &event, &timeout);
235 if (have_event)
236 ui_cons_event_process(ui, &event);
237 } else {
238 fibril_usleep(100000);
239 }
240 }
241}
242
243/** Terminate user interface.
244 *
245 * Calling this function causes the user interface to terminate
246 * (i.e. exit from ui_run()). This would be typically called from
247 * an event handler.
248 *
249 * @param ui User interface
250 */
251void ui_quit(ui_t *ui)
252{
253 ui->quit = true;
254}
255
256/** Determine if we are running in text mode.
257 *
258 * @param ui User interface
259 * @return @c true iff we are running in text mode
260 */
261bool ui_is_textmode(ui_t *ui)
262{
263 /*
264 * XXX Currently console is always text and display is always
265 * graphics, but this need not always be true.
266 */
267 return (ui->console != NULL);
268}
269
270/** @}
271 */
Note: See TracBrowser for help on using the repository browser.