static void
do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
{
    int i;
    xEvent core_mn;
    deviceMappingNotify xi_mn;

    /* The map in ButtonClassRec refers to button numbers, whereas the
     * protocol is zero-indexed.  Sigh. */
    memcpy(&(dev->button->map[1]), map, len);

    core_mn.u.u.type = MappingNotify;
    core_mn.u.mappingNotify.request = MappingPointer;

    /* 0 is the server client. */
    for (i = 1; i < currentMaxClients; i++) {
        /* Don't send irrelevant events to naïve clients. */
        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
            continue;

        if (!XIShouldNotify(clients[i], dev))
            continue;

        core_mn.u.u.sequenceNumber = clients[i]->sequence;
        WriteEventsToClient(clients[i], 1, &core_mn);
    }

    xi_mn.type = DeviceMappingNotify;
    xi_mn.request = MappingPointer;
    xi_mn.deviceid = dev->id;
    xi_mn.time = GetTimeInMillis();

    SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1);
}
示例#2
0
/*
 * This function sends out two kinds of notification:
 *   - Core mapping notify events sent to clients for whom kbd is the
 *     current core ('picked') keyboard _and_ have not explicitly
 *     selected for XKB mapping notify events;
 *   - Xi mapping events, sent unconditionally to all clients who have
 *     explicitly selected for them (including those who have explicitly
 *     selected for XKB mapping notify events!).
 */
static void
XkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed,
                       int first_key, int num_keys)
{
    int i;
    int keymap_changed = 0;
    int modmap_changed = 0;
    CARD32 time = GetTimeInMillis();

    if (xkb_event == XkbNewKeyboardNotify) {
        if (changed & XkbNKN_KeycodesMask) {
            keymap_changed = 1;
            modmap_changed = 1;
        }
    }
    else if (xkb_event == XkbMapNotify) {
        if (changed & XkbKeySymsMask)
            keymap_changed = 1;
        if (changed & XkbModifierMapMask)
            modmap_changed = 1;
    }
    if (!keymap_changed && !modmap_changed)
        return;

    /* 0 is serverClient. */
    for (i = 1; i < currentMaxClients; i++) {
        if (!clients[i] || clients[i]->clientState != ClientStateRunning)
            continue;

        /* XKB allows clients to restrict the MappingNotify events sent to
         * them.  This was broken for three years.  Sorry. */
        if (xkb_event == XkbMapNotify &&
            (clients[i]->xkbClientFlags & _XkbClientInitialized) &&
            !(clients[i]->mapNotifyMask & changed))
            continue;
        /* Emulate previous server behaviour: any client which has activated
         * XKB will not receive core events emulated from a NewKeyboardNotify
         * at all. */
        if (xkb_event == XkbNewKeyboardNotify &&
            (clients[i]->xkbClientFlags & _XkbClientInitialized))
            continue;

        /* Don't send core events to clients who don't know about us. */
        if (!XIShouldNotify(clients[i], kbd))
            continue;

        if (keymap_changed) {
            xEvent core_mn;
            core_mn.u.u.type = MappingNotify;
            core_mn.u.mappingNotify.request = MappingKeyboard;

            /* Clip the keycode range to what the client knows about, so it
             * doesn't freak out. */
            if (first_key >= clients[i]->minKC)
                core_mn.u.mappingNotify.firstKeyCode = first_key;
            else
                core_mn.u.mappingNotify.firstKeyCode = clients[i]->minKC;
            if (first_key + num_keys - 1 <= clients[i]->maxKC)
                core_mn.u.mappingNotify.count = num_keys;
            else
                core_mn.u.mappingNotify.count = clients[i]->maxKC -
                    clients[i]->minKC + 1;

            WriteEventsToClient(clients[i], 1, &core_mn);
        }
        if (modmap_changed) {
            xEvent core_mn;
            core_mn.u.mappingNotify.request = MappingModifier;
            core_mn.u.mappingNotify.firstKeyCode = 0;
            core_mn.u.mappingNotify.count = 0;
            core_mn.u.u.type = MappingNotify;
            WriteEventsToClient(clients[i], 1, &core_mn);
        }
    }

    /* Hmm, maybe we can accidentally generate Xi events for core devices
     * here? Clients might be upset, but that seems better than the
     * alternative of stale keymaps. -ds */
    if (keymap_changed) {
        deviceMappingNotify xi_mn;
        xi_mn.type = DeviceMappingNotify;
        xi_mn.deviceid = kbd->id;
        xi_mn.request = MappingKeyboard;
        xi_mn.firstKeyCode = first_key;
        xi_mn.count = num_keys;
        xi_mn.time = time;
        SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
                              1);
    }
    if (modmap_changed) {
        deviceMappingNotify xi_mn;
        xi_mn.type = DeviceMappingNotify;
        xi_mn.deviceid = kbd->id;
        xi_mn.request = MappingModifier;
        xi_mn.firstKeyCode = 0;
        xi_mn.count = 0;
        xi_mn.time = time;
        SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
                              1);
    }
}