Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/video_output/wayland/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 14 kB image not shown  

Quelle  input.c   Sprache: C

 

/**
 * @file input.c
 * @brief Wayland input events for VLC media player
 */

/*****************************************************************************
 * Copyright © 2018 Rémi Denis-Courmont
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <assert.h>
#include <inttypes.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/input-event-codes.h>
#include <wayland-client.h>
#ifdef HAVE_XKBCOMMON
# include <xkbcommon/xkbcommon.h>
# include "../xcb/vlc_xkb.h"
#endif
#include <vlc_common.h>
#include <vlc_threads.h>
#include <vlc_window.h>
#include <vlc_mouse.h>
#include <vlc_fs.h>

#include "input.h"

struct seat_data
{
    vlc_window_t *owner;
    struct wl_seat *seat;

    struct wl_pointer *pointer;
    vlc_tick_t cursor_timeout;
    vlc_tick_t cursor_deadline;
    uint32_t cursor_serial;

#ifdef HAVE_XKBCOMMON
    struct xkb_context *xkb;
    struct wl_keyboard *keyboard;
    struct xkb_keymap *keymap;
    struct xkb_state *keystate;
#endif

    uint32_t name;
    uint32_t version;
    struct wl_list node;
};

static void pointer_show(struct seat_data *sd, struct wl_pointer *pointer)
{
    int hsx, hsy;
    struct wl_surface *surface = window_get_cursor(sd->owner, &hsx, &hsy);

    if (surface != NULL)
    {
        wl_pointer_set_cursor(pointer, sd->cursor_serial, surface, hsx, hsy);
        sd->cursor_deadline = vlc_tick_now() + sd->cursor_timeout;
    }
}

static void pointer_enter_cb(void *data, struct wl_pointer *pointer,
                             uint32_t serial, struct wl_surface *surface,
                             wl_fixed_t sx, wl_fixed_t sy)
{
    struct seat_data *sd = data;

    sd->cursor_serial = serial;
    pointer_show(sd, pointer);
    (void) surface; (void) sx; (void) sy;
}

static void pointer_leave_cb(void *data, struct wl_pointer *pointer,
                             uint32_t serial, struct wl_surface *surface)
{
    (void) data; (void) pointer; (void) serial; (void) surface;
}

static void pointer_motion_cb(void *data, struct wl_pointer *pointer,
                              uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
{
    struct seat_data *sd = data;

    pointer_show(sd, pointer);
    vlc_window_ReportMouseMoved(sd->owner,
                                 wl_fixed_to_int(sx), wl_fixed_to_int(sy));
    (void) time;
}

static void pointer_button_cb(void *data, struct wl_pointer *pointer,
                              uint32_t serial, uint32_t time,
                              uint32_t keycode, uint32_t state)
{
    struct seat_data *sd = data;
    int button;

    pointer_show(sd, pointer);

    switch (keycode)
    {
        case BTN_LEFT:
            button = MOUSE_BUTTON_LEFT;
            break;
        case BTN_RIGHT:
            button = MOUSE_BUTTON_RIGHT;
            break;
        case BTN_MIDDLE:
            button = MOUSE_BUTTON_CENTER;
            break;
        default:
            return;
    }

    switch (state)
    {
        case WL_POINTER_BUTTON_STATE_RELEASED:
            vlc_window_ReportMouseReleased(sd->owner, button);
            break;
        case WL_POINTER_BUTTON_STATE_PRESSED:
            vlc_window_ReportMousePressed(sd->owner, button);
            break;
    }

    (void) serial; (void) time;
}

static void pointer_axis_cb(void *data, struct wl_pointer *pointer,
                            uint32_t serial, uint32_t type, wl_fixed_t value)
{
    struct seat_data *sd = data;
    vlc_window_t *wnd = sd->owner;
    int button;
    bool plus = value > 0;

    pointer_show(sd, pointer);
    value = abs(value);

    switch (type)
    {
        case WL_POINTER_AXIS_VERTICAL_SCROLL:
            button = plus ? MOUSE_BUTTON_WHEEL_DOWN : MOUSE_BUTTON_WHEEL_UP;
            break;
        case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
            button = plus ? MOUSE_BUTTON_WHEEL_RIGHT : MOUSE_BUTTON_WHEEL_LEFT;
            break;
        default:
            return;
    }

    while (value > 0)
    {
        vlc_window_ReportMousePressed(wnd, button);
        vlc_window_ReportMouseReleased(wnd, button);
        value -= wl_fixed_from_int(10);
    }
    (void) serial;
}

static void pointer_frame_cb(void *data, struct wl_pointer *pointer)
{
    (void) data; (void) pointer;
}

static void pointer_axis_source(void *data, struct wl_pointer *pointer,
                                uint32_t source)
{
    (void) data; (void) pointer; (void) source;
}

static void pointer_axis_stop(void *data, struct wl_pointer *pointer,
                              uint32_t time, uint32_t axis)
{
    (void) data; (void) pointer; (void) time; (void) axis;
}

static void pointer_axis_discrete(void *data, struct wl_pointer *pointer,
                                  uint32_t type, int steps)
{
    (void) data; (void) pointer; (void) type; (void) steps;
}

static const struct wl_pointer_listener pointer_cbs =
{
    pointer_enter_cb,
    pointer_leave_cb,
    pointer_motion_cb,
    pointer_button_cb,
    pointer_axis_cb,
    pointer_frame_cb,
    pointer_axis_source,
    pointer_axis_stop,
    pointer_axis_discrete,
#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
    NULL, /* We don't support axis_value120 for now */
