📄 launcher.c
字号:
}
new_litem->prev = NULL;
new_litem->next = NULL;
if(!state->litems) {
state->lastlitem = new_litem;
state->litems = new_litem;
} else {
new_litem->next = state->litems;
state->litems->prev = new_litem;
state->litems = new_litem;
}
state->numlitems++;
return;
nomem:
fprintf(stderr, "Out of memory\n");
exit(1);
premature:
fprintf(stderr, "Premature end of line on line %d of config file\n",
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->sitems = NULL;
while(fgets(buf, 256, fp)) {
parse_config_line(state, buf, lineno);
lineno++;
}
fclose(fp);
free(buf);
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);
}
void 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);
}
}
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 handle_screensaver_event(lstate *state)
{
GR_EVENT_SCREENSAVER *event = &state->event.screensaver;
if(event->activate != GR_TRUE) return;
if(!state->sitems) {
fprintf(stderr, "Got screensaver activate event with no "
"screensavers defined\n");
return;
}
state->cursitem = state->cursitem->next;
if(!state->cursitem) state->cursitem = state->sitems;
launch_program(state->cursitem->prog);
}
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_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 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 = 1;
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;
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->sitems)
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);
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);
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 + -