📄 launcher.c
字号:
lineno);}void read_config(lstate *state){ int lineno = 1; FILE *fp; char *buf = my_malloc(256); if(!(fp = fopen(state->config_file, "r"))) { fprintf(stderr, "Couldn't open config file \"%s\"\n", state->config_file); exit(2); } state->litems = NULL; state->numlitems = 0; state->ssitems = NULL; state->randomss = 0; state->numssitems = 0; state->stitems = NULL; state->rotatess = 0; while(fgets(buf, 256, fp)) { parse_config_line(state, buf, lineno); lineno++; } fclose(fp); free(buf); if(state->randomss) choose_random_screensaver(state); else state->curssitem = state->ssitems; if(!state->numlitems) { fprintf(stderr, "No valid launcher items in config file\n"); exit(5); }}void draw_item(lstate *state, litem *item){ GR_SIZE width, height, base, x, len; GrDrawImageToFit(item->wid, state->gc, ICON_X_POSITION, ICON_Y_POSITION, ICON_WIDTH, ICON_HEIGHT, item->iconid); len = strlen(item->name); GrGetGCTextSize(state->gc, item->name, len, 0, &width, &height, &base); if(width >= ITEM_WIDTH) x = 0; else x = (ITEM_WIDTH - width) / 2; GrText(item->wid, state->gc, x, TEXT_Y_POSITION, item->name, len, 0);}void handle_exposure_event(lstate *state){ GR_EVENT_EXPOSURE *event = &state->event.exposure; litem *i = state->litems; if(event->wid == state->main_window) return; while(i) { if(event->wid == i->wid) { draw_item(state, i); return; } i = i->next; } fprintf(stderr, "Got exposure event for unknown window %d\n", event->wid);}pid_t launch_program(prog_item *prog){ pid_t pid; if((pid = fork()) == -1) perror("Couldn't fork"); else if(!pid) { if(execvp(prog->command, prog->argv) == -1) fprintf(stderr, "Couldn't start \"%s\": %s\n", prog->command, strerror(errno)); exit(7); } return pid;}void handle_mouse_event(lstate *state){ GR_EVENT_MOUSE *event = &state->event.mouse; litem *i = state->litems; if(event->wid == state->main_window) return; while(i) { if(event->wid == i->wid) { launch_program(i->prog); return; } i = i->next; } fprintf(stderr, "Got mouse event for unknown window %d\n", event->wid);}void choose_random_screensaver(lstate *state){ int i; ssitem *s; if(!state->numssitems) return; do { i = rand() % state->numssitems; s = state->ssitems; while(i--) s = s->next; } while(s == state->curssitem); state->curssitem = s;}void activate_screensaver(lstate *state){ sspid = launch_program(state->curssitem->prog); if(state->randomss) choose_random_screensaver(state); else { state->curssitem = state->curssitem->next; if(!state->curssitem) state->curssitem = state->ssitems; }}void deactivate_screensaver(lstate *state){ if(sspid >= 0) kill(sspid, SIGINT);}void handle_screensaver_event(lstate *state){ GR_EVENT_SCREENSAVER *event = &state->event.screensaver; if(event->activate != GR_TRUE) { if(state->ssrotatetimer > 0) GrDestroyTimer(state->ssrotatetimer); return; } if(!state->ssitems) { fprintf(stderr, "Got screensaver activate event with no " "screensavers defined\n"); return; } activate_screensaver(state); if(state->rotatess) { state->ssrotatetimer = GrCreateTimer(state->main_window, state->rotatess * 1000 /*, GR_TRUE*/); } else state->ssrotatetimer = -1;}void handle_timer_event(lstate *state){ GR_EVENT_TIMER *event = &state->event.timer; if(event->tid != state->ssrotatetimer) return; deactivate_screensaver(state); activate_screensaver(state);}void handle_event(lstate *state){ switch(state->event.type) { case GR_EVENT_TYPE_EXPOSURE: handle_exposure_event(state); break; case GR_EVENT_TYPE_BUTTON_DOWN: handle_mouse_event(state); break; case GR_EVENT_TYPE_CLOSE_REQ: break; case GR_EVENT_TYPE_SCREENSAVER: handle_screensaver_event(state); break; case GR_EVENT_TYPE_TIMER: handle_timer_event(state); break; case GR_EVENT_TYPE_NONE: break; default: fprintf(stderr, "Got unknown event type %d\n", state->event.type); break; }}void do_event_loop(lstate *state){ do { GrGetNextEvent(&state->event); handle_event(state); } while(state->event.type != GR_EVENT_TYPE_CLOSE_REQ);}void do_startups(lstate *state){ stitem *tmp, *st = state->stitems; while(st) { launch_program(st->prog); tmp = st; st = st->next; free_prog_item(tmp->prog); free(tmp); }}void initialise(lstate *state){ GR_SCREEN_INFO si; GR_IMAGE_ID back_image; GR_IMAGE_INFO imageinfo; int rows = 1, columns = 1, width, height, x = 0, y = 0; GR_WM_PROPERTIES props; litem *i; if(GrOpen() < 0) { fprintf(stderr, "Couldn't connect to Nano-X server\n"); exit(4); } state->window_background_mode = 0; state->window_background_image = NULL; sspid = -1; read_config(state); GrGetScreenInfo(&si); if(si.rows > si.cols) { rows = state->numlitems; while((((rows / columns) + rows % columns) * ITEM_HEIGHT) > si.rows) { columns++; } if((columns * ITEM_WIDTH) > si.cols) goto toomany; rows = (rows / columns) + (rows % columns); width = columns * ITEM_WIDTH + 1 + columns; height = rows * ITEM_HEIGHT + 1 + rows; } else { columns = state->numlitems; while((((columns / rows) + (columns % rows)) * ITEM_WIDTH) > si.cols) { rows++; } if((rows * ITEM_HEIGHT) > si.rows) goto toomany; columns = (columns / rows) + (columns % rows); width = columns * ITEM_WIDTH + 1 + columns; height = (rows * ITEM_HEIGHT) + 1 + rows; y = si.rows - (rows * ITEM_HEIGHT) - 1 - rows; } state->gc = GrNewGC(); GrSetGCForeground(state->gc, ITEM_TEXT_COLOUR); GrSetGCBackground(state->gc, ITEM_BACKGROUND_COLOUR); if(state->window_background_image) { if(!(back_image = GrLoadImageFromFile( state->window_background_image, 0))) { fprintf(stderr, "Couldn't load background image\n"); } else { GrGetImageInfo(back_image, &imageinfo); if(!(state->background_pixmap = GrNewPixmap( imageinfo.width, imageinfo.height, NULL))) { fprintf(stderr, "Couldn't allocate pixmap " "for background image\n"); } else { GrDrawImageToFit(state->background_pixmap, state->gc, 0, 0, imageinfo.width, imageinfo.height, back_image); GrFreeImage(back_image); GrSetBackgroundPixmap(GR_ROOT_WINDOW_ID, state->background_pixmap, state->window_background_mode); GrClearWindow(GR_ROOT_WINDOW_ID, GR_TRUE); } } } if(state->ssitems) GrSelectEvents(GR_ROOT_WINDOW_ID, GR_EVENT_MASK_SCREENSAVER); state->main_window = GrNewWindow(GR_ROOT_WINDOW_ID, 0, y, width, height, 0, ITEM_BACKGROUND_COLOUR, 0); GrSelectEvents(state->main_window, GR_EVENT_MASK_CLOSE_REQ | GR_EVENT_MASK_TIMER); props.flags = GR_WM_FLAGS_PROPS; props.props = GR_WM_PROPS_NOMOVE | GR_WM_PROPS_NODECORATE | GR_WM_PROPS_NOAUTOMOVE | GR_WM_PROPS_NOAUTORESIZE; GrSetWMProperties(state->main_window, &props); i = state->lastlitem; y = 0; while(i) { i->wid = GrNewWindow(state->main_window, (x * ITEM_WIDTH) + x + 1, (y * ITEM_HEIGHT) + y + 1, ITEM_WIDTH, ITEM_HEIGHT, 1, ITEM_BACKGROUND_COLOUR, ITEM_BORDER_COLOUR); GrSelectEvents(i->wid, GR_EVENT_MASK_EXPOSURE | GR_EVENT_MASK_BUTTON_DOWN); GrMapWindow(i->wid); i = i->prev; if(++x == columns) { x = 0; y++; } } GrMapWindow(state->main_window); signal(SIGCHLD, &reaper); do_startups(state); return;toomany: fprintf(stderr, "Too many items to fit on screen\n"); exit(6);}int main(int argc, char *argv[]){ lstate *state; if(argc != 2) usage(); state = my_malloc(sizeof(lstate)); state->config_file = strdup(argv[1]); initialise(state); do_event_loop(state); GrClose(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -