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

Last change on this file since 2448 was 2448, checked in by jylam, 6 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
  • Property svn:keywords set to Id
File size: 11.8 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$
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 <unistd.h>
22#include <fcntl.h>
23#include <signal.h>
24#include <sys/ioctl.h>
25#include <sys/types.h>
26#include <sys/wait.h>
27#include <sys/time.h>
28#include <time.h>
29
30#if defined HAVE_PTY_H
31#   include <pty.h>  /* for openpty and forkpty */
32#else
33#   include <util.h> /* for OS X */
34#endif
35#if !defined HAVE_GETOPT_LONG
36#   include "mygetopt.h"
37#elif defined HAVE_GETOPT_H
38#   include <getopt.h>
39#endif
40#if defined HAVE_GETOPT_LONG
41#   define mygetopt getopt_long
42#   define myoptind optind
43#   define myoptarg optarg
44#   define myoption option
45#endif
46#include <errno.h>
47#include <cucul.h>
48#include <caca.h>
49
50#include "neercs.h"
51
52
53void version(void)
54{
55    printf("%s\n", PACKAGE_STRING);
56    printf("Copyright (C) 2006, 2008 Sam Hocevar <sam@zoy.org>\n");
57    printf("                         Jean-Yves Lamoureux <jylam@lnxscene.org>\n\n");
58    printf("This is free software.  You may redistribute copies of it under the\n");
59    printf("terms of the Do What The Fuck You Want To Public License, Version 2\n");
60    printf("<http://sam.zoy.org/wtfpl/>.\n");
61    printf("There is NO WARRANTY, to the extent permitted by law.\n");
62    printf("\n");
63    printf("For more informations, visit http://libcaca.zoy.org/wiki/neercs\n");
64}
65
66
67int main(int argc, char **argv)
68{
69    static cucul_canvas_t *cv;
70    static caca_display_t *dp;
71    struct screen_list *screen_list = NULL;
72    struct recurrent_list *recurrent_list = NULL;
73    char *default_shell = NULL;
74    int i, w, h, args, s=0;
75    int eof = 0, refresh = 1, command = 0;
76    long long unsigned int last_key_time = 0;
77
78    default_shell = getenv("SHELL");
79
80    args = argc -1;
81    if(default_shell == NULL  && args <= 0)
82    {
83        fprintf(stderr, "Environment variable SHELL not set and no arguments given. kthxbye.\n");
84        return -1;
85    }
86
87    if(args==0)
88        args = 1;
89
90    /* Create main canvas and associated caca window */
91    cv = cucul_create_canvas(0, 0);
92    dp = caca_create_display(cv);
93    if(!dp)
94        return 1;
95    caca_set_cursor(dp, 1);
96
97    w = cucul_get_canvas_width(cv);
98    h = cucul_get_canvas_height(cv);
99
100
101    /* Create screen list */
102    screen_list = (struct screen_list*)     malloc(sizeof(struct screen_list));
103    if(!screen_list)
104    {
105        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
106        return -1;
107    }
108    screen_list->screen = (struct screen**) malloc(sizeof(sizeof(struct screen*)));
109    if(!screen_list->screen)
110    {
111        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
112        return -1;
113    }
114    screen_list->count = 0;
115    screen_list->width  = cucul_get_canvas_width(cv);
116    screen_list->mini = 1;
117    screen_list->help = 0;
118    screen_list->status = 1;
119    screen_list->height = cucul_get_canvas_height(cv) - ((screen_list->mini*6) + (screen_list->status));
120    screen_list->wm_type = WM_VSPLIT;
121    screen_list->in_bell = 0;
122    screen_list->pty = screen_list->prevpty = 0;
123    screen_list->dont_update_coords = 0;
124    screen_list->screensaver_timeout = (60) * 1000000;
125    screen_list->screensaver_data = NULL;
126    screen_list->in_screensaver = 0;
127
128    recurrent_list = (struct recurrent_list*) malloc(sizeof(struct recurrent_list));
129    recurrent_list->recurrent = (struct recurrent**) malloc(sizeof(struct recurrent*));
130    if(!recurrent_list->recurrent)
131    {
132        fprintf(stderr, "Can't allocate memory at %s:%d\n", __FUNCTION__, __LINE__);
133        return -1;
134    }
135    recurrent_list->count = 0;
136
137    for(;;)
138    {
139        int option_index = 0;
140        static struct myoption long_options[] =
141            {
142#ifdef USE_GRAB
143                { "pid",         1, NULL, 'P' },
144#endif
145                { "help",        0, NULL, 'h' },
146                { "version",     0, NULL, 'v' },
147            };
148        int c = mygetopt(argc, argv, "P:hv", long_options, &option_index);
149        if(c == -1)
150            break;
151
152        switch(c)
153        {
154#ifdef USE_GRAB
155        case 'P': /* --pid */
156            add_screen(screen_list,create_screen_grab(w, h, atoi(myoptarg)));
157            s+=2;
158            break;
159#endif
160        case 'h': /* --help */
161            //   usage(argc, argv);
162            return 0;
163            break;
164        case 'v': /* --version */
165            version();
166            goto end;
167            break;
168        default:
169            fprintf(stderr, "Unknow argument #%d\n", myoptind);
170            return -1;
171            break;
172        }
173    }
174
175
176    if(s == 0 && argc<2)
177    {
178        add_screen(screen_list, create_screen(w, h, default_shell));
179    }
180
181    /* Launch command line processes */
182    for(i=0; i<(argc-1) - s; i++)
183    {
184        add_screen(screen_list, create_screen(w, h, argv[i+s+1]));
185    }
186
187
188    /* Windows are in a temporary state, resize them to the right dimensions */
189    update_windows_props(cv, screen_list);
190
191    last_key_time = get_ms();
192
193    /* Refresh */
194    caca_refresh_display(dp);
195
196    for(;;)
197    {
198        caca_event_t ev;
199        int ret;
200
201        refresh |= update_screens_contents(screen_list);
202
203        /* No more screens, exit */
204        if(!screen_list->count) break;
205
206        /* Update each screen canvas  */
207        refresh |= update_terms(screen_list);
208
209        /* Get events, if any */
210        ret = caca_get_event(dp, CACA_EVENT_ANY, &ev, 0);
211        if(ret && (caca_get_event_type(&ev) & CACA_EVENT_KEY_PRESS))
212        {
213            unsigned int c = caca_get_event_key_ch(&ev);
214
215            if(command)
216            {
217                command = 0;
218
219                switch(c)
220                {
221                case 0x01: //CACA_KEY_CTRL_A:
222                    screen_list->pty ^= screen_list->prevpty;
223                    screen_list->prevpty ^= screen_list->pty;
224                    screen_list->pty ^= screen_list->prevpty;
225                    refresh = 1;
226                    break;
227                case 'm':
228                case 0x0d: //CACA_KEY_CTRL_M:
229                    screen_list->mini = !screen_list->mini;
230                    refresh = 1;
231                    break;
232                case 'n':
233                case ' ':
234                case '\0':
235                case 0x0e: //CACA_KEY_CTRL_N:
236                    screen_list->prevpty = screen_list->pty;
237                    screen_list->pty = (screen_list->pty + 1) % screen_list->count;
238                    refresh = 1;
239                    break;
240                case 'p':
241                case 0x10: //CACA_KEY_CTRL_P:
242                    screen_list->prevpty = screen_list->pty;
243                    screen_list->pty = (screen_list->pty + screen_list->count - 1) % screen_list->count;
244                    refresh = 1;
245                    break;
246                case 'c':
247                case 0x03: //CACA_KEY_CTRL_C:
248                    screen_list->prevpty = screen_list->pty;
249                    screen_list->pty =
250                        add_screen(screen_list, create_screen(w, h, default_shell));
251                    refresh = 1;
252                    break;
253                case 'w':
254                case 0x17: //CACA_KEY_CTRL_W:
255                    screen_list->wm_type = (screen_list->wm_type==(WM_MAX-1)?
256                                            screen_list->wm_type=0:
257                                            screen_list->wm_type+1);
258                    refresh = 1;
259                    break;
260                case 0x0b: //CACA_KEY_CTRL_K:
261                    add_recurrent(recurrent_list, close_screen_recurrent, cv);
262                    refresh = 1;
263                    break;
264                case 'h':
265                case 0x08: //CACA_KEY_CTRL_H:
266                    screen_list->help = !screen_list->help;
267                    refresh = 1;
268                    break;
269                }
270            }
271            else
272            {
273
274                last_key_time = get_ms();
275                caca_set_cursor(dp, 1);
276
277                if(screen_list->in_screensaver)
278                {
279                    screensaver_kill(cv, dp, screen_list);
280                    screen_list->in_screensaver = 0;
281                    refresh = 1;
282                    continue;
283                }
284
285
286                switch(c)
287                {
288                case 0x01: //CACA_KEY_CTRL_A:
289                    command = 1; break;
290                case CACA_KEY_UP:
291                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[A", 3); break;
292                case CACA_KEY_DOWN:
293                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[B", 3); break;
294                case CACA_KEY_RIGHT:
295                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[C", 3); break;
296                case CACA_KEY_LEFT:
297                    write(screen_list->screen[screen_list->pty]->fd, "\x1b[D", 3); break;
298                case CACA_KEY_ESCAPE:
299                    if(screen_list->help) screen_list->help = 0;
300                default:
301                    write(screen_list->screen[screen_list->pty]->fd, &c, 1); break;
302                }
303            }
304        }
305        else if(ret && (caca_get_event_type(&ev) & CACA_EVENT_RESIZE))
306        {
307            update_windows_props(cv, screen_list);
308            cucul_clear_canvas(cv);
309            refresh = 1;
310        }
311        else if(ret && (caca_get_event_type(&ev) & CACA_EVENT_QUIT))
312        {
313            break;
314        }
315
316        /* Recurrent functions */
317        for(i=0; i<recurrent_list->count; i++)
318        {
319            if(recurrent_list->recurrent[i]->function)
320            {
321                refresh |= recurrent_list->recurrent[i]->function(screen_list,
322                                                                  recurrent_list->recurrent[i],
323                                                                  recurrent_list->recurrent[i]->user,
324                                                                  get_ms());
325            }
326        }
327       /* Delete recurrent functions */
328        for(i=0; i<recurrent_list->count; i++)
329        {
330            if(recurrent_list->recurrent[i]->kill_me)
331            {
332                remove_recurrent(recurrent_list, i);
333                i = 0;
334            }
335        }
336
337        /* Resfresh screen */
338        if((refresh || screen_list->in_bell) &&
339           (get_ms() - last_key_time < screen_list->screensaver_timeout))
340        {
341            refresh = 0;
342            refresh_screens(cv, dp, screen_list);
343        }
344        if((get_ms() - last_key_time > screen_list->screensaver_timeout))
345        {
346            if(!screen_list->in_screensaver)
347                screensaver_init(cv, dp, screen_list);
348            screen_list->in_screensaver = 1;
349
350            caca_set_cursor(dp, 0);
351            draw_screensaver(cv, dp, screen_list);
352            caca_refresh_display(dp);
353        }
354
355        eof = 1;
356        for(i = 0; i < screen_list->count; i++)
357            if(screen_list->screen[i]->fd >= 0)
358                eof = 0;
359        if(eof)
360            break;
361    }
362
363end:
364    /* Clean up */
365    caca_free_display(dp);
366    cucul_free_canvas(cv);
367    for(i = 0; i < screen_list->count; i++)
368    {
369        destroy_screen(screen_list->screen[i]);
370    }
371
372    free(screen_list->screen);
373    free(screen_list);
374
375
376    for(i=0; i<recurrent_list->count; i++)
377    {
378        remove_recurrent(recurrent_list, i);
379        i = 0;
380    }
381
382    free(recurrent_list->recurrent);
383    free(recurrent_list);
384
385
386    return 0;
387}
388
389
390
391long long get_ms(void)
392{
393    struct timeval tv;
394    gettimeofday(&tv, NULL);
395
396
397    return (tv.tv_sec*(1000000) + tv.tv_usec);
398}
Note: See TracBrowser for help on using the repository browser.