#endif
#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION
    NULL, /* We don't support axis_relative_direction for now */
#endif
};

static void pointer_create(struct seat_data *sd)
{
    if (sd->pointer != NULL)
        return;

    sd->pointer = wl_seat_get_pointer(sd->seat);
    if (likely(sd->pointer != NULL))
        wl_pointer_add_listener(sd->pointer, &pointer_cbs, sd);

    sd->cursor_timeout = VLC_TICK_FROM_MS( var_InheritInteger(sd->owner, "mouse-hide-timeout") );
    sd->cursor_deadline = VLC_TICK_MAX;
}

static void pointer_destroy(struct seat_data *sd)
{
    if (sd->pointer == NULL)
        return;

    if (sd->version >= WL_POINTER_RELEASE_SINCE_VERSION)
        wl_pointer_release(sd->pointer);
    else
        wl_pointer_destroy(sd->pointer);

    sd->pointer = NULL;
}

#ifdef HAVE_XKBCOMMON
static void keyboard_keymap_cb(void *data, struct wl_keyboard *keyboard,
                               uint32_t format, int fd, uint32_t size)
{
    struct seat_data *sd = data;
    vlc_window_t *wnd = sd->owner;
    void *map;

    msg_Dbg(wnd, "format %"PRIu32" keymap of %"PRIu32" bytes", format, size);

    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
    {
        msg_Err(wnd, "unsupported keymap format %"PRIu32, format);
        goto out;
    }

    size++; /* trailing nul */

    map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED)
        goto out;

    assert(((char *)map)[size - 1] == '\0');
    sd->keymap = xkb_keymap_new_from_string(sd->xkb, map,
                                            XKB_KEYMAP_FORMAT_TEXT_V1,
                                            XKB_KEYMAP_COMPILE_NO_FLAGS);
    munmap(map, size);

    if (sd->keymap != NULL)
        sd->keystate = xkb_state_new(sd->keymap);
    else
        msg_Err(wnd, "keymap parse error");

out:
    vlc_close(fd);
    (void) keyboard;
}

static void keyboard_enter_cb(void *data, struct wl_keyboard *keyboard,
                              uint32_t serial, struct wl_surface *surface,
                              struct wl_array *keys)
{
    (void) data; (void) keyboard; (void) serial; (void) surface; (void) keys;
}

static void keyboard_leave_cb(void *data, struct wl_keyboard *keyboard,
                              uint32_t serial, struct wl_surface *surface)
{
    (void) data; (void) keyboard; (void) serial; (void) surface;}

static void keyboard_key_cb(void *data, struct wl_keyboard *keyboard,
                            uint32_t serial, uint32_t time, uint32_t keycode,
                            uint32_t state)
{
    struct seat_data *sd = data;
    vlc_window_t *wnd = sd->owner;
    uint_fast32_t vk;

    if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
        return;
    if (unlikely(sd->keystate == NULL))
        return;

    vk = vlc_xkb_get_one(sd->keystate, keycode + 8);
    if (vk)
    {
        msg_Dbg(wnd, "key: 0x%08"PRIxFAST32" (XKB: 0x%04"PRIx32")",
                vk, keycode);
        vlc_window_ReportKeyPress(wnd, vk);
    }

    (void) keyboard; (void) serial; (void) time;
}

static void keyboard_modifiers_cb(void *data, struct wl_keyboard *keyboard,
                                  uint32_t serial, uint32_t depressed,
                                  uint32_t latched, uint32_t locked,
                                  uint32_t group)
{
    struct seat_data *sd = data;

    if (unlikely(sd->keystate == NULL))
        return;

    xkb_state_update_mask(sd->keystate, depressed, latched, locked,
                          0, 0, group);

    (void) keyboard; (void) serial;
}

static void keyboard_repeat_info_cb(void *data, struct wl_keyboard *keyboard,
                                    int32_t rate, int32_t delay)
{
    struct seat_data *sd = data;
    vlc_window_t *wnd = sd->owner;

    msg_Dbg(wnd, "keyboard repeat info: %d Hz after %d ms", rate, delay);
    (void) keyboard;
}

static const struct wl_keyboard_listener keyboard_cbs =
{
    keyboard_keymap_cb,
    keyboard_enter_cb,
    keyboard_leave_cb,
    keyboard_key_cb,
    keyboard_modifiers_cb,
    keyboard_repeat_info_cb,
};

