source: neercs/trunk/src/screens.c @ 4110

Last change on this file since 4110 was 4110, checked in by Jean-Yves Lamoureux, 12 years ago
  • Improved X10 mouse emulation, mc now accepts its click. Added MOUSER command to client/server as 'Mouse Release' command.
  • Property svn:keywords set to Id
File size: 8.7 KB
Line 
1/*
2 *  neercs        console-based window manager
3 *  Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
4 *                2008 Jean-Yves Lamoureux <jylam@lnxscene.org>
5 *                All Rights Reserved
6 *
7 *  $Id: screens.c 4110 2009-12-08 14:57:08Z jylam $
8 *
9 *  This program is free software. It comes without any warranty, to
10 *  the extent permitted by applicable law. You can redistribute it
11 *  and/or modify it under the terms of the Do What The Fuck You Want
12 *  To Public License, Version 2, as published by Sam Hocevar. See
13 *  http://sam.zoy.org/wtfpl/COPYING for more details.
14 */
15
16#include "config.h"
17
18#include <stdio.h>
19#include <string.h>
20#include <stdlib.h>
21#include <sys/types.h>
22#include <signal.h>
23#include <sys/wait.h>
24#include <errno.h>
25#include <unistd.h>
26
27#include <caca.h>
28
29#include "neercs.h"
30
31struct screen *create_screen_grab(int w, int h, int pid)
32{
33    struct screen *s = (struct screen *)malloc(sizeof(struct screen));
34
35    s->cv = caca_create_canvas(w, h);
36    caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK);
37    caca_clear_canvas(s->cv);
38    s->init = 0;
39
40    s->buf = NULL;
41    s->title = NULL;
42    s->total = 0;
43    s->w = w;
44    s->h = h;
45    s->bell = 0;
46    s->report_mouse = MOUSE_NONE;
47
48    s->fd = create_pty_grab(pid, w, h, &s->pid);
49
50    if (s->fd < 0)
51    {
52        caca_free_canvas(s->cv);
53        free(s);
54        return NULL;
55    }
56    return s;
57}
58
59struct screen *create_screen(int w, int h, char *command)
60{
61    struct screen *s = (struct screen *)malloc(sizeof(struct screen));
62
63    s->cv = caca_create_canvas(w, h);
64    caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK);
65    caca_clear_canvas(s->cv);
66    s->init = 0;
67
68    s->buf = NULL;
69    s->title = NULL;
70    s->total = 0;
71    s->w = w + 1;
72    s->h = h + 1;
73    s->bell = 0;
74    s->visible = 1;
75    s->scroll = 0;
76    s->report_mouse = MOUSE_NONE;
77    s->fd = create_pty(command, w, h, &s->pid);
78
79    s->orig_w = s->w;
80    s->orig_h = s->h;
81    s->orig_x = s->x;
82    s->orig_y = s->y;
83
84
85    if (s->fd < 0)
86    {
87        caca_free_canvas(s->cv);
88        free(s);
89        return NULL;
90    }
91    return s;
92}
93
94int destroy_screen(struct screen *s)
95{
96    if (s->fd >= 0)
97        close(s->fd);
98    if (s->buf)
99        free(s->buf);
100    if (s->title)
101        free(s->title);
102    s->buf = NULL;
103    if (s->cv)
104        caca_free_canvas(s->cv);
105    s->cv = NULL;
106    free(s);
107    return 1;
108}
109
110int add_screen(struct screen_list *list, struct screen *s)
111{
112    if (list == NULL || s == NULL)
113        return -1;
114
115    else
116    {
117        list->screen = (struct screen **)realloc(list->screen,
118                                                 sizeof(sizeof
119                                                        (struct screen *)) *
120                                                 (list->count + 1));
121        if (!list->screen)
122            fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__,
123                    __LINE__);
124        list->screen[list->count] = s;
125        list->count++;
126    }
127
128    list->changed = 1;
129
130    return list->count - 1;
131}
132
133int remove_screen(struct screen_list *list, int n, int please_kill)
134{
135
136    if (n >= list->count)
137        return -1;
138
139    if (please_kill)
140    {
141        int status = 0;
142        int ret = 0;
143        /* FIXME */
144        close(list->screen[n]->fd);
145        list->screen[n]->fd = -1;
146        kill(list->screen[n]->pid, SIGINT);
147        ret = waitpid(list->screen[n]->pid, &status,
148                      WNOHANG | WUNTRACED | WCONTINUED);
149        if (!ret)
150            kill(list->screen[n]->pid, SIGQUIT);
151        ret = waitpid(list->screen[n]->pid, &status,
152                      WNOHANG | WUNTRACED | WCONTINUED);
153        if (!ret)
154            kill(list->screen[n]->pid, SIGABRT);
155        ret = waitpid(list->screen[n]->pid, &status,
156                      WNOHANG | WUNTRACED | WCONTINUED);
157        if (!ret)
158            kill(list->screen[n]->pid, SIGKILL);
159
160    }
161    destroy_screen(list->screen[n]);
162
163    memmove(&list->screen[n],
164            &list->screen[n + 1],
165            sizeof(struct screen *) * (list->count - (n + 1)));
166
167    list->screen = (struct screen **)realloc(list->screen,
168                                             sizeof(sizeof(struct screen *))
169                                             * (list->count));
170    if (!list->screen)
171        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__,
172                __LINE__);
173
174
175
176    list->count--;
177    list->changed = 1;
178    return 1;
179}
180
181
182
183void refresh_screens(struct screen_list *screen_list)
184{
185    int i;
186
187    if (!screen_list->count)
188        return;
189
190
191    screen_list->width = caca_get_canvas_width(screen_list->cv);
192    screen_list->height =
193        caca_get_canvas_height(screen_list->cv) - (screen_list->modals.mini * 6) -
194        screen_list->modals.status;
195
196    if (!screen_list->dont_update_coords)
197    {
198        update_windows_props(screen_list);
199    }
200
201    if (screen_list->changed)
202    {
203        caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT);
204        caca_clear_canvas(screen_list->cv);
205    }
206
207    wm_refresh(screen_list);
208
209    caca_gotoxy(screen_list->cv,
210                screen_list->screen[screen_list->pty]->x +
211                caca_get_cursor_x(screen_list->screen[screen_list->pty]->cv),
212                screen_list->screen[screen_list->pty]->y +
213                caca_get_cursor_y(screen_list->screen[screen_list->pty]->cv));
214
215
216    if (screen_list->modals.mini)
217    {
218        draw_thumbnails(screen_list);
219    }
220    if (screen_list->modals.status)
221    {
222        draw_status(screen_list);
223    }
224    if (screen_list->modals.help)
225    {
226        draw_help(screen_list);
227    }
228    if (screen_list->modals.window_list)
229    {
230        draw_list(screen_list);
231    }
232#ifdef USE_PYTHON
233    debug("py : command is %d (at %p)\n", screen_list->modals.python_command, &screen_list->modals.python_command);
234    if(screen_list->modals.python_command)
235    {
236        draw_python_command(screen_list);
237    }
238#endif
239    screen_list->changed = 0;
240    for (i = screen_list->count - 1; i >= 0; i--)
241        screen_list->screen[i]->changed = 0;
242}
243
244
245int update_screens_contents(struct screen_list *screen_list)
246{
247    int i, refresh = 0;
248    int maxfd = 0;
249    struct timeval tv;
250    fd_set fdset;
251    int ret;
252
253    /* Read data, if any */
254    FD_ZERO(&fdset);
255    for (i = 0; i < screen_list->count; i++)
256    {
257        if (screen_list->screen[i]->fd >= 0)
258            FD_SET(screen_list->screen[i]->fd, &fdset);
259        if (screen_list->screen[i]->fd > maxfd)
260            maxfd = screen_list->screen[i]->fd;
261    }
262    tv.tv_sec = 0;
263    tv.tv_usec = 50000;
264    ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
265
266    if (ret < 0)
267    {
268        if (errno == EINTR)
269            ;                   /* We probably got a SIGWINCH, ignore it */
270        else
271        {
272            /* FIXME: Useless since break will mean that we return 0 But I
273               don't know what was the purpose of this code */
274            for (i = 0; i < screen_list->count; i++)
275                if (screen_list->screen[i]->total)
276                    break;
277            if (i == screen_list->count)
278                return 0;
279        }
280    }
281    else if (ret)
282    {
283
284        for (i = 0; i < screen_list->count; i++)
285        {
286            /* FIXME: try a new strategy: read all filedescriptors until each
287               of them starved at least once. */
288
289            if (screen_list->screen[i]->fd < 0 ||
290                !FD_ISSET(screen_list->screen[i]->fd, &fdset))
291                continue;
292
293            for (;;)
294            {
295                ssize_t nr;
296
297                screen_list->screen[i]->buf =
298                    realloc(screen_list->screen[i]->buf,
299                            screen_list->screen[i]->total + 1024);
300                if (!screen_list->screen[i]->buf)
301                    fprintf(stderr, "Can't allocate memory at %s:%d\n",
302                            __FUNCTION__, __LINE__);
303
304                nr = read(screen_list->screen[i]->fd,
305                          screen_list->screen[i]->buf +
306                          screen_list->screen[i]->total, 1024);
307
308                if (nr > 0)
309                {
310                    screen_list->screen[i]->total += nr;
311                    continue;
312                }
313
314                if (nr == 0 || errno != EWOULDBLOCK)
315                {
316                    remove_screen(screen_list, i, 0);
317                    if (i < screen_list->prevpty)
318                        screen_list->prevpty--;
319                    if (i == screen_list->pty)
320                    {
321                        screen_list->pty = screen_list->prevpty;
322                        screen_list->prevpty = 0;
323                    }
324                    if (i < (screen_list->pty))
325                        (screen_list->pty)--;
326                    /* Don't skip the element which is now at position i */
327                    i--;
328                    refresh = 1;
329                }
330
331                break;
332            }
333        }
334    }
335    return refresh;
336}
Note: See TracBrowser for help on using the repository browser.