/* * Instead of polling the X connection socket we leave this to * xcb_poll_for_event() which knows better than we can ever know. * */ static void xcb_check_cb(EV_P_ ev_check *w, int revents) { xcb_generic_event_t *event; while ((event = xcb_poll_for_event(conn)) != NULL) { if (event->response_type == 0) { xcb_generic_error_t *error = (xcb_generic_error_t*)event; if (debug_mode) fprintf(stderr, "X11 Error received! sequence 0x%x, error_code = %d\n", error->sequence, error->error_code); free(event); continue; } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_KEY_PRESS: handle_key_press((xcb_key_press_event_t*)event); break; case XCB_KEY_RELEASE: handle_key_release((xcb_key_release_event_t*)event); /* If this was the backspace or escape key we are back at an * empty input, so turn off the screen if DPMS is enabled */ if (dpms && input_position == 0) dpms_turn_off_screen(conn); break; case XCB_VISIBILITY_NOTIFY: handle_visibility_notify((xcb_visibility_notify_event_t*)event); break; case XCB_MAP_NOTIFY: if (!dont_fork) { /* After the first MapNotify, we never fork again. We don’t * expect to get another MapNotify, but better be sure… */ dont_fork = true; /* In the parent process, we exit */ if (fork() != 0) exit(0); ev_loop_fork(EV_DEFAULT); } break; case XCB_MAPPING_NOTIFY: handle_mapping_notify((xcb_mapping_notify_event_t*)event); break; case XCB_CONFIGURE_NOTIFY: handle_screen_resize(); break; } free(event); } }
static int on_event(struct rtb_element *elem, const struct rtb_event *e) { SELF_FROM(elem); switch (e->type) { case RTB_MOUSE_DOWN: case RTB_DRAG_START: return 1; case RTB_KEY_PRESS: if (handle_key_press(self, RTB_EVENT_AS(e, rtb_key_event))) return 1; break; case RTB_MOUSE_CLICK: if (RTB_EVENT_AS(e, rtb_mouse_event)->button != RTB_MOUSE_BUTTON1) return 0; return dispatch_click_event(self, RTB_EVENT_AS(e, rtb_mouse_event)); default: return super.on_event(elem, e); } return 0; }
/* * Instead of polling the X connection socket we leave this to * xcb_poll_for_event() which knows better than we can ever know. * */ static void xcb_check_cb(EV_P_ ev_check *w, int revents) { xcb_generic_event_t *event; while ((event = xcb_poll_for_event(conn)) != NULL) { if (event->response_type == 0) { xcb_generic_error_t *error = (xcb_generic_error_t*)event; if (debug_mode) fprintf(stderr, "X11 Error received! sequence 0x%x, error_code = %d\n", error->sequence, error->error_code); free(event); continue; } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_KEY_PRESS: handle_key_press((xcb_key_press_event_t*)event); break; case XCB_KEY_RELEASE: /* If this was the backspace or escape key we are back at an * empty input, so turn off the screen if DPMS is enabled, but * only do that after some timeout: maybe user mistyped and * will type again right away */ START_TIMER(dpms_timeout, TSTAMP_N_SECS(inactivity_timeout), turn_off_monitors_cb); break; case XCB_VISIBILITY_NOTIFY: handle_visibility_notify(conn, (xcb_visibility_notify_event_t*)event); break; case XCB_MAP_NOTIFY: if (!dont_fork) { /* After the first MapNotify, we never fork again. We don’t * expect to get another MapNotify, but better be sure… */ dont_fork = true; /* In the parent process, we exit */ if (fork() != 0) exit(0); ev_loop_fork(EV_DEFAULT); } break; case XCB_CONFIGURE_NOTIFY: handle_screen_resize(); break; default: if (type == xkb_base_event) process_xkb_event(event); } free(event); } }
/* * Run through one frame drawing cycle */ void SdlApp::step() { if (!running) return; draw_scene(); SDL_Event event; while ( SDL_PollEvent( &event ) ) { switch( event.type ) { case SDL_ACTIVEEVENT: //TODO: handle focus change break; case SDL_KEYDOWN: /* handle key presses */ handle_key_press( &event.key.keysym ); break; case SDL_QUIT: /* handle quit requests */ tear_down(); break; default: break; } } }
TaskResult Char(const KeyInfo& info) override{ auto handleKeyPress = [&](){ m_autoComplete.Forget(); return handle_key_press(info.key, m_textObject->GetTextBuffer()) ? TaskResult::DRAW : TaskResult::NONE; }; if (is_exit_key(info.key)){ return Commit(info.layerType); } else if (info.key.Is(key::tab) && m_settings.Get(ts_ParseExpressions)){ return handle_completion(m_autoComplete, m_textObject->GetTextBuffer()) ? TaskResult::DRAW : handleKeyPress(); } return handle_command_key(info.key, m_textObject).Visit( [&](TextChange& cmd){ m_autoComplete.Forget(); // Fixme: Need to support undo cmd.Do(); m_states.Did(cmd); return TaskResult::DRAW; }, handleKeyPress); }
/* process_character: [fdwatch thread] * This is where most of the work gets done. CH is a byte read in * from the keyboard's fd. This function finds the Allegro equivalent * of that key code, figures out which ASCII character that key * generates (if any), and then calls the handle_key_press() and * handle_key_release() functions with that information. It also does * some things with modifier keys. */ static void process_character(unsigned char ch) { /* read kernel's keycode and convert to Allegro's keycode */ int keycode = ch & 0x7f; bool press = !(ch & 0x80); int mycode = kernel_to_mycode[keycode]; /* if the key was something weird we don't understand, skip it */ if (mycode == 0) return; /* process modifiers */ if (mycode >= ALLEGRO_KEY_MODIFIERS) { int flag = modifier_table[mycode - ALLEGRO_KEY_MODIFIERS]; if (press) { if (flag & KB_MODIFIERS) the_keyboard.modifiers |= flag; else if ((flag & KB_LED_FLAGS) && the_keyboard.key_led_flag) the_keyboard.modifiers ^= flag; } else { /* XXX: if the user presses LCTRL, then RCTRL, then releases * LCTRL, the ALLEGRO_KEYMOD_CTRL modifier should still be on. */ if (flag & KB_MODIFIERS) the_keyboard.modifiers &= ~flag; } } /* call the handlers */ if (press) { int ascii = keycode_to_char(keycode); /* switch VT if the user requested so */ if (ascii < 0) { int console = -ascii; int last_console; ioctl(the_keyboard.fd, VT_OPENQRY, &last_console); if (console < last_console) if (ioctl(the_keyboard.fd, VT_ACTIVATE, console) == 0) return; } handle_key_press(mycode, ascii); } else { handle_key_release(mycode); } /* three-finger salute for killing the program */ if ((the_keyboard.three_finger_flag) && ((mycode == ALLEGRO_KEY_DELETE) || (mycode == ALLEGRO_KEY_END)) && (the_keyboard.modifiers & ALLEGRO_KEYMOD_CTRL) && (the_keyboard.modifiers & ALLEGRO_KEYMOD_ALT)) { kill(main_pid, SIGTERM); } }
/* * Instead of polling the X connection socket we leave this to * xcb_poll_for_event() which knows better than we can ever know. * */ static void xcb_check_cb(EV_P_ ev_check *w, int revents) { xcb_generic_event_t *event; if (xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "X11 connection broke, did your server terminate?\n"); while ((event = xcb_poll_for_event(conn)) != NULL) { if (event->response_type == 0) { xcb_generic_error_t *error = (xcb_generic_error_t *)event; if (debug_mode) fprintf(stderr, "X11 Error received! sequence 0x%x, error_code = %d\n", error->sequence, error->error_code); free(event); continue; } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_BUTTON_PRESS: handle_button_press((xcb_button_press_event_t *)event); break; case XCB_KEY_PRESS: handle_key_press((xcb_key_press_event_t *)event); break; case XCB_VISIBILITY_NOTIFY: handle_visibility_notify(conn, (xcb_visibility_notify_event_t *)event); break; case XCB_MAP_NOTIFY: if (!dont_fork) { /* After the first MapNotify, we never fork again. We don’t * expect to get another MapNotify, but better be sure… */ dont_fork = true; /* In the parent process, we exit */ if (fork() != 0) exit(0); ev_loop_fork(EV_DEFAULT); } break; case XCB_CONFIGURE_NOTIFY: handle_screen_resize(); break; default: if (type == xkb_base_event) process_xkb_event(event); } free(event); } }
/* key_dinput_handle_scancode: [input thread] * Handles a single scancode. */ static void key_dinput_handle_scancode(unsigned char scancode, int pressed) { HWND allegro_wnd = win_get_window(); static int ignore_three_finger_flag = FALSE; /* ignore special Windows keys (alt+tab, alt+space, (ctrl|alt)+esc) */ if (((scancode == DIK_TAB) && (_key_shifts & KB_ALT_FLAG)) || ((scancode == DIK_SPACE) && (_key_shifts & KB_ALT_FLAG)) || ((scancode == DIK_ESCAPE) && (_key_shifts & (KB_CTRL_FLAG | KB_ALT_FLAG)))) return; /* alt+F4 triggers a WM_CLOSE under Windows */ if ((scancode == DIK_F4) && (_key_shifts & KB_ALT_FLAG)) { if (pressed) PostMessage(allegro_wnd, WM_CLOSE, 0, 0); return; } /* Special case KEY_PAUSE as flip-flop key. */ if (scancode == DIK_PAUSE) { if (!pressed) return; if (key[KEY_PAUSE]) pressed = 0; else pressed = 1; } /* if not foreground, filter out press codes and handle only release codes */ if (!wnd_sysmenu || !pressed) { /* three-finger salute for killing the program */ if (three_finger_flag && (_key_shifts & KB_CTRL_FLAG) && (_key_shifts & KB_ALT_FLAG)) { if (scancode == 0x00) { /* when pressing CTRL-ALT-DEL, Windows launches CTRL-ALT-EVERYTHING */ ignore_three_finger_flag = TRUE; } else if (!ignore_three_finger_flag && (scancode == DIK_END || scancode == DIK_NUMPAD1)) { /* we can now safely assume the user hit CTRL-ALT-END as opposed to CTRL-ALT-DEL */ _TRACE(PREFIX_I "Terminating application\n"); abort(); } else if (ignore_three_finger_flag && scancode == 0xff) { /* Windows is finished with CTRL-ALT-EVERYTHING - lets return to normality */ ignore_three_finger_flag = FALSE; _key_shifts = 0; } } if (pressed) handle_key_press(scancode); else handle_key_release(scancode); } }
/* * Function: init_keyboard_handler() * Description: This function reads from the appropriate port on the keyboard to * receive the interrupts generated, parses this information, and * displays the associated character on the screen. * inputs: nothing * outputs: nothing * effects: prints character to screen from scancode_map */ void keyboard_interrupt_handler() { cli(); uint8_t c = 0; do { if (inb(KEYBOARD_DATA_PORT) != 0) { c = inb(KEYBOARD_DATA_PORT); if (c > 0) { break; } } } while(1); switch (c) { case LSHIFT_DOWN: case RSHIFT_DOWN: ENABLE_SHIFT(); break; case LSHIFT_UP: case RSHIFT_UP: DISABLE_SHIFT(); break; case CAPS_LOCK: TOGGLE_CAPS(); break; case BACKSPACE: handle_backspace(); break; case ENTER: handle_enter(); break; case CTRL_DOWN: ctrl_state = PRESSED; break; case CTRL_UP: ctrl_state = UNPRESSED; break; case ALT_DOWN: alt_state = PRESSED; break; case ALT_UP: alt_state = UNPRESSED; break; case F1_KEY: if (alt_state == PRESSED) { send_eoi(KEYBOARD_IRQ_LINE); launch_term(TERMINAL_ONE); } break; case F2_KEY: if (alt_state == PRESSED) { send_eoi(KEYBOARD_IRQ_LINE); launch_term(TERMINAL_TWO); } break; case F3_KEY: if (alt_state == PRESSED) { send_eoi(KEYBOARD_IRQ_LINE); launch_term(TERMINAL_THREE); } break; default: handle_key_press(c); break; } send_eoi(KEYBOARD_IRQ_LINE); sti(); }
/* * Instead of polling the X connection socket we leave this to * xcb_poll_for_event() which knows better than we can ever know. * */ static void xcb_check_cb(EV_P_ ev_check *w, int revents) { xcb_generic_event_t *event; if (xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "X11 connection broke, did your server terminate?\n"); while ((event = xcb_poll_for_event(conn)) != NULL) { if (event->response_type == 0) { xcb_generic_error_t *error = (xcb_generic_error_t *)event; /* Ignore errors when damage report is about destroyed window * or damage object is created for already destroyed window */ if (error->major_code == dam_ext_data->major_opcode && (error->minor_code == XCB_DAMAGE_SUBTRACT || error->minor_code == XCB_DAMAGE_CREATE)) { free(event); continue; } if (debug_mode) fprintf(stderr, "X11 Error received! sequence 0x%x, error_code " "= %d, major = 0x%x, minor = 0x%x\n", error->sequence, error->error_code, error->major_code, error->minor_code); free(event); continue; } if (fuzzy && event->response_type == dam_ext_data->first_event + XCB_DAMAGE_NOTIFY) { xcb_damage_notify_event_t *ev = (xcb_damage_notify_event_t *)event; xcb_damage_subtract(conn, ev->damage, XCB_NONE, XCB_NONE); redraw_screen(); } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_KEY_PRESS: handle_key_press((xcb_key_press_event_t *)event); break; case XCB_VISIBILITY_NOTIFY: handle_visibility_notify( conn, (xcb_visibility_notify_event_t *)event); break; case XCB_MAP_NOTIFY: handle_map_notify((xcb_map_notify_event_t *)event); break; case XCB_CONFIGURE_NOTIFY: handle_screen_resize(); break; default: if (type == xkb_base_event) process_xkb_event(event); } free(event); } }
/* _al_xwin_keyboard_handler: * Keyboard "interrupt" handler. */ void _al_xwin_keyboard_handler(XKeyEvent *event, ALLEGRO_DISPLAY *display) { int keycode; if (!xkeyboard_installed) return; keycode = keycode_to_scancode[event->keycode]; if (keycode == -1) keycode = find_unknown_key_assignment(event->keycode); update_shifts(event); /* Special case the pause key. */ if (keycode == ALLEGRO_KEY_PAUSE) { /* Allegro ignore's releasing of the pause key. */ if (event->type == KeyRelease) return; if (pause_key) { event->type = KeyRelease; pause_key = 0; } else { pause_key = 1; } } if (event->type == KeyPress) { /* Key pressed. */ int len; char buffer[16]; int unicode = 0; int filtered = 0; #if defined (ALLEGRO_XWINDOWS_WITH_XIM) && defined(X_HAVE_UTF8_STRING) if (xic) { len = Xutf8LookupString(xic, event, buffer, sizeof buffer, NULL, NULL); } else #endif { /* XLookupString is supposed to only use ASCII. */ len = XLookupString(event, buffer, sizeof buffer, NULL, NULL); } buffer[len] = '\0'; ALLEGRO_USTR_INFO info; const ALLEGRO_USTR *ustr = al_ref_cstr(&info, buffer); unicode = al_ustr_get(ustr, 0); if (unicode < 0) unicode = 0; #ifdef ALLEGRO_XWINDOWS_WITH_XIM ALLEGRO_DISPLAY_XGLX *glx = (void *)display; filtered = XFilterEvent((XEvent *)event, glx->window); #endif if (keycode || unicode) { handle_key_press(keycode, unicode, filtered, _key_shifts, display); } } else { /* Key release. */ /* HACK: * Detect key repeat by looking forward to see if this release is * followed by a press event, in which case we assume that this release * event was generated in response to that key press event. Events are * simultaneous if they are separated by less than 4 ms (a value that * worked well on one machine where this hack was needed). * * This is unnecessary on systems where XkbSetDetectableAutorepeat works. */ if (XPending(event->display) > 0) { ALLEGRO_KEY_REPEAT_DATA d; XEvent dummy; d.event = event; d.found = false; XCheckIfEvent(event->display, &dummy, check_for_repeat, (XPointer)&d); if (d.found) { return; } } handle_key_release(keycode, display); } }
int main(int argc, char * argv[]) { int i; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0) { show_help(argc, argv); return 0; } else if (strcmp(argv[i], "-res") == 0) { show_resources(); return 0; } } init_appres(argc, argv); the_bar.realized = 0; if (!get_display_info() || !init_resources() || !create_main_window()) exit (1); set_signals(); XMapWindow(gdi.display, gdi.mainw); set_keybindings(); XEvent evt; while (1) { XNextEvent(gdi.display, &evt); #ifdef DEBUG printf("wid %08X\t%s\n", (int)(evt.xany.window), event_names[evt.type]); fflush(stdout); #endif switch(evt.type){ case KeyPress: handle_key_press(&evt); break; case ReparentNotify: handle_reparent(&evt); break; case MapRequest: /* add a new tab */ handle_maprequest(&evt); break; case DestroyNotify: /* remove a tab */ handle_destroy(&evt); break; case ConfigureNotify: handle_configure_notify(&evt); break; case ConfigureRequest: handle_configure_request(&evt); break; case Expose: if (evt.xexpose.window != gdi.mainw) bar_handle_expose(&(evt.xexpose)); break; case ButtonPress: bar_handle_button(&(evt.xbutton)); break; case PropertyNotify: bar_handle_prop(&evt); break; case MapNotify: if (evt.xmap.window == gdi.mainw) { if (init_stage == 0) { init_stage ++; spawn_xterm(); } } break; case UnmapNotify: if (the_bar.tab_group.tab_count == 0) exit(0); break; case EnterNotify: set_focus(); break; default: break; } XFlush(gdi.display); }; return 0; }
/* * Creates the config file and tells i3 to reload. * */ static void finish() { printf("creating \"%s\"...\n", config_path); if (!(dpy = XOpenDisplay(NULL))) errx(1, "Could not connect to X11"); FILE *kc_config = fopen(SYSCONFDIR "/i3/config.keycodes", "r"); if (kc_config == NULL) err(1, "Could not open input file \"%s\"", SYSCONFDIR "/i3/config.keycodes"); FILE *ks_config = fopen(config_path, "w"); if (ks_config == NULL) err(1, "Could not open output config file \"%s\"", config_path); free(config_path); char *line = NULL; size_t len = 0; #ifndef USE_FGETLN ssize_t read; #endif bool head_of_file = true; /* write a header about auto-generation to the output file */ fputs("# This file has been auto-generated by i3-config-wizard(1).\n", ks_config); fputs("# It will not be overwritten, so edit it as you like.\n", ks_config); fputs("#\n", ks_config); fputs("# Should you change your keyboard layout somewhen, delete\n", ks_config); fputs("# this file and re-run i3-config-wizard(1).\n", ks_config); fputs("#\n", ks_config); #ifdef USE_FGETLN char *buf = NULL; while ((buf = fgetln(kc_config, &len)) != NULL) { /* fgetln does not return null-terminated strings */ FREE(line); sasprintf(&line, "%.*s", len, buf); #else size_t linecap = 0; while ((read = getline(&line, &linecap, kc_config)) != -1) { len = strlen(line); #endif /* skip the warning block at the beginning of the input file */ if (head_of_file && strncmp("# WARNING", line, strlen("# WARNING")) == 0) continue; head_of_file = false; /* Skip leading whitespace */ char *walk = line; while (isspace(*walk) && walk < (line + len)) { /* Pre-output the skipped whitespaces to keep proper indentation */ fputc(*walk, ks_config); walk++; } /* Set the modifier the user chose */ if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) { if (modifier == MOD_Mod1) fputs("set $mod Mod1\n", ks_config); else fputs("set $mod Mod4\n", ks_config); continue; } /* Check for 'bindcode'. If it’s not a bindcode line, we * just copy it to the output file */ if (strncmp(walk, "bindcode", strlen("bindcode")) != 0) { fputs(walk, ks_config); continue; } char *result = rewrite_binding(walk); fputs(result, ks_config); free(result); } /* sync to do our best in order to have the file really stored on disk */ fflush(ks_config); fsync(fileno(ks_config)); #ifndef USE_FGETLN free(line); #endif fclose(kc_config); fclose(ks_config); /* tell i3 to reload the config file */ int sockfd = ipc_connect(socket_path); ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t*)"reload"); close(sockfd); exit(0); } int main(int argc, char *argv[]) { config_path = resolve_tilde("~/.i3/config"); socket_path = getenv("I3SOCK"); char *pattern = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1"; char *patternbold = "-misc-fixed-bold-r-normal--13-120-75-75-C-70-iso10646-1"; int o, option_index = 0; static struct option long_options[] = { {"socket", required_argument, 0, 's'}, {"version", no_argument, 0, 'v'}, {"limit", required_argument, 0, 'l'}, {"prompt", required_argument, 0, 'P'}, {"prefix", required_argument, 0, 'p'}, {"font", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; char *options_string = "s:vh"; while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) { switch (o) { case 's': FREE(socket_path); socket_path = strdup(optarg); break; case 'v': printf("i3-config-wizard " I3_VERSION "\n"); return 0; case 'h': printf("i3-config-wizard " I3_VERSION "\n"); printf("i3-config-wizard [-s <socket>] [-v]\n"); return 0; } } /* Check if the destination config file does not exist but the path is * writable. If not, exit now, this program is not useful in that case. */ struct stat stbuf; if (stat(config_path, &stbuf) == 0) { printf("The config file \"%s\" already exists. Exiting.\n", config_path); return 0; } /* Create ~/.i3 if it does not yet exist */ char *config_dir = resolve_tilde("~/.i3"); if (stat(config_dir, &stbuf) != 0) if (mkdir(config_dir, 0755) == -1) err(1, "mkdir(%s) failed", config_dir); free(config_dir); int fd; if ((fd = open(config_path, O_CREAT | O_RDWR, 0644)) == -1) { printf("Cannot open file \"%s\" for writing: %s. Exiting.\n", config_path, strerror(errno)); return 0; } close(fd); unlink(config_path); if (socket_path == NULL) socket_path = root_atom_contents("I3_SOCKET_PATH"); if (socket_path == NULL) socket_path = "/tmp/i3-ipc.sock"; int screens; if ((conn = xcb_connect(NULL, &screens)) == NULL || xcb_connection_has_error(conn)) errx(1, "Cannot open display\n"); xcb_get_modifier_mapping_cookie_t modmap_cookie; modmap_cookie = xcb_get_modifier_mapping(conn); symbols = xcb_key_symbols_alloc(conn); /* Place requests for the atoms we need as soon as possible */ #define xmacro(atom) \ xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom); #include "atoms.xmacro" #undef xmacro root_screen = xcb_aux_get_screen(conn, screens); root = root_screen->root; if (!(modmap_reply = xcb_get_modifier_mapping_reply(conn, modmap_cookie, NULL))) errx(EXIT_FAILURE, "Could not get modifier mapping\n"); xcb_numlock_mask = get_mod_mask_for(XCB_NUM_LOCK, symbols, modmap_reply); font = load_font(pattern, true); bold_font = load_font(patternbold, true); /* Open an input window */ win = xcb_generate_id(conn); xcb_create_window( conn, XCB_COPY_FROM_PARENT, win, /* the window id */ root, /* parent == root */ 490, 297, 300, 205, /* dimensions */ 0, /* X11 border = 0, we draw our own */ XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, (uint32_t[]){ 0, /* back pixel: black */ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS }); /* Map the window (make it visible) */ xcb_map_window(conn, win); /* Setup NetWM atoms */ #define xmacro(name) \ do { \ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \ if (!reply) \ errx(EXIT_FAILURE, "Could not get atom " # name "\n"); \ \ A_ ## name = reply->atom; \ free(reply); \ } while (0); #include "atoms.xmacro" #undef xmacro /* Set dock mode */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, A__NET_WM_WINDOW_TYPE, A_ATOM, 32, 1, (unsigned char*) &A__NET_WM_WINDOW_TYPE_DIALOG); /* Set window title */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3: first configuration"), "i3: first configuration"); /* Create pixmap */ pixmap = xcb_generate_id(conn); pixmap_gc = xcb_generate_id(conn); xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, 500, 500); xcb_create_gc(conn, pixmap_gc, pixmap, 0, 0); /* Grab the keyboard to get all input */ xcb_flush(conn); /* Try (repeatedly, if necessary) to grab the keyboard. We might not * get the keyboard at the first attempt because of the keybinding * still being active when started via a wm’s keybinding. */ xcb_grab_keyboard_cookie_t cookie; xcb_grab_keyboard_reply_t *reply = NULL; int count = 0; while ((reply == NULL || reply->status != XCB_GRAB_STATUS_SUCCESS) && (count++ < 500)) { cookie = xcb_grab_keyboard(conn, false, win, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); reply = xcb_grab_keyboard_reply(conn, cookie, NULL); usleep(1000); } if (reply->status != XCB_GRAB_STATUS_SUCCESS) { fprintf(stderr, "Could not grab keyboard, status = %d\n", reply->status); exit(-1); } xcb_flush(conn); xcb_generic_event_t *event; while ((event = xcb_wait_for_event(conn)) != NULL) { if (event->response_type == 0) { fprintf(stderr, "X11 Error received! sequence %x\n", event->sequence); continue; } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_KEY_PRESS: handle_key_press(NULL, conn, (xcb_key_press_event_t*)event); break; /* TODO: handle mappingnotify */ case XCB_BUTTON_PRESS: handle_button_press((xcb_button_press_event_t*)event); break; case XCB_EXPOSE: handle_expose(); break; } free(event); } return 0; }
void keypress(XEvent* event) { HSDebug("name is: KeyPress\n"); handle_key_press(event); }
int main(int argc, char *argv[]) { struct spwd *sp = getspnam(getenv("USER")); if (!sp) { fprintf(stderr, "Get password failed\n"); return EXIT_FAILURE; } char *password = sp->sp_pwdp; // Parse command line parameters. struct arguments arguments = { .radius = 16, .iterations = 2, }; argp_parse(&argp, argc, argv, 0, NULL, &arguments); // Connect to X11. xcb_connection_t *conn = xcb_connect(NULL, NULL); const xcb_setup_t *setup = xcb_get_setup(conn); xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); xcb_screen_t *screen = iter.data; // Initialize keyboard stuff. Keyboard keyboard = { .conn = conn, }; init_keyboard(&keyboard); // Take a screenshot and blur it. xcb_image_t *screenshot = take_screenshot(conn, screen); blur_image(screenshot, arguments.radius, arguments.iterations); // Create window. xcb_window_t window = create_window(conn, screen, screenshot); if (!grab_inputs(conn, screen)) { fprintf(stderr, "Failed to grab keyboard and pointer.\n"); exit(EXIT_FAILURE); } xcb_map_window(conn, window); // Original screenshot image is not needed anymore because it's copied to the X server as pixmap. xcb_image_destroy(screenshot); xcb_flush(conn); // XXX: Max password length? char input[256] = { '\0' }; char *cursor = &input[0]; running = true; xcb_generic_event_t *event; while (running && (event = xcb_wait_for_event(conn))) { switch (event->response_type & ~0x80) { case XCB_EXPOSE: break; case XCB_KEY_PRESS: if (handle_key_press(&keyboard, ((xcb_key_press_event_t *)event)->detail, input, &cursor)) { if (strcmp(crypt(input, password), password) == 0) { running = false; } else { input[0] = '\0'; cursor = &input[0]; } } break; default: if (event->response_type == keyboard.first_xkb_event) { process_keyboard_event(&keyboard, event); } break; } free(event); } free_keyboard(&keyboard); xcb_unmap_window(conn, window); xcb_destroy_window(conn, window); xcb_disconnect(conn); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { format = sstrdup("%s"); char *socket_path = NULL; char *pattern = sstrdup("pango:monospace 8"); int o, option_index = 0; static struct option long_options[] = { {"socket", required_argument, 0, 's'}, {"version", no_argument, 0, 'v'}, {"limit", required_argument, 0, 'l'}, {"prompt", required_argument, 0, 'P'}, {"prefix", required_argument, 0, 'p'}, {"format", required_argument, 0, 'F'}, {"font", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; char *options_string = "s:p:P:f:l:F:vh"; while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) { switch (o) { case 's': FREE(socket_path); socket_path = sstrdup(optarg); break; case 'v': printf("i3-input " I3_VERSION); return 0; case 'p': /* This option is deprecated, but will still work in i3 v4.1, 4.2 and 4.3 */ fprintf(stderr, "i3-input: WARNING: the -p option is DEPRECATED in favor of the -F (format) option\n"); FREE(format); sasprintf(&format, "%s%%s", optarg); break; case 'l': limit = atoi(optarg); break; case 'P': i3string_free(prompt); prompt = i3string_from_utf8(optarg); break; case 'f': FREE(pattern); pattern = sstrdup(optarg); break; case 'F': FREE(format); format = sstrdup(optarg); break; case 'h': printf("i3-input " I3_VERSION "\n"); printf("i3-input [-s <socket>] [-F <format>] [-l <limit>] [-P <prompt>] [-f <font>] [-v]\n"); printf("\n"); printf("Example:\n"); printf(" i3-input -F 'workspace \"%%s\"' -P 'Switch to workspace: '\n"); return 0; } } printf("using format \"%s\"\n", format); int screen; conn = xcb_connect(NULL, &screen); if (!conn || xcb_connection_has_error(conn)) die("Cannot open display\n"); sockfd = ipc_connect(socket_path); root_screen = xcb_aux_get_screen(conn, screen); root = root_screen->root; symbols = xcb_key_symbols_alloc(conn); init_dpi(); font = load_font(pattern, true); set_font(&font); if (prompt != NULL) prompt_offset = predict_text_width(prompt); const xcb_rectangle_t win_pos = get_window_position(); /* Open an input window */ win = xcb_generate_id(conn); xcb_create_window( conn, XCB_COPY_FROM_PARENT, win, /* the window id */ root, /* parent == root */ win_pos.x, win_pos.y, win_pos.width, win_pos.height, /* dimensions */ 0, /* X11 border = 0, we draw our own */ XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, (uint32_t[]){ 0, /* back pixel: black */ 1, /* override redirect: don’t manage this window */ XCB_EVENT_MASK_EXPOSURE}); /* Map the window (make it visible) */ xcb_map_window(conn, win); /* Initialize the drawable surface */ draw_util_surface_init(conn, &surface, win, get_visualtype(root_screen), win_pos.width, win_pos.height); /* Grab the keyboard to get all input */ xcb_flush(conn); /* Try (repeatedly, if necessary) to grab the keyboard. We might not * get the keyboard at the first attempt because of the keybinding * still being active when started via a wm’s keybinding. */ xcb_grab_keyboard_cookie_t cookie; xcb_grab_keyboard_reply_t *reply = NULL; int count = 0; while ((reply == NULL || reply->status != XCB_GRAB_STATUS_SUCCESS) && (count++ < 500)) { cookie = xcb_grab_keyboard(conn, false, win, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); reply = xcb_grab_keyboard_reply(conn, cookie, NULL); usleep(1000); } if (reply->status != XCB_GRAB_STATUS_SUCCESS) { fprintf(stderr, "Could not grab keyboard, status = %d\n", reply->status); exit(-1); } xcb_flush(conn); xcb_generic_event_t *event; while ((event = xcb_wait_for_event(conn)) != NULL) { if (event->response_type == 0) { fprintf(stderr, "X11 Error received! sequence %x\n", event->sequence); continue; } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_KEY_PRESS: handle_key_press(NULL, conn, (xcb_key_press_event_t *)event); break; case XCB_KEY_RELEASE: handle_key_release(NULL, conn, (xcb_key_release_event_t *)event); break; case XCB_EXPOSE: if (((xcb_expose_event_t *)event)->count == 0) { handle_expose(NULL, conn, (xcb_expose_event_t *)event); } break; } free(event); } draw_util_surface_free(conn, &surface); return 0; }