Пример #1
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:
                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);
    }
}
Пример #2
0
/* 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);
   }
}
Пример #3
0
/* 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);
   }
}
Пример #4
0
int wikilib_run(void)
{
	int sleep;
	long time_now;
	struct wl_input_event ev;
	int more_events = 0;
	unsigned long last_event_time = 0;
	int rc;


	/*
	 * test searching code...
	 */
	article_buf_pointer = NULL;
	search_init();
	history_list_init();
	malloc_status_simple();
	print_intro();
#ifndef INCLUDED_FROM_KERNEL
	if (!load_init_article(idx_init_article))
	{
		display_mode = DISPLAY_MODE_ARTICLE;
		last_display_mode = DISPLAY_MODE_INDEX;
	}
#endif
	render_string(SUBTITLE_FONT_IDX, -1, 55, MESSAGE_TYPE_A_WORD, strlen(MESSAGE_TYPE_A_WORD), 0);

	for (;;) {
		if (more_events)
			sleep = 0;
		else
		sleep = 1;
		if (!more_events && display_mode == DISPLAY_MODE_ARTICLE && render_article_with_pcf())
			sleep = 0;
		else if (!more_events && display_mode == DISPLAY_MODE_INDEX && render_search_result_with_pcf())
			sleep = 0;
		else if (!more_events && display_mode == DISPLAY_MODE_HISTORY && render_history_with_pcf())
			sleep = 0;
		if (finger_move_speed != 0)
		{
			scroll_article();
			sleep = 0;
		}

#ifdef INCLUDED_FROM_KERNEL
		time_now = get_time_ticks();
		if(display_mode == DISPLAY_MODE_INDEX)
		{
		    if (press_delete_button && get_search_string_len()>0)
		    {
			 sleep = 0;
			 if(time_diff(time_now, start_search_time) > seconds_to_ticks(3.5))
			 {
			     if (!clear_search_string())
			     {
				search_string_changed_remove = true;
				search_reload_ex(SEARCH_RELOAD_NORMAL);
			     }
			     press_delete_button = false;
			 }
			 else if (time_diff(time_now, start_search_time) > seconds_to_ticks(0.5) &&
				time_diff(time_now, last_delete_time) > seconds_to_ticks(0.25))
			 {
			     if (!search_remove_char(0))
			     {
				     search_string_changed_remove = true;
				     search_reload_ex(SEARCH_RELOAD_NO_POPULATE);
			     }
			     last_delete_time = time_now;
			 }
		    }
		}
		else if (display_mode == DISPLAY_MODE_RESTRICTED)
		{
		    if (press_delete_button && get_password_string_len()>0)
		    {
			 sleep = 0;
			 time_now = get_time_ticks();
			 if(time_diff(time_now, start_search_time) > seconds_to_ticks(3.5))
			 {
			     clear_password_string();
			     press_delete_button = false;
			 }
			 else if (time_diff(time_now, start_search_time) > seconds_to_ticks(0.5) &&
				time_diff(time_now, last_delete_time) > seconds_to_ticks(0.25))
			 {
			     password_remove_char();
			     last_delete_time = time_now;
			 }
		    }
		}

#endif

		if (!more_events && display_mode == DISPLAY_MODE_INDEX && fetch_search_result(0, 0, 0))
		{
		    sleep = 0;
		}

		if (keyboard_key_reset_invert(KEYBOARD_RESET_INVERT_CHECK)) // check if need to reset invert
			sleep = 0;

		if (check_invert_link()) // check if need to invert link
			sleep = 0;

		if (sleep)
		{
			if (time_diff(get_time_ticks(), last_event_time) > seconds_to_ticks(15))
				rc = history_list_save(HISTORY_SAVE_POWER_OFF);
			else
				rc = history_list_save(HISTORY_SAVE_NORMAL);
			if (rc > 0)
			{
#ifdef INCLUDED_FROM_KERNEL
				delay_us(200000); // for some reason, save may not work if no delay
#endif
			}
			else if (rc < 0)
				sleep = 0; // waiting for last_event_time timeout to save the history
		}

		wl_input_wait(&ev, sleep);
		more_events = 1;
		switch (ev.type) {
		case WL_INPUT_EV_TYPE_CURSOR:
			handle_cursor(&ev);
			last_event_time = get_time_ticks();
			break;
		case WL_INPUT_EV_TYPE_KEYBOARD:
			if (ev.key_event.value != 0)
			{
				b_show_scroll_bar = 0;
				handle_key_release(ev.key_event.keycode);
			}
			last_event_time = get_time_ticks();
			break;
		case WL_INPUT_EV_TYPE_TOUCH:
			handle_touch(&ev);
			last_event_time = ev.touch_event.ticks;
			break;
		default:
			more_events = 0;
			break;
		}
	}

	/* never reached */
	return 0;
}
Пример #5
0
/* _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);
    }
}
Пример #6
0
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;
}