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

Last change on this file since 3463 was 3463, checked in by Pascal Terjan, 11 years ago
  • Skip useless some blits
File size: 10.4 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: main.c 2401 2008-06-15 12:50:12Z 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#include <caca.h>
29
30#include "neercs.h"
31
32struct screen* create_screen_grab(int w, int h, int pid)
33{
34    struct screen *s = (struct screen*) malloc(sizeof(struct screen));
35
36    s->cv = caca_create_canvas(w, h);
37    caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK);
38    caca_clear_canvas(s->cv);
39    s->init = 0;
40
41    s->buf = NULL;
42    s->title = NULL;
43    s->total = 0;
44    s->w = w+1;
45    s->h = h+1;
46    s->bell = 0;
47    s->pid = pid;
48
49    s->fd = create_pty_grab(pid, w, h);
50
51    if(s->fd < 0)
52    {
53        caca_free_canvas(s->cv);
54        free(s);
55        return NULL;
56    }
57    return s;
58}
59
60struct screen* create_screen(int w, int h, char *command)
61{
62    struct screen *s = (struct screen*) malloc(sizeof(struct screen));
63
64    s->cv = caca_create_canvas(w, h);
65    caca_set_color_ansi(s->cv, CACA_BLACK, CACA_BLACK);
66    caca_clear_canvas(s->cv);
67    s->init = 0;
68
69    s->buf = NULL;
70    s->title = NULL;
71    s->total = 0;
72    s->w = w+1;
73    s->h = h+1;
74    s->bell = 0;
75    s->visible = 1;
76    s->scroll = 0;
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) return -1;
113
114    else
115    {
116        list->screen = (struct screen**) realloc(list->screen,
117                                                 sizeof(sizeof(struct screen*))
118                                                 * (list->count+1));
119        if(!list->screen)
120            fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
121        list->screen[list->count] = s;
122        list->count++;
123    }
124
125    list->changed = 1;
126
127    return list->count-1;
128}
129
130int remove_screen(struct screen_list *list, int n, int please_kill)
131{
132
133    if(n>=list->count) return -1;
134
135    if(please_kill)
136    {
137        int status = 0;
138        int ret = 0;
139        /* FIXME */
140        close(list->screen[n]->fd);
141        list->screen[n]->fd = -1;
142        kill(list->screen[n]->pid, SIGINT);
143        ret = waitpid(list->screen[n]->pid, &status,
144                      WNOHANG|WUNTRACED|WCONTINUED);
145        if(!ret)
146            kill(list->screen[n]->pid, SIGQUIT);
147        ret = waitpid(list->screen[n]->pid, &status,
148                      WNOHANG|WUNTRACED|WCONTINUED);
149        if(!ret)
150            kill(list->screen[n]->pid, SIGABRT);
151        ret = waitpid(list->screen[n]->pid, &status,
152                      WNOHANG|WUNTRACED|WCONTINUED);
153        if(!ret)
154            kill(list->screen[n]->pid, SIGKILL);
155
156    }
157    destroy_screen(list->screen[n]);
158
159    memmove(&list->screen[n],
160            &list->screen[n+1],
161            sizeof(struct screen*)*(list->count-(n+1)));
162
163    list->screen = (struct screen**) realloc(list->screen,
164                                             sizeof(sizeof(struct screen*))
165                                             * (list->count));
166    if(!list->screen)
167        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
168
169
170
171    list->count--;
172    list->changed = 1;
173    return 1;
174}
175
176
177
178void refresh_screens(struct screen_list *screen_list)
179{
180    int i;
181
182    if(!screen_list->count) return;
183
184
185    debug("Current pty is %d\n", screen_list->pty);
186
187    screen_list->width  = caca_get_canvas_width(screen_list->cv);
188    screen_list->height = caca_get_canvas_height(screen_list->cv) - (screen_list->mini*6);
189
190    if(!screen_list->dont_update_coords)
191        update_windows_props(screen_list);
192
193    if(screen_list->changed)
194    {
195        caca_set_color_ansi(screen_list->cv, CACA_DEFAULT, CACA_DEFAULT);
196        caca_clear_canvas(screen_list->cv);
197    }
198    caca_set_color_ansi(screen_list->cv, CACA_LIGHTRED, CACA_BLACK);
199
200    for(i = screen_list->count - 1; i >=0; i--)
201    {
202        if(i!=screen_list->pty && screen_list->screen[i]->visible &&
203           (screen_list->screen[i]->changed || screen_list->changed || screen_list->wm_type==WM_CARD))
204        {
205            caca_blit(screen_list->cv,
206                       screen_list->screen[i]->x,
207                       screen_list->screen[i]->y,
208                       screen_list->screen[i]->cv, NULL);
209
210            caca_draw_cp437_box(screen_list->cv,
211                                 screen_list->screen[i]->x - 1,
212                                 screen_list->screen[i]->y - 1,
213                                 screen_list->screen[i]->w + 2,
214                                 screen_list->screen[i]->h + 2);
215            if(screen_list->screen[i]->title)
216                caca_printf(screen_list->cv,
217                             screen_list->screen[i]->x,
218                             screen_list->screen[i]->y - 1,
219                             " %.*s ",
220                             screen_list->screen[i]->w - 3,
221                             screen_list->screen[i]->title);
222        }
223    }
224
225    if(screen_list->screen[screen_list->pty]->changed || screen_list->changed || screen_list->wm_type==WM_CARD)
226        caca_blit(screen_list->cv,
227                  screen_list->screen[screen_list->pty]->x,
228                  screen_list->screen[screen_list->pty]->y,
229                  screen_list->screen[screen_list->pty]->cv, NULL);
230
231    if(screen_list->screen[screen_list->pty]->bell)
232    {
233        caca_set_color_ansi(screen_list->cv, CACA_RED, CACA_BLACK);
234        screen_list->screen[screen_list->pty]->bell = 0;
235        screen_list->in_bell--;
236    }
237    else
238    {
239        caca_set_color_ansi(screen_list->cv, CACA_LIGHTGREEN, CACA_BLACK);
240    }
241
242    caca_draw_cp437_box(screen_list->cv,
243                         screen_list->screen[screen_list->pty]->x - 1,
244                         screen_list->screen[screen_list->pty]->y - 1,
245                         screen_list->screen[screen_list->pty]->w + 2,
246                         screen_list->screen[screen_list->pty]->h + 2);
247
248    if(screen_list->screen[screen_list->pty]->title)
249    {
250        caca_printf(screen_list->cv,
251                     screen_list->screen[screen_list->pty]->x,
252                     screen_list->screen[screen_list->pty]->y - 1,
253                     " %.*s ",
254                     screen_list->screen[screen_list->pty]->w - 3,
255                     screen_list->screen[screen_list->pty]->title);
256    }
257
258    caca_gotoxy(screen_list->cv,
259                 screen_list->screen[screen_list->pty]->x +
260                 caca_get_cursor_x(screen_list->screen[screen_list->pty]->cv),
261                 screen_list->screen[screen_list->pty]->y +
262                 caca_get_cursor_y(screen_list->screen[screen_list->pty]->cv));
263
264
265    if(screen_list->mini)
266    {
267        draw_thumbnails(screen_list);
268    }
269    if(screen_list->status)
270    {
271        draw_status(screen_list);
272    }
273    if(screen_list->help)
274    {
275        draw_help(screen_list);
276    }
277    if(screen_list->window_list)
278    {
279        draw_list(screen_list);
280    }
281    screen_list->changed = 0;
282    for(i = screen_list->count - 1; i >=0; i--)
283        screen_list->screen[i]->changed = 0;
284}
285
286
287int update_screens_contents(struct screen_list* screen_list)
288{
289    int i, refresh = 0;
290    int maxfd = 0;
291    struct timeval tv;
292    fd_set fdset;
293    int ret;
294
295    /* Read data, if any */
296    FD_ZERO(&fdset);
297    for(i = 0; i < screen_list->count; i++)
298    {
299        if(screen_list->screen[i]->fd >= 0)
300            FD_SET(screen_list->screen[i]->fd, &fdset);
301        if(screen_list->screen[i]->fd > maxfd)
302            maxfd = screen_list->screen[i]->fd;
303    }
304    tv.tv_sec = 0;
305    tv.tv_usec = 50000;
306    ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
307
308    if(ret < 0)
309    {
310        if(errno == EINTR)
311            ; /* We probably got a SIGWINCH, ignore it */
312        else
313        {
314            for(i = 0; i < screen_list->count; i++)
315                if(screen_list->screen[i]->total)
316                    break;
317            if(i == screen_list->count)
318                return 0;
319        }
320    }
321    else if(ret)
322    {
323
324    for(i = 0; i < screen_list->count; i++)
325    {
326        /* FIXME: try a new strategy: read all filedescriptors until
327         * each of them starved at least once. */
328
329        if(screen_list->screen[i]->fd < 0 ||
330           !FD_ISSET(screen_list->screen[i]->fd, &fdset))
331            continue;
332
333        for(;;)
334        {
335            ssize_t nr;
336
337            screen_list->screen[i]->buf =
338                realloc(screen_list->screen[i]->buf,
339                        screen_list->screen[i]->total + 1024);
340            if(!screen_list->screen[i]->buf)
341                fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
342
343            nr = read(screen_list->screen[i]->fd,
344                      screen_list->screen[i]->buf +
345                      screen_list->screen[i]->total, 1024);
346
347            if(nr > 0)
348            {
349                screen_list->screen[i]->total += nr;
350                continue;
351            }
352
353            if(nr == 0 || errno != EWOULDBLOCK)
354            {
355                remove_screen(screen_list, i, 0);
356                if(i < screen_list->prevpty) screen_list->prevpty--;
357                if(i == screen_list->pty)
358                {
359                    screen_list->pty = screen_list->prevpty;
360                    screen_list->prevpty = 0;
361                }
362                if(i < (screen_list->pty)) (screen_list->pty)--;
363                /* Don't skip the element which is now at position i */
364                i--;
365                refresh = 1;
366            }
367
368            break;
369        }
370    }
371    }
372    return refresh;
373}
374
375
Note: See TracBrowser for help on using the repository browser.