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

Last change on this file since 2448 was 2448, checked in by jylam, 7 years ago
  • Made Screensaver Engine (called a glazillon times) cleaner
  • Set default screensaver timeout to 60 seconds
  • Don't send key event that caused screensaver to quit to active terminal
File size: 10.0 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 <cucul.h>
28#include <caca.h>
29
30#include "neercs.h"
31
32#ifdef USE_GRAB
33struct screen* create_screen_grab(int w, int h, int pid)
34{
35    struct screen *s = (struct screen*) malloc(sizeof(struct screen));
36
37    s->cv = cucul_create_canvas(w, h);
38    cucul_set_color_ansi(s->cv, CUCUL_BLACK, CUCUL_BLACK);
39    cucul_clear_canvas(s->cv);
40    s->init = 0;
41
42    s->buf = NULL;
43    s->title = NULL;
44    s->total = 0;
45    s->w = w+1;
46    s->h = h+1;
47    s->bell = 0;
48    s->pid = pid;
49
50    s->fd = create_pty_grab(pid, w, h);
51
52    if(s->fd < 0)
53    {
54        cucul_free_canvas(s->cv);
55        free(s);
56        return NULL;
57    }
58    return s;
59}
60#endif
61
62struct screen* create_screen(int w, int h, char *command)
63{
64    struct screen *s = (struct screen*) malloc(sizeof(struct screen));
65
66    s->cv = cucul_create_canvas(w, h);
67    cucul_set_color_ansi(s->cv, CUCUL_BLACK, CUCUL_BLACK);
68    cucul_clear_canvas(s->cv);
69    s->init = 0;
70
71    s->buf = NULL;
72    s->title = NULL;
73    s->total = 0;
74    s->w = w+1;
75    s->h = h+1;
76    s->bell = 0;
77    s->visible = 1;
78    s->scroll = 0;
79    s->fd = create_pty(command, w, h, &s->pid);
80
81    s->orig_w = s->w;
82    s->orig_h = s->h;
83    s->orig_x = s->x;
84    s->orig_y = s->y;
85
86
87    if(s->fd < 0)
88    {
89        cucul_free_canvas(s->cv);
90        free(s);
91        return NULL;
92    }
93    return s;
94}
95
96int destroy_screen(struct screen *s)
97{
98    if(s->fd>=0)
99        close(s->fd);
100    if(s->buf)
101        free(s->buf);
102    if(s->title)
103        free(s->title);
104    s->buf = NULL;
105    if(s->cv)
106        cucul_free_canvas(s->cv);
107    s->cv = NULL;
108    free(s);
109    return 1;
110}
111
112int add_screen(struct screen_list *list, struct screen *s)
113{
114    if(list == NULL || s == NULL) return -1;
115
116    else
117    {
118        list->screen = (struct screen**) realloc(list->screen,
119                                                 sizeof(sizeof(struct screen*))
120                                                 * (list->count+1));
121        if(!list->screen)
122            fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
123        list->screen[list->count] = s;
124        list->count++;
125    }
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    return 1;
173}
174
175
176
177void refresh_screens(cucul_canvas_t *cv,
178                     caca_display_t *dp,
179                     struct screen_list *screen_list)
180{
181    int i;
182
183    if(!screen_list->count) return;
184
185    screen_list->width  = cucul_get_canvas_width(cv);
186    screen_list->height = cucul_get_canvas_height(cv) - (screen_list->mini*6);
187
188    if(!screen_list->dont_update_coords)
189        update_windows_props(cv, screen_list);
190
191    if(screen_list->screen[screen_list->pty]->title)
192        caca_set_display_title(dp, screen_list->screen[screen_list->pty]->title);
193    else
194        caca_set_display_title(dp, PACKAGE_STRING);
195
196    cucul_set_color_ansi(cv, CUCUL_DEFAULT, CUCUL_DEFAULT);
197    cucul_clear_canvas(cv);
198    cucul_set_color_ansi(cv, CUCUL_LIGHTRED, CUCUL_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        {
204            cucul_blit(cv,
205                       screen_list->screen[i]->x,
206                       screen_list->screen[i]->y,
207                       screen_list->screen[i]->cv, NULL);
208
209            cucul_draw_cp437_box(cv,
210                                 screen_list->screen[i]->x - 1,
211                                 screen_list->screen[i]->y - 1,
212                                 screen_list->screen[i]->w + 2,
213                                 screen_list->screen[i]->h + 2);
214            if(screen_list->screen[i]->title)
215                cucul_printf(cv,
216                             screen_list->screen[i]->x,
217                             screen_list->screen[i]->y - 1,
218                             " %.*s ",
219                             screen_list->screen[i]->w - 3,
220                             screen_list->screen[i]->title);
221        }
222    }
223
224    cucul_blit(cv,
225               screen_list->screen[screen_list->pty]->x,
226               screen_list->screen[screen_list->pty]->y,
227               screen_list->screen[screen_list->pty]->cv, NULL);
228
229    if(screen_list->screen[screen_list->pty]->bell)
230    {
231        cucul_set_color_ansi(cv, CUCUL_RED, CUCUL_BLACK);
232        screen_list->screen[screen_list->pty]->bell = 0;
233        screen_list->in_bell--;
234    }
235    else
236    {
237        cucul_set_color_ansi(cv, CUCUL_LIGHTGREEN, CUCUL_BLACK);
238    }
239
240    cucul_draw_cp437_box(cv,
241                         screen_list->screen[screen_list->pty]->x - 1,
242                         screen_list->screen[screen_list->pty]->y - 1,
243                         screen_list->screen[screen_list->pty]->w + 2,
244                         screen_list->screen[screen_list->pty]->h + 2);
245
246    if(screen_list->screen[screen_list->pty]->title)
247    {
248        cucul_printf(cv,
249                     screen_list->screen[screen_list->pty]->x,
250                     screen_list->screen[screen_list->pty]->y - 1,
251                     " %.*s ",
252                     screen_list->screen[screen_list->pty]->w - 3,
253                     screen_list->screen[screen_list->pty]->title);
254    }
255
256    cucul_gotoxy(cv,
257                 screen_list->screen[screen_list->pty]->x +
258                 cucul_get_cursor_x(screen_list->screen[screen_list->pty]->cv),
259                 screen_list->screen[screen_list->pty]->y +
260                 cucul_get_cursor_y(screen_list->screen[screen_list->pty]->cv));
261
262
263    if(screen_list->mini)
264    {
265        draw_thumbnails(cv, screen_list);
266    }
267    if(screen_list->status)
268    {
269        draw_status(cv, screen_list);
270    }
271    if(screen_list->help)
272    {
273        draw_help(cv, screen_list);
274    }
275
276    caca_refresh_display(dp);
277}
278
279
280int update_screens_contents(struct screen_list* screen_list)
281{
282    int i, refresh = 0;
283    int maxfd = 0;
284    struct timeval tv;
285    fd_set fdset;
286    int ret;
287
288    /* Read data, if any */
289    FD_ZERO(&fdset);
290    for(i = 0; i < screen_list->count; i++)
291    {
292        if(screen_list->screen[i]->fd >= 0)
293            FD_SET(screen_list->screen[i]->fd, &fdset);
294        if(screen_list->screen[i]->fd > maxfd)
295            maxfd = screen_list->screen[i]->fd;
296    }
297    tv.tv_sec = 0;
298    tv.tv_usec = 50000;
299    ret = select(maxfd + 1, &fdset, NULL, NULL, &tv);
300
301    if(ret < 0)
302    {
303        if(errno == EINTR)
304            ; /* We probably got a SIGWINCH, ignore it */
305        else
306        {
307            for(i = 0; i < screen_list->count; i++)
308                if(screen_list->screen[i]->total)
309                    break;
310            if(i == screen_list->count)
311                return 0;
312        }
313    }
314    else if(ret)
315    {
316
317    for(i = 0; i < screen_list->count; i++)
318    {
319        /* FIXME: try a new strategy: read all filedescriptors until
320         * each of them starved at least once. */
321
322        if(screen_list->screen[i]->fd < 0 ||
323           !FD_ISSET(screen_list->screen[i]->fd, &fdset))
324            continue;
325
326        for(;;)
327        {
328            ssize_t nr;
329
330            screen_list->screen[i]->buf =
331                realloc(screen_list->screen[i]->buf,
332                        screen_list->screen[i]->total + 1024);
333            if(!screen_list->screen[i]->buf)
334                fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
335
336            nr = read(screen_list->screen[i]->fd,
337                      screen_list->screen[i]->buf +
338                      screen_list->screen[i]->total, 1024);
339
340            if(nr > 0)
341            {
342                screen_list->screen[i]->total += nr;
343                continue;
344            }
345
346            if(nr == 0 || errno != EWOULDBLOCK) {
347
348                remove_screen(screen_list, i, 0);
349                if(i < screen_list->prevpty) screen_list->prevpty--;
350                if(i == screen_list->pty)
351                {
352                    screen_list->pty = screen_list->prevpty;
353                    screen_list->prevpty = 0;
354                }
355                if(i < (screen_list->pty)) (screen_list->pty)--;
356                /* Don't skip the element which is now at position i */
357                i--;
358                refresh = 1;
359            }
360
361            break;
362        }
363    }
364    }
365    return refresh;
366}
367
368
Note: See TracBrowser for help on using the repository browser.