Exemple #1
0
static void keyboard_handle_key(void *data,
                                struct wl_keyboard *wl_keyboard,
                                uint32_t serial,
                                uint32_t time,
                                uint32_t key,
                                uint32_t state)
{
    struct vo_wayland_state *wl = data;
    uint32_t code, num_syms;
    int mpkey;

    const xkb_keysym_t *syms;
    xkb_keysym_t sym;

    code = key + 8;
    num_syms = xkb_key_get_syms(wl->input.xkb.state, code, &syms);

    sym = XKB_KEY_NoSymbol;
    if (num_syms == 1)
        sym = syms[0];

    if (sym != XKB_KEY_NoSymbol && (mpkey = lookupkey(sym))) {
        if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
            mp_input_put_key(wl->vo->input_ctx, mpkey | MP_KEY_STATE_DOWN);
        else
            mp_input_put_key(wl->vo->input_ctx, mpkey | MP_KEY_STATE_UP);
    }
}
Exemple #2
0
static void read_input(void)
{
    DWORD retval;
    HANDLE in = GetStdHandle(STD_INPUT_HANDLE);

    /*check if there are input events*/
    if (!GetNumberOfConsoleInputEvents(in, &retval))
        return;
    if (!retval)
        return;

    /*read all events*/
    INPUT_RECORD eventbuffer[128];
    if (!ReadConsoleInput(in, eventbuffer, MP_ARRAY_SIZE(eventbuffer), &retval))
        return;

    /*filter out keyevents*/
    for (int i = 0; i < retval; i++) {
        switch (eventbuffer[i].EventType) {
        case KEY_EVENT: {
            KEY_EVENT_RECORD *record = &eventbuffer[i].Event.KeyEvent;

            /*only a pressed key is interesting for us*/
            if (record->bKeyDown) {
                UINT vkey = record->wVirtualKeyCode;
                bool ext = record->dwControlKeyState & ENHANCED_KEY;

                int mpkey = mp_w32_vkey_to_mpkey(vkey, ext);
                if (mpkey) {
                    mp_input_put_key(input_ctx, mpkey);
                } else {
                    /*only characters should be remaining*/
                    int c = record->uChar.UnicodeChar;
                    if (c > 0)
                        mp_input_put_key(input_ctx, c);
                }
            }
            break;
        }
        case MOUSE_EVENT:
        case WINDOW_BUFFER_SIZE_EVENT:
        case FOCUS_EVENT:
        case MENU_EVENT:
        default:
            break;
        }
    }
    return;
}
Exemple #3
0
/**
 * \brief Dispatch incoming window events and handle them.
 *
 * This function should be placed inside libvo's function "check_events".
 *
 * \return int with these flags possibly set, take care to handle in the right order
 *         if it matters in your driver:
 *
 * VO_EVENT_RESIZE = The window was resized. If necessary reinit your
 *                   driver render context accordingly.
 * VO_EVENT_EXPOSE = The window was exposed. Call e.g. flip_frame() to redraw
 *                   the window if the movie is paused.
 */