static void keyboard_create(struct seat_data *sd)
{
    if (sd->keyboard != NULL)
        return;

    sd->keyboard = wl_seat_get_keyboard(sd->seat);
    if (likely(sd->keyboard != NULL))
    {
        sd->keymap = NULL;
        wl_keyboard_add_listener(sd->keyboard, &keyboard_cbs, sd);
    }
}

static void keyboard_destroy(struct seat_data *sd)
{
    if (sd->keyboard == NULL)
        return;

    if (sd->version >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
        wl_keyboard_release(sd->keyboard);
    else
        wl_keyboard_destroy(sd->keyboard);

    if (sd->keymap != NULL)
    {
        if (sd->keystate != NULL)
            xkb_state_unref(sd->keystate);
        xkb_keymap_unref(sd->keymap);
    }

    sd->keyboard = NULL;
}
#endif /* HAVE_XKBCOMMON */

static void seat_capabilities_cb(void *data, struct wl_seat *seat,
                                 uint32_t capabilities)
{
    struct seat_data *sd = data;
    struct vlc_window *wnd = sd->owner;

    msg_Dbg(wnd, "seat capabilities: 0x%"PRIx32, capabilities);
    (void) seat;

    if (capabilities & WL_SEAT_CAPABILITY_POINTER)
    {
        if (var_InheritBool(wnd, "mouse-events"))
            pointer_create(sd);
    }
    else
        pointer_destroy(sd);

#ifdef HAVE_XKBCOMMON
    if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
    {
        if (sd->xkb != NULL)
            keyboard_create(sd);
    }
    else
        keyboard_destroy(sd);
#endif
}

static void seat_name_cb(void *data, struct wl_seat *seat, const char *name)
{
    struct seat_data *sd = data;

    msg_Dbg(sd->owner, "seat name: %s", name);
    (void) seat;
}

static const struct wl_seat_listener seat_cbs =
{
    seat_capabilities_cb,
    seat_name_cb,
};

int seat_create(vlc_window_t *wnd, struct wl_registry *registry,
                uint32_t name, uint32_t version, struct wl_list *list)
{
    struct seat_data *sd = malloc(sizeof (*sd));
    if (unlikely(sd == NULL))
        return -1;

    if (version > 5)
        version = 5;

    sd->seat = wl_registry_bind(registry, name, &wl_seat_interface, version);
    if (unlikely(sd->seat == NULL))
    {
        free(sd);
        return -1;
    }

    sd->owner = wnd;
    sd->pointer = NULL;
#ifdef HAVE_XKBCOMMON
    if (var_InheritBool(wnd, "keyboard-events"))
        sd->xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);

    sd->keyboard = NULL;
#endif
    sd->version = version;

    wl_seat_add_listener(sd->seat, &seat_cbs, sd);
    wl_list_insert(list, &sd->node);
    return 0;
}

static vlc_tick_t seat_next_deadline(const struct seat_data *sd)
{
    return (sd->pointer != NULL) ? sd->cursor_deadline : VLC_TICK_MAX;
}

static void seat_refresh(struct seat_data *sd, vlc_tick_t now)
{
    if (sd->pointer != NULL && sd->cursor_deadline <= now)
    {   /* Hide cursor */
        wl_pointer_set_cursor(sd->pointer, sd->cursor_serial, NULL, 0, 0);
        sd->cursor_deadline = VLC_TICK_MAX;
    }
}

static void seat_destroy(struct seat_data *sd)
{
    wl_list_remove(&sd->node);

#ifdef HAVE_XKBCOMMON
    keyboard_destroy(sd);

    if (sd->xkb != NULL)
        xkb_context_unref(sd->xkb);
#endif
    pointer_destroy(sd);

    if (sd->version >= WL_SEAT_RELEASE_SINCE_VERSION)
        wl_seat_release(sd->seat);
    else
        wl_seat_destroy(sd->seat);
    free(sd);
}

int seat_destroy_one(struct wl_list *list, uint32_t name)
{
    struct seat_data *sd;

    wl_list_for_each(sd, list, node)
    {
        if (sd->name == name)
        {
            seat_destroy(sd);
            /* Note: return here so no needs for safe walk variant */
            return 0;
        }
    }

    return -1;
}

void seat_destroy_all(struct wl_list *list)
{
    while (!wl_list_empty(list))
        seat_destroy(container_of(list->next, struct seat_data, node));
}

int seat_next_timeout(const struct wl_list *list)
{
    struct seat_data *sd;
    vlc_tick_t deadline = VLC_TICK_MAX;

    wl_list_for_each(sd, list, node)
    {
        vlc_tick_t d = seat_next_deadline(sd);
        if (deadline > d)
            deadline = d;
    }

    if (deadline == VLC_TICK_MAX)
        return -1;

    vlc_tick_t now = vlc_tick_now();
    if (now >= deadline)
        return 0;

    return (deadline - now) / 1000 + 1;
}

void seat_timeout(struct wl_list *list)
{
    struct seat_data *sd;
    vlc_tick_t now = vlc_tick_now();

    wl_list_for_each(sd, list, node)
        seat_refresh(sd, now);
}

Messung
CHZG
84979993

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.