/* * Called when the keyboard mapping changes. We update our symbols. * * We ignore errors — if the new keymap cannot be loaded it’s better if the * screen stays locked and the user intervenes by using killall i3lock. * */ static void process_xkb_event(xcb_generic_event_t *gevent) { union xkb_event { struct { uint8_t response_type; uint8_t xkbType; uint16_t sequence; xcb_timestamp_t time; uint8_t deviceID; } any; xcb_xkb_new_keyboard_notify_event_t new_keyboard_notify; xcb_xkb_map_notify_event_t map_notify; xcb_xkb_state_notify_event_t state_notify; } *event = (union xkb_event *)gevent; DEBUG("process_xkb_event for device %d\n", event->any.deviceID); if (event->any.deviceID != xkb_x11_get_core_keyboard_device_id(conn)) return; /* * XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap * updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent * recompilations. */ switch (event->any.xkbType) { case XCB_XKB_NEW_KEYBOARD_NOTIFY: if (event->new_keyboard_notify.changed & XCB_XKB_NKN_DETAIL_KEYCODES) (void)load_keymap(); break; case XCB_XKB_MAP_NOTIFY: (void)load_keymap(); break; case XCB_XKB_STATE_NOTIFY: xkb_state_update_mask(xkb_state, event->state_notify.baseMods, event->state_notify.latchedMods, event->state_notify.lockedMods, event->state_notify.baseGroup, event->state_notify.latchedGroup, event->state_notify.lockedGroup); break; } }
void rungame(void) { int ret, role = initrole, race = initrace, gend = initgend, align = initalign; int fd = -1; char plname[BUFSZ]; fnchar filename[1024]; fnchar savedir[BUFSZ]; long t; if (!get_gamedir(SAVE_DIR, savedir)) { curses_raw_print("Could not find where to put the logfile for a new game."); return; } if (!player_selection(&role, &race, &gend, &align, random_player)) return; strncpy(plname, settings.plname, PL_NSIZ); /* The player name is set to "wizard" (again) in nh_start_game, so setting * it here just prevents wizmode player from being asked for a name. */ if (ui_flags.playmode == MODE_WIZARD) strcpy(plname, "wizard"); while (!plname[0]) curses_getline("what is your name?", plname); if (plname[0] == '\033') /* canceled */ return; t = (long)time(NULL); #if defined(WIN32) snwprintf(filename, 1024, L"%ls%ld_%hs.nhgame", savedir, t, plname); #else snprintf(filename, 1024, "%s%ld_%s.nhgame", savedir, t, plname); #endif fd = sys_open(filename, O_TRUNC | O_CREAT | O_RDWR, FILE_OPEN_MASK); if (fd == -1) { curses_raw_print("Could not create the logfile."); return; } create_game_windows(); if (!nh_start_game(fd, plname, role, race, gend, align, ui_flags.playmode)) { destroy_game_windows(); close(fd); return; } load_keymap(); /* need to load the keymap after the game has been started */ ret = commandloop(); free_keymap(); close(fd); destroy_game_windows(); cleanup_messages(); game_ended(ret, filename); }
int run_repl() { repl_t *repl = make_repl(); s_repl = repl; repl->current_ns = strdup("cljs.user"); repl->current_prompt = form_prompt(repl->current_ns, false); // Per-type initialization if (!config.dumb_terminal) { char *home = getenv("HOME"); if (home != NULL) { char history_name[] = ".planck_history"; size_t len = strlen(home) + strlen(history_name) + 2; repl->history_path = malloc(len * sizeof(char)); snprintf(repl->history_path, len, "%s/%s", home, history_name); linenoiseHistoryLoad(repl->history_path); exit_value = load_keymap(home); if (exit_value != EXIT_SUCCESS) { return exit_value; } } linenoiseSetMultiLine(1); linenoiseSetCompletionCallback(completion); linenoiseSetHighlightCallback(highlight); linenoiseSetHighlightCancelCallback(highlight_cancel); } if (!config.dumb_terminal) { cljs_set_print_sender(&linenoisePrintNow); } if (config.socket_repl_port) { pthread_t thread; pthread_create(&thread, NULL, accept_connections, NULL); } run_cmdline_loop(repl); return exit_value; }
/* \brief Helper function to load a keymap configuration file. Used by the input method implementations. */ int load_keymap(imli_input_method_t im, const char *basedir, const char *file) { int i; char fullpath[128]; snprintf(fullpath, sizeof(fullpath), "%s\\langfiles\\%s", basedir, file); //TODO needs to be backslash FILE *fp = fopen(fullpath, "r"); if (!fp) return -1; for(i = 0; i <= 32; i++) { im->codes[i] = i; im->types[i] = TYPE_ASCII; } for(i = 33; i < 128; i++) { im->codes[i] = 0; im->types[i] = TYPE_INVALID; } char buf[128]; while (!feof(fp)) { fgets(buf, sizeof(buf), fp); char include_file[128]; if (sscanf(buf, "include %s\n", include_file) == 1) { load_keymap(im, basedir, include_file); continue; } if (parse_keymap_line(im, buf) != 0) fprintf(stderr, "Debug: malformed line in file: %s\nLine: %s\n", file, buf); } fclose(fp); return 0; }
imli_input_method_t open_phonetic_input_method (imli_context_t ctx, imli_script_t script) { char buf[128]; char *basedir = imli_home_dir(ctx); const char *script_name = imli_script_name(script); imli_input_method_t im = (imli_input_method_t)malloc(sizeof(struct imli_input_method)); if (!im) return NULL; im->keyboard = PHONETIC; im->compose = phonetic_process_key; snprintf(buf, sizeof(buf), "%s_phonetic.txt", script_name); if (load_keymap(im, basedir, buf) == 0) { im->tag = 1; } else { free(im); im = open_phonetic_input_method_compat(ctx, script); } free(basedir); return im; }
int main(int argc, char *argv[]) { struct passwd *pw; char *username; char *image_path = NULL; int ret; struct pam_conv conv = {conv_callback, NULL}; int curs_choice = CURS_NONE; int o; int optind = 0; struct option longopts[] = { {"version", no_argument, NULL, 'v'}, {"nofork", no_argument, NULL, 'n'}, {"beep", no_argument, NULL, 'b'}, {"dpms", no_argument, NULL, 'd'}, {"color", required_argument, NULL, 'c'}, {"pointer", required_argument, NULL, 'p'}, {"debug", no_argument, NULL, 0}, {"help", no_argument, NULL, 'h'}, {"no-unlock-indicator", no_argument, NULL, 'u'}, {"image", required_argument, NULL, 'i'}, {"tiling", no_argument, NULL, 't'}, {"ignore-empty-password", no_argument, NULL, 'e'}, {"inactivity-timeout", required_argument, NULL, 'I'}, {"show-failed-attempts", no_argument, NULL, 'f'}, {NULL, no_argument, NULL, 0} }; if ((pw = getpwuid(getuid())) == NULL) err(EXIT_FAILURE, "getpwuid() failed"); if ((username = pw->pw_name) == NULL) errx(EXIT_FAILURE, "pw->pw_name is NULL.\n"); char *optstring = "hvnbdc:p:ui:teI:f"; while ((o = getopt_long(argc, argv, optstring, longopts, &optind)) != -1) { switch (o) { case 'v': errx(EXIT_SUCCESS, "version " VERSION " © 2010 Michael Stapelberg"); case 'n': dont_fork = true; break; case 'b': beep = true; break; case 'd': fprintf(stderr, "DPMS support has been removed from i3lock. Please see the manpage i3lock(1).\n"); break; case 'I': { int time = 0; if (sscanf(optarg, "%d", &time) != 1 || time < 0) errx(EXIT_FAILURE, "invalid timeout, it must be a positive integer\n"); inactivity_timeout = time; break; } case 'c': { char *arg = optarg; /* Skip # if present */ if (arg[0] == '#') arg++; if (strlen(arg) != 6 || sscanf(arg, "%06[0-9a-fA-F]", color) != 1) errx(EXIT_FAILURE, "color is invalid, it must be given in 3-byte hexadecimal format: rrggbb\n"); break; } case 'u': unlock_indicator = false; break; case 'i': image_path = strdup(optarg); break; case 't': tile = true; break; case 'p': if (!strcmp(optarg, "win")) { curs_choice = CURS_WIN; } else if (!strcmp(optarg, "default")) { curs_choice = CURS_DEFAULT; } else { errx(EXIT_FAILURE, "i3lock: Invalid pointer type given. Expected one of \"win\" or \"default\".\n"); } break; case 'e': ignore_empty_password = true; break; case 0: if (strcmp(longopts[optind].name, "debug") == 0) debug_mode = true; break; case 'f': show_failed_attempts = true; break; default: errx(EXIT_FAILURE, "Syntax: i3lock [-v] [-n] [-b] [-d] [-c color] [-u] [-p win|default]" " [-i image.png] [-t] [-e] [-I timeout] [-f]"); } } /* We need (relatively) random numbers for highlighting a random part of * the unlock indicator upon keypresses. */ srand(time(NULL)); /* Initialize PAM */ ret = pam_start("i3lock", username, &conv, &pam_handle); if (ret != PAM_SUCCESS) errx(EXIT_FAILURE, "PAM: %s", pam_strerror(pam_handle, ret)); /* Using mlock() as non-super-user seems only possible in Linux. Users of other * operating systems should use encrypted swap/no swap (or remove the ifdef and * run i3lock as super-user). */ #if defined(__linux__) /* Lock the area where we store the password in memory, we don’t want it to * be swapped to disk. Since Linux 2.6.9, this does not require any * privileges, just enough bytes in the RLIMIT_MEMLOCK limit. */ if (mlock(password, sizeof(password)) != 0) err(EXIT_FAILURE, "Could not lock page in memory, check RLIMIT_MEMLOCK"); #endif /* Double checking that connection is good and operatable with xcb */ int screennr; if ((conn = xcb_connect(NULL, &screennr)) == NULL || xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?"); if (xkb_x11_setup_xkb_extension(conn, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, 0, NULL, NULL, &xkb_base_event, &xkb_base_error) != 1) errx(EXIT_FAILURE, "Could not setup XKB extension."); static const xcb_xkb_map_part_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP); static const xcb_xkb_event_type_t required_events = (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY); xcb_xkb_select_events( conn, xkb_x11_get_core_keyboard_device_id(conn), required_events, 0, required_events, required_map_parts, required_map_parts, 0); /* When we cannot initially load the keymap, we better exit */ if (!load_keymap()) errx(EXIT_FAILURE, "Could not load keymap"); const char *locale = getenv("LC_ALL"); if (!locale) locale = getenv("LC_CTYPE"); if (!locale) locale = getenv("LANG"); if (!locale) { if (debug_mode) fprintf(stderr, "Can't detect your locale, fallback to C\n"); locale = "C"; } load_compose_table(locale); xinerama_init(); xinerama_query_screens(); screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; last_resolution[0] = screen->width_in_pixels; last_resolution[1] = screen->height_in_pixels; xcb_change_window_attributes(conn, screen->root, XCB_CW_EVENT_MASK, (uint32_t[]) { XCB_EVENT_MASK_STRUCTURE_NOTIFY }); if (image_path) { /* Create a pixmap to render on, fill it with the background color */ img = cairo_image_surface_create_from_png(image_path); /* In case loading failed, we just pretend no -i was specified. */ if (cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not load image \"%s\": %s\n", image_path, cairo_status_to_string(cairo_surface_status(img))); img = NULL; } } /* Pixmap on which the image is rendered to (if any) */ xcb_pixmap_t bg_pixmap = draw_image(last_resolution); /* open the fullscreen window, already with the correct pixmap in place */ win = open_fullscreen_window(conn, screen, color, bg_pixmap); xcb_free_pixmap(conn, bg_pixmap); pid_t pid = fork(); /* The pid == -1 case is intentionally ignored here: * While the child process is useful for preventing other windows from * popping up while i3lock blocks, it is not critical. */ if (pid == 0) { /* Child */ close(xcb_get_file_descriptor(conn)); raise_loop(win); exit(EXIT_SUCCESS); } cursor = create_cursor(conn, screen, win, curs_choice); grab_pointer_and_keyboard(conn, screen, cursor); /* Load the keymap again to sync the current modifier state. Since we first * loaded the keymap, there might have been changes, but starting from now, * we should get all key presses/releases due to having grabbed the * keyboard. */ (void)load_keymap(); /* Initialize the libev event loop. */ main_loop = EV_DEFAULT; if (main_loop == NULL) errx(EXIT_FAILURE, "Could not initialize libev. Bad LIBEV_FLAGS?\n"); struct ev_io *xcb_watcher = calloc(sizeof(struct ev_io), 1); struct ev_check *xcb_check = calloc(sizeof(struct ev_check), 1); struct ev_prepare *xcb_prepare = calloc(sizeof(struct ev_prepare), 1); ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ); ev_io_start(main_loop, xcb_watcher); ev_check_init(xcb_check, xcb_check_cb); ev_check_start(main_loop, xcb_check); ev_prepare_init(xcb_prepare, xcb_prepare_cb); ev_prepare_start(main_loop, xcb_prepare); /* Invoke the event callback once to catch all the events which were * received up until now. ev will only pick up new events (when the X11 * file descriptor becomes readable). */ ev_invoke(main_loop, xcb_check, 0); ev_loop(main_loop, 0); }
void replay_commandloop(int fd) { int key, move, count; char buf[BUFSZ], qbuf[BUFSZ]; nh_bool ret, firsttime = TRUE; struct nh_replay_info rinfo; struct nh_cmd_arg noarg; struct nh_cmd_desc *cmd; create_game_windows(); if (!nh_view_replay_start(fd, &curses_replay_windowprocs, &rinfo)) return; load_keymap(); while (1) { draw_msgwin(); curses_update_status(NULL); draw_sidebar(); draw_replay_info(&rinfo); if (firsttime) show_replay_help(); firsttime = FALSE; key = get_map_key(TRUE); switch (key) { /* step forward */ case KEY_RIGHT: case ' ': ret = nh_view_replay_step(&rinfo, REPLAY_FORWARD, 1); draw_replay_info(&rinfo); if (ret == FALSE) { key = curses_msgwin("You have reached the end of this game. " "Go back or press ESC to exit."); if (key == KEY_ESC) goto out; } break; /* step backward */ case KEY_LEFT: nh_view_replay_step(&rinfo, REPLAY_BACKWARD, 1); draw_replay_info(&rinfo); break; case KEY_ESC: goto out; case 'g': strncpy(qbuf, "What move do you want to jump to?", BUFSZ); if (rinfo.max_moves > 0) sprintf(qbuf + strlen(qbuf), " (Max: %d)", rinfo.max_moves); curses_getline(qbuf, buf); if (buf[0] == '\033' || !(move = atoi(buf))) break; nh_view_replay_step(&rinfo, REPLAY_GOTO, move); break; case KEY_F(12): /* timetest! */ if (allow_timetest()) timetest(fd, &rinfo); break; default: count = 0; noarg.argtype = CMD_ARG_NONE; cmd = keymap[key]; if (!cmd) break; if (cmd->flags & CMD_UI) handle_internal_cmd(&cmd, &noarg, &count); if (cmd) nh_command(cmd->name, count, &noarg); break; } } out: nh_view_replay_finish(); free_keymap(); destroy_game_windows(); cleanup_messages(); }
int main(int argc, char** argv) { const char* output = NULL; const char* input = NULL; enum { kUnspecified, kLoadBinary, kLoadText, kSaveText, kRestore, kCompile, kSaveHeader, } mode = kUnspecified; static struct option const kLongOptions[] = { {"output", required_argument, 0, 'o'}, {"dump", optional_argument, 0, 'd'}, {"load", optional_argument, 0, 'l'}, {"load-source", optional_argument, 0, 's'}, {"restore", no_argument, 0, 'r'}, {"compile", optional_argument, 0, 'c'}, {"header", optional_argument, 0, 'h'}, {"help", no_argument, 0, 'H'}, {NULL} }; int c; while ((c = getopt_long(argc, argv, "o:dblsrchH", kLongOptions, NULL)) != -1) { switch (c) { case 0: break; case 'o': output = optarg; break; case 'd': mode = kSaveText; input = optarg; break; case 'l': case 'b': mode = kLoadBinary; input = optarg; break; case 's': mode = kLoadText; input = optarg; break; case 'r': mode = kRestore; break; case 'c': mode = kCompile; input = optarg; break; case 'h': mode = kSaveHeader; input = optarg; break; case 'H': default: mode = kUnspecified; break; } } if (argc > optind && input == NULL) input = argv[optind]; BApplication* app = new BApplication("application/x-vnd.Haiku-keymap-cli"); Keymap keymap; switch (mode) { case kUnspecified: usage(); break; case kLoadBinary: case kLoadText: { load_keymap(keymap, input, mode == kLoadText); status_t status = keymap.SaveAsCurrent(); if (status != B_OK) { fprintf(stderr, "%s: error when saving as current: %s", sProgramName, strerror(status)); return 1; } printf("Key map loaded.\n"); break; } case kSaveText: { if (input == NULL) { status_t status = keymap.SetToCurrent(); if (status != B_OK) { fprintf(stderr, "%s: error while getting keymap: %s!\n", sProgramName, keymap_error(status)); return 1; } } else load_keymap(keymap, input, false); if (output != NULL) keymap.SaveAsSource(output); else keymap.SaveAsSource(stdout); break; } case kRestore: keymap.RestoreSystemDefault(); break; case kCompile: { load_keymap(keymap, input, true); if (output == NULL) output = "keymap.out"; status_t status = keymap.Save(output); if (status != B_OK) { fprintf(stderr, "%s: error saving \"%s\": %s\n", sProgramName, output, strerror(status)); return 1; } break; } case kSaveHeader: { load_keymap(keymap, input, true); if (output == NULL) output = "keymap.h"; status_t status = keymap.SaveAsCppHeader(output, input); if (status != B_OK) { fprintf(stderr, "%s: error saving \"%s\": %s\n", sProgramName, output, strerror(status)); return 1; } break; } } return 0; }
static void mainmenu(void) { int menuresult[1]; int n = 1, logoheight, i; const char *const *copybanner = nh_get_copyright_banner(); const char **nhlogo; char verstr[32]; nh_bool first = TRUE; snprintf(verstr, ARRAY_SIZE(verstr), "Version %d.%d.%d", VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL); #if defined(NETCLIENT) if (ui_flags.connection_only) { netgame(); return; } #endif load_keymap(); /* netgame() assumes the keymap isn't loaded */ while (n >= 0) { if (COLS >= 100) { nhlogo = nhlogo_large; logoheight = sizeof (nhlogo_large) / sizeof (nhlogo_large[0]); } else { nhlogo = nhlogo_small; logoheight = sizeof (nhlogo_small) / sizeof (nhlogo_small[0]); } wclear(basewin); wattron(basewin, A_BOLD | COLOR_PAIR(4)); for (i = 0; i < logoheight; i++) { wmove(basewin, i, (COLS - strlen(nhlogo[0])) / 2); if (nhlogo[i]) waddstr(basewin, nhlogo[i]); } wattroff(basewin, A_BOLD | COLOR_PAIR(4)); mvwaddstr(basewin, LINES - 3, 0, copybanner[0]); mvwaddstr(basewin, LINES - 2, 0, copybanner[1]); mvwaddstr(basewin, LINES - 1, 0, copybanner[2]); mvwaddstr(basewin, LINES - 4, COLS - strlen(verstr), verstr); wnoutrefresh(basewin); if (first) { network_motd(); first = FALSE; } menuresult[0] = EXITGAME; /* default action */ if (!override_hackdir) curses_display_menu_core( STATIC_MENULIST(mainmenu_items), NULL, PICK_ONE, menuresult, curses_menu_callback, 0, logoheight - 1, COLS, LINES - 3, FALSE, NULL, FALSE); else curses_display_menu_core( STATIC_MENULIST(mainmenu_items_noclient), NULL, PICK_ONE, menuresult, curses_menu_callback, 0, logoheight - 1, COLS, LINES - 3, FALSE, NULL, FALSE); if (*menuresult == CURSES_MENU_CANCELLED && !ui_flags.done_hup) continue; switch (menuresult[0]) { case NEWGAME: rungame(FALSE); break; case LOAD: loadgame(); break; case REPLAY: replay(); break; case OPTIONS: display_options(TRUE); break; #if defined(NETCLIENT) case NETWORK: free_keymap(); /* don't use the local keymap for server play */ netgame(); load_keymap(); break; #endif case TOPTEN: show_topten(NULL, -1, FALSE, FALSE); break; case EXITGAME: case CURSES_MENU_CANCELLED: /* in case of hangup */ n = -1; /* simulate menu cancel */ break; } } free_keymap(); }
nh_bool loadgame(void) { char buf[BUFSZ]; fnchar savedir[BUFSZ], filename[1024], **files; struct nh_menuitem *items; int size, icount, fd, i, n, ret, pick[1]; enum nh_log_status status; struct nh_game_info gi; if (!get_gamedir(SAVE_DIR, savedir)) { curses_raw_print("Could not find or create the save directory."); return FALSE; } files = list_gamefiles(savedir, &size); if (!size) { curses_msgwin("No saved games found."); return FALSE; } icount = 0; items = malloc(size * sizeof(struct nh_menuitem)); for (i = 0; i < size; i++) { fd = sys_open(files[i], O_RDWR, FILE_OPEN_MASK); status = nh_get_savegame_status(fd, &gi); close(fd); describe_game(buf, status, &gi); add_menu_item(items, size, icount, (status == LS_IN_PROGRESS) ? 0 : icount + 1, buf, 0, FALSE); } n = curses_display_menu(items, icount, "saved games", PICK_ONE, pick); free(items); filename[0] = '\0'; if (n > 0) fnncat(filename, files[pick[0]-1], sizeof(filename)/sizeof(fnchar)-1); for (i = 0; i < icount; i++) free(files[i]); free(files); if (n <= 0) return FALSE; fd = sys_open(filename, O_RDWR, FILE_OPEN_MASK); create_game_windows(); if (nh_restore_game(fd, NULL, FALSE) != GAME_RESTORED) { destroy_game_windows(); close(fd); if (curses_yn_function("Failed to load the save. Do you wish to delete the file?", "yn", 'n') == 'y') unlink(filename); return FALSE; } load_keymap(); /* need to load the keymap after the game has been started */ ret = commandloop(); free_keymap(); close(fd); destroy_game_windows(); cleanup_messages(); game_ended(ret, filename); return TRUE; }
int main(int argc, char *argv[]) { setlocale(LC_TIME, "ru_RU.UTF-8"); char *username; char *image_path = NULL; int ret; struct pam_conv conv = {conv_callback, NULL}; int curs_choice = CURS_NONE; int o; int optind = 0; struct option longopts[] = { {"version", no_argument, NULL, 'v'}, {"nofork", no_argument, NULL, 'n'}, {"beep", no_argument, NULL, 'b'}, {"dpms", no_argument, NULL, 'd'}, {"color", required_argument, NULL, 'c'}, {"pointer", required_argument, NULL , 'p'}, {"debug", no_argument, NULL, 0}, {"help", no_argument, NULL, 'h'}, {"no-unlock-indicator", no_argument, NULL, 'u'}, {"image", required_argument, NULL, 'i'}, {"tiling", no_argument, NULL, 't'}, {"auth-fail-command", required_argument, NULL, 'f'}, {"auth-done-command", required_argument, NULL, 'o'}, {NULL, no_argument, NULL, 0} }; if ((username = getenv("USER")) == NULL) errx(1, "USER environment variable not set, please set it.\n"); while ((o = getopt_long(argc, argv, "hvnbdc:p:ui:f:o:t", longopts, &optind)) != -1) { switch (o) { case 'v': errx(EXIT_SUCCESS, "version " VERSION " © 2010-2012 Michael Stapelberg"); case 'n': dont_fork = true; break; case 'b': beep = true; break; case 'd': dpms = true; break; case 'c': { char *arg = optarg; /* Skip # if present */ if (arg[0] == '#') arg++; if (strlen(arg) != 6 || sscanf(arg, "%06[0-9a-fA-F]", color) != 1) errx(1, "color is invalid, it must be given in 3-byte hexadecimal format: rrggbb\n"); break; } case 'u': unlock_indicator = false; break; case 'i': image_path = strdup(optarg); break; case 't': tile = true; break; case 'p': if (!strcmp(optarg, "win")) { curs_choice = CURS_WIN; } else if (!strcmp(optarg, "default")) { curs_choice = CURS_DEFAULT; } else { errx(1, "i3lock: Invalid pointer type given. Expected one of \"win\" or \"default\".\n"); } break; case 'f': shell_auth_fail_command = strdup(optarg); break; case 'o': shell_auth_done_command = strdup(optarg); break; case 'h': show_time = false; break; case 0: if (strcmp(longopts[optind].name, "debug") == 0) debug_mode = true; break; default: errx(1, "Syntax: i3lock [-v] [-n] [-b] [-d] [-c color] [-u] [-p win|default] [-h]" " [-i image.png] [-t] [-f command] [-o command]" ); } } /* We need (relatively) random numbers for highlighting a random part of * the unlock indicator upon keypresses. */ srand(time(NULL)); /* Initialize PAM */ ret = pam_start("i3lock", username, &conv, &pam_handle); if (ret != PAM_SUCCESS) errx(EXIT_FAILURE, "PAM: %s", pam_strerror(pam_handle, ret)); /* Using mlock() as non-super-user seems only possible in Linux. Users of other * operating systems should use encrypted swap/no swap (or remove the ifdef and * run i3lock as super-user). */ #if defined(__linux__) /* Lock the area where we store the password in memory, we don’t want it to * be swapped to disk. Since Linux 2.6.9, this does not require any * privileges, just enough bytes in the RLIMIT_MEMLOCK limit. */ if (mlock(password, sizeof(password)) != 0) err(EXIT_FAILURE, "Could not lock page in memory, check RLIMIT_MEMLOCK"); #endif /* Initialize connection to X11 */ if ((display = XOpenDisplay(NULL)) == NULL) errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?"); XSetEventQueueOwner(display, XCBOwnsEventQueue); conn = XGetXCBConnection(display); /* Double checking that connection is good and operatable with xcb */ if (xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "Could not connect to X11, maybe you need to set DISPLAY?"); /* When we cannot initially load the keymap, we better exit */ if (!load_keymap()) errx(EXIT_FAILURE, "Could not load keymap"); xinerama_init(); xinerama_query_screens(); /* if DPMS is enabled, check if the X server really supports it */ if (dpms) { xcb_dpms_capable_cookie_t dpmsc = xcb_dpms_capable(conn); xcb_dpms_capable_reply_t *dpmsr; if ((dpmsr = xcb_dpms_capable_reply(conn, dpmsc, NULL))) { if (!dpmsr->capable) { if (debug_mode) fprintf(stderr, "Disabling DPMS, X server not DPMS capable\n"); dpms = false; } free(dpmsr); } } screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; last_resolution[0] = screen->width_in_pixels; last_resolution[1] = screen->height_in_pixels; xcb_change_window_attributes(conn, screen->root, XCB_CW_EVENT_MASK, (uint32_t[]){ XCB_EVENT_MASK_STRUCTURE_NOTIFY }); if (image_path) { /* Create a pixmap to render on, fill it with the background color */ img = cairo_image_surface_create_from_png(image_path); /* In case loading failed, we just pretend no -i was specified. */ if (cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not load image \"%s\": cairo surface status %d\n", image_path, cairo_surface_status(img)); img = NULL; } } /* Pixmap on which the image is rendered to (if any) */ xcb_pixmap_t bg_pixmap = draw_image(last_resolution); /* open the fullscreen window, already with the correct pixmap in place */ win = open_fullscreen_window(conn, screen, color, bg_pixmap); xcb_free_pixmap(conn, bg_pixmap); cursor = create_cursor(conn, screen, win, curs_choice); grab_pointer_and_keyboard(conn, screen, cursor); if (dpms) dpms_turn_off_screen(conn); /* Initialize the libev event loop. */ main_loop = EV_DEFAULT; if (main_loop == NULL) errx(EXIT_FAILURE, "Could not initialize libev. Bad LIBEV_FLAGS?\n"); struct ev_io *xcb_watcher = calloc(sizeof(struct ev_io), 1); struct ev_check *xcb_check = calloc(sizeof(struct ev_check), 1); struct ev_prepare *xcb_prepare = calloc(sizeof(struct ev_prepare), 1); ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ); ev_io_start(main_loop, xcb_watcher); ev_check_init(xcb_check, xcb_check_cb); ev_check_start(main_loop, xcb_check); ev_prepare_init(xcb_prepare, xcb_prepare_cb); ev_prepare_start(main_loop, xcb_prepare); /* Invoke the event callback once to catch all the events which were * received up until now. ev will only pick up new events (when the X11 * file descriptor becomes readable). */ ev_invoke(main_loop, xcb_check, 0); if(show_time) start_time_redraw_tick(); ev_loop(main_loop, 0); }
/* * Called when the keyboard mapping changes. We update our symbols. * */ static void handle_mapping_notify(xcb_mapping_notify_event_t *event) { /* We ignore errors — if the new keymap cannot be loaded it’s better if the * screen stays locked and the user intervenes by using killall i3lock. */ (void)load_keymap(); }
int main(int argc, char **argv) { int i; char errbuf[128]; FILE *file; if (argc<2) { printf("usage: %s keymap\n", argv[0]); return 1; } file = fopen(argv[1], "rt"); if (!file) { printf("cannot open file %s\n", argv[1]); return 2; } if (load_keymap(file, errbuf, sizeof(errbuf))) { printf("load_keymap error: %s\n", errbuf); exit(1); } fclose(file); tcgetattr(0, &ts); ts0 = ts; cfmakeraw(&ts); tcsetattr(0, TCSANOW, &ts); atexit(exit_f); signal(SIGINT, sig_f); signal(SIGTERM, sig_f); signal(SIGHUP, sig_f); /* switch into scanmode */ printf("\033[S"); printf("\r\n"); for (i = 0; i < 100; i++) { unsigned char b; long key; int state; state = scan_state(); printf("\r\nstate: %d\r\n", state ); if (!read(0, &b, 1)) break; /*printf("read: %x\r\n", (int)b); */ key = scan_key(b); if (key) { state = scan_state(); printf("scan_key: %ld (%c), state=%d\r\n", key, (int) ((key > 32 && key < 256) ? key : 32), state); if (key == 'q') exit(0); } } return 0; }