int vo_w32_check_events(struct vo *vo)
{
    struct vo_w32_state *w32 = vo->w32;
    MSG msg;
    w32->event_flags = 0;
    while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }
    if (vo->opts->WinID >= 0) {
        BOOL res;
        RECT r;
        POINT p;
        res = GetClientRect(w32->window, &r);
        if (res && (r.right != vo->dwidth || r.bottom != vo->dheight)) {
            vo->dwidth = r.right; vo->dheight = r.bottom;
            w32->event_flags |= VO_EVENT_RESIZE;
        }
        p.x = 0; p.y = 0;
        ClientToScreen(w32->window, &p);
        if (p.x != w32->window_x || p.y != w32->window_y) {
            w32->window_x = p.x; w32->window_y = p.y;
        }
        res = GetClientRect(WIN_ID_TO_HWND(vo->opts->WinID), &r);
        if (res && (r.right != vo->dwidth || r.bottom != vo->dheight))
            MoveWindow(w32->window, 0, 0, r.right, r.bottom, FALSE);
        if (!IsWindow(WIN_ID_TO_HWND(vo->opts->WinID)))
            // Window has probably been closed, e.g. due to program crash
            mp_input_put_key(vo->input_ctx, MP_KEY_CLOSE_WIN);
    }

    return w32->event_flags;
}
Exemple #4
0
static void pointer_handle_leave(void *data,
                                 struct wl_pointer *pointer,
                                 uint32_t serial,
                                 struct wl_surface *surface)
{
    struct vo_wayland_state *wl = data;
    mp_input_put_key(wl->vo->input_ctx, MP_KEY_MOUSE_LEAVE);
}
Exemple #5
0
static void pointer_handle_button(void *data,
                                  struct wl_pointer *pointer,
                                  uint32_t serial,
                                  uint32_t time,
                                  uint32_t button,
                                  uint32_t state)
{
    struct vo_wayland_state *wl = data;

    mp_input_put_key(wl->vo->input_ctx, MP_MOUSE_BTN0 + (button - BTN_LEFT) |
                    ((state == WL_POINTER_BUTTON_STATE_PRESSED)
                    ? MP_KEY_STATE_DOWN : MP_KEY_STATE_UP));

    if ((button == BTN_LEFT) && (state == WL_POINTER_BUTTON_STATE_PRESSED))
        wl_shell_surface_move(wl->window.shell_surface, wl->input.seat, serial);
}
Exemple #6
0
/* POINTER LISTENER */
static void pointer_handle_enter(void *data,
                                 struct wl_pointer *pointer,
                                 uint32_t serial,
                                 struct wl_surface *surface,
                                 wl_fixed_t sx_w,
                                 wl_fixed_t sy_w)
{
    struct vo_wayland_state *wl = data;

    wl->cursor.serial = serial;
    wl->cursor.pointer = pointer;

    /* Release the left button on pointer enter again
     * because after moving the shell surface no release event is sent */
    mp_input_put_key(wl->vo->input_ctx, MP_MOUSE_BTN0 | MP_KEY_STATE_UP);
    show_cursor(wl);
}
Exemple #7
0
bool getch2(struct input_ctx *input_ctx)
{
    int retval = read(0, &getch2_buf[getch2_pos], BUF_LEN - getch2_len - getch2_pos);
    /* Return false on EOF to stop running select() on the FD, as it'd
     * trigger all the time. Note that it's possible to get temporary
     * EOF on terminal if the user presses ctrl-d, but that shouldn't
     * happen if the terminal state change done in getch2_enable()
     * works.
     */
    if (retval == 0)
        return false;
    if (retval == -1)
        return errno != EBADF && errno != EINVAL;
    getch2_len += retval;

    while (getch2_pos < getch2_len) {
        unsigned char c = getch2_buf[getch2_pos++];

        switch (state) {
            case STATE_INITIAL: {
                int match_count = keys_count_matches(&getch2_buf[0], getch2_len);
                if (match_count == 1) {
                    keycode_st *st = keys_search(&getch2_buf[0], getch2_len);

                    if (st) {
                        mp_input_put_key(input_ctx, st->code);
                        walk_buf(st->len);
                    } /* else this is still a partial (but unique) match */

                    continue;
                } else if (match_count > 1) {
                    continue; /* need more bytes to disambiguate */
                } else {
                    /* backtrack, send as UTF-8 */
                    getch2_pos = 1;
                    c = getch2_buf[0];
                }
                utf8_len = bstr_parse_utf8_code_length(c);

                if (utf8_len > 1) {
                    state = STATE_UTF8;
                } else if (utf8_len == 1) {
                    switch (c) {
                    case 0x1b: /* ESC that's not part of escape sequence */
                        /* only if ESC was typed twice, otherwise ignore it */
                        if (getch2_len > 1 && getch2_buf[1] == 0x1b) {
                            walk_buf(1); /* eat the second ESC */
                            mp_input_put_key(input_ctx, MP_KEY_ESC);
                        }
                        break;
                    default:
                        mp_input_put_key(input_ctx, c);
                    }
                    walk_buf(1);
                } else
                    walk_buf(getch2_pos);

                break;
            }
            case STATE_UTF8: {
                if (getch2_pos < utf8_len) /* need more bytes */
                    continue;

                struct bstr s = {getch2_buf, utf8_len};
                int unicode = bstr_decode_utf8(s, NULL);

                if (unicode > 0) {
                    mp_input_put_key(input_ctx, unicode);
                }
                walk_buf(utf8_len);
                state = STATE_INITIAL;
                continue;
            }
        }
    }

    return true;
}
Exemple #8
0
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
                                LPARAM lParam)
{
    if (message == WM_NCCREATE) {
        CREATESTRUCT *cs = (void*)lParam;
        SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams);
    }
    struct vo *vo = (void*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
    // message before WM_NCCREATE, pray to Raymond Chen that it's not important
    if (!vo)
        return DefWindowProcW(hWnd, message, wParam, lParam);
    struct vo_w32_state *w32 = vo->w32;
    int mouse_button = 0;

    switch (message) {
        case WM_ERASEBKGND: // no need to erase background seperately
            return 1;
        case WM_PAINT:
            w32->event_flags |= VO_EVENT_EXPOSE;
            break;
        case WM_MOVE: {
            POINT p = {0};
            ClientToScreen(w32->window, &p);
            w32->window_x = p.x;
            w32->window_y = p.y;
            MP_VERBOSE(vo, "move window: %d:%d\n",
                   w32->window_x, w32->window_y);
            break;
        }
        case WM_SIZE: {
            w32->event_flags |= VO_EVENT_RESIZE;
            RECT r;
            GetClientRect(w32->window, &r);
            vo->dwidth = r.right;
            vo->dheight = r.bottom;
            MP_VERBOSE(vo, "resize window: %d:%d\n",
                   vo->dwidth, vo->dheight);
            break;
        }
        case WM_SIZING:
            if (vo->opts->keepaspect && !vo->opts->fullscreen &&
                vo->opts->WinID < 0)
            {
                RECT *rc = (RECT*)lParam;
                // get client area of the windows if it had the rect rc
                // (subtracting the window borders)
                RECT r = *rc;
                subtract_window_borders(w32->window, &r);
                int c_w = r.right - r.left, c_h = r.bottom - r.top;
                float aspect = w32->o_dwidth / (float) MPMAX(w32->o_dheight, 1);
                int d_w = c_h * aspect - c_w;
                int d_h = c_w / aspect - c_h;
                int d_corners[4] = { d_w, d_h, -d_w, -d_h };
                int corners[4] = { rc->left, rc->top, rc->right, rc->bottom };
                int corner = get_resize_border(wParam);
                if (corner >= 0)
                    corners[corner] -= d_corners[corner];
                *rc = (RECT) { corners[0], corners[1], corners[2], corners[3] };
                return TRUE;
            }
            break;
        case WM_CLOSE:
            mp_input_put_key(vo->input_ctx, MP_KEY_CLOSE_WIN);
            break;
        case WM_SYSCOMMAND:
            switch (wParam) {
            case SC_SCREENSAVE:
            case SC_MONITORPOWER:
                if (w32->disable_screensaver) {
                    MP_VERBOSE(vo, "win32: killing screensaver\n");
                    return 0;
                }
                break;
            }
            break;
        case WM_KEYDOWN:
        case WM_SYSKEYDOWN: {
            int mpkey = lookup_keymap_table(vk_map, wParam);
            if (mpkey)
                mp_input_put_key(vo->input_ctx, mpkey | mod_state(vo));
            if (wParam == VK_F10)
                return 0;
            break;
        }
        case WM_CHAR:
        case WM_SYSCHAR: {
            int mods = mod_state(vo);
            int code = wParam;
            // Windows enables Ctrl+Alt when AltGr (VK_RMENU) is pressed.
            // E.g. AltGr+9 on a German keyboard would yield Ctrl+Alt+[
            // Warning: wine handles this differently. Don't test this on wine!
            if (key_state(vo, VK_RMENU) && mp_input_use_alt_gr(vo->input_ctx))
                mods &= ~(MP_KEY_MODIFIER_CTRL | MP_KEY_MODIFIER_ALT);
            // Apparently Ctrl+A to Ctrl+Z is special cased, and produces
            // character codes from 1-26. Work it around.
            // Also, enter/return (including the keypad variant) and CTRL+J both
            // map to wParam==10. As a workaround, check VK_RETURN to
            // distinguish these two key combinations.
            if ((mods & MP_KEY_MODIFIER_CTRL) && code >= 1 && code <= 26
                && !key_state(vo, VK_RETURN))
                code = code - 1 + (mods & MP_KEY_MODIFIER_SHIFT ? 'A' : 'a');
            if (code >= 32 && code < (1<<21)) {
                mp_input_put_key(vo->input_ctx, code | mods);
                // At least with Alt+char, not calling DefWindowProcW stops
                // Windows from emitting a beep.
                return 0;
            }
            break;
        }
        case WM_SETCURSOR:
            if (LOWORD(lParam) == HTCLIENT && !w32->cursor_visible) {
                SetCursor(NULL);
                return TRUE;
            }
            break;
        case WM_MOUSELEAVE:
            w32->tracking = FALSE;
            mp_input_put_key(vo->input_ctx, MP_KEY_MOUSE_LEAVE);
            break;
        case WM_MOUSEMOVE: {
            if (!w32->tracking)
                w32->tracking = TrackMouseEvent(&w32->trackEvent);
            // Windows can send spurious mouse events, which would make the mpv
            // core unhide the mouse cursor on completely unrelated events. See:
            //  https://blogs.msdn.com/b/oldnewthing/archive/2003/10/01/55108.aspx
            int x = GET_X_LPARAM(lParam);
            int y = GET_Y_LPARAM(lParam);
            if (x != w32->mouse_x || y != w32->mouse_y) {
                w32->mouse_x = x;
                w32->mouse_y = y;
                vo_mouse_movement(vo, x, y);
            }
            break;
        }
        case WM_LBUTTONDOWN:
            mouse_button = MP_MOUSE_BTN0 | MP_KEY_STATE_DOWN;
            break;
        case WM_LBUTTONUP:
            mouse_button = MP_MOUSE_BTN0 | MP_KEY_STATE_UP;
            break;
        case WM_MBUTTONDOWN:
            mouse_button = MP_MOUSE_BTN1 | MP_KEY_STATE_DOWN;
            break;
        case WM_MBUTTONUP:
            mouse_button = MP_MOUSE_BTN1 | MP_KEY_STATE_UP;
            break;
        case WM_RBUTTONDOWN:
            mouse_button = MP_MOUSE_BTN2 | MP_KEY_STATE_DOWN;
            break;
        case WM_RBUTTONUP:
            mouse_button = MP_MOUSE_BTN2 | MP_KEY_STATE_UP;
            break;
        case WM_MOUSEWHEEL: {
            int x = GET_WHEEL_DELTA_WPARAM(wParam);
            mouse_button = x > 0 ? MP_MOUSE_BTN3 : MP_MOUSE_BTN4;
            break;
        }
        case WM_XBUTTONDOWN:
            mouse_button = HIWORD(wParam) == 1 ? MP_MOUSE_BTN5 : MP_MOUSE_BTN6;
            mouse_button |= MP_KEY_STATE_DOWN;
            break;
        case WM_XBUTTONUP:
            mouse_button = HIWORD(wParam) == 1 ? MP_MOUSE_BTN5 : MP_MOUSE_BTN6;
            mouse_button |= MP_KEY_STATE_UP;
            break;
    }

    if (mouse_button && vo->opts->enable_mouse_movements) {
        int x = GET_X_LPARAM(lParam);
        int y = GET_Y_LPARAM(lParam);
        mouse_button |= mod_state(vo);
        if (mouse_button == (MP_MOUSE_BTN0 | MP_KEY_STATE_DOWN) &&
            !vo->opts->fullscreen && !mp_input_test_dragging(vo->input_ctx, x, y))
        {
            // Window dragging hack
            ReleaseCapture();
            SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
            return 0;
        }
        mp_input_put_key(vo->input_ctx, mouse_button);
    }

    return DefWindowProcW(hWnd, message, wParam, lParam);
}
Exemple #9
0
static void check_events(struct vo *vo)
{
    caca_event_t cev;
    while (caca_get_event(display, CACA_EVENT_ANY, &cev, 0)) {

        switch (cev.type) {
        case CACA_EVENT_RESIZE:
            caca_refresh_display(display);
            resize();
            break;
        case CACA_EVENT_QUIT:
            mp_input_put_key(vo->input_ctx, MP_KEY_CLOSE_WIN);
            break;
        case CACA_EVENT_MOUSE_MOTION:
            vo_mouse_movement(vo, cev.data.mouse.x, cev.data.mouse.y);
            break;
        case CACA_EVENT_MOUSE_PRESS:
            if (!vo->opts->nomouse_input)
                mp_input_put_key(vo->input_ctx,
                    (MP_MOUSE_BTN0 + cev.data.mouse.button - 1) | MP_KEY_STATE_DOWN);
            break;
        case CACA_EVENT_MOUSE_RELEASE:
            if (!vo->opts->nomouse_input)
                mp_input_put_key(vo->input_ctx,
                    (MP_MOUSE_BTN0 + cev.data.mouse.button - 1) | MP_KEY_STATE_UP);
            break;
        case CACA_EVENT_KEY_PRESS:
        {
            int key = cev.data.key.ch;
            int mpkey = lookup_keymap_table(keysym_map, key);
            const char *msg_name;

            if (mpkey)
                mp_input_put_key(vo->input_ctx, mpkey);
            else
            switch (key) {
            case 'd':
            case 'D':
                /* Toggle dithering algorithm */
                set_next_str(caca_get_dither_algorithm_list(dither),
                             &dither_algo, &msg_name);
                caca_set_dither_algorithm(dither, dither_algo);
                break;

            case 'a':
            case 'A':
                /* Toggle antialiasing method */
                set_next_str(caca_get_dither_antialias_list(dither),
                             &dither_antialias, &msg_name);
                caca_set_dither_antialias(dither, dither_antialias);
                break;

            case 'h':
            case 'H':
                /* Toggle charset method */
                set_next_str(caca_get_dither_charset_list(dither),
                             &dither_charset, &msg_name);
                caca_set_dither_charset(dither, dither_charset);
                break;

            case 'c':
            case 'C':
                /* Toggle color method */
                set_next_str(caca_get_dither_color_list(dither),
                             &dither_color, &msg_name);
                caca_set_dither_color(dither, dither_color);
                break;

            default:
                if (key <= 255)
                    mp_input_put_key(vo->input_ctx, key);
                break;
            }
        }
        }
    }
}