Example #1
0
static void
send_property_event(DeviceIntPtr dev, Atom property, int what)
{
    devicePropertyNotify event;
    xXIPropertyEvent xi2;
    int state;

    if (what == XIPropertyDeleted)
        state = PropertyDelete;
    else
        state = PropertyNewValue;

    event.type = DevicePropertyNotify;
    event.deviceid = dev->id;
    event.state = state;
    event.atom = property;
    event.time = currentTime.milliseconds;
    SendEventToAllWindows(dev, DevicePropertyNotifyMask, (xEvent *) &event, 1);

    xi2.type = GenericEvent;
    xi2.extension = IReqCode;
    xi2.length = 0;
    xi2.evtype = XI_PropertyEvent;
    xi2.deviceid = dev->id;
    xi2.time = currentTime.milliseconds;
    xi2.property = property;
    xi2.what = what;
    SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent *) &xi2),
                          (xEvent *) &xi2, 1);
}
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);
}
Example #3
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);
    }
}
int
ProcXChangeDeviceControl(ClientPtr client)
{
    unsigned len;
    int i, status, ret = BadValue;
    DeviceIntPtr dev;
    xDeviceResolutionCtl *r;
    xChangeDeviceControlReply rep;
    AxisInfoPtr a;
    CARD32 *resolution;
    xDeviceEnableCtl *e;

    REQUEST(xChangeDeviceControlReq);
    REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq);

    len = stuff->length - bytes_to_int32(sizeof(xChangeDeviceControlReq));
    ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess);
    if (ret != Success)
        goto out;

    rep = (xChangeDeviceControlReply) {
        .repType = X_Reply,
        .RepType = X_ChangeDeviceControl,
        .sequenceNumber = client->sequence,
        .length = 0
    };

    switch (stuff->control) {
    case DEVICE_RESOLUTION:
        r = (xDeviceResolutionCtl *) &stuff[1];
        if ((len < bytes_to_int32(sizeof(xDeviceResolutionCtl))) ||
            (len !=
             bytes_to_int32(sizeof(xDeviceResolutionCtl)) + r->num_valuators)) {
            ret = BadLength;
            goto out;
        }
        if (!dev->valuator) {
            ret = BadMatch;
            goto out;
        }
        if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client)) {
            rep.status = AlreadyGrabbed;
            ret = Success;
            goto out;
        }
        resolution = (CARD32 *) (r + 1);
        if (r->first_valuator + r->num_valuators > dev->valuator->numAxes) {
            ret = BadValue;
            goto out;
        }
        status = ChangeDeviceControl(client, dev, (xDeviceCtl *) r);
        if (status == Success) {
            a = &dev->valuator->axes[r->first_valuator];
            for (i = 0; i < r->num_valuators; i++)
                if (*(resolution + i) < (a + i)->min_resolution ||
                    *(resolution + i) > (a + i)->max_resolution)
                    return BadValue;
            for (i = 0; i < r->num_valuators; i++)
                (a++)->resolution = *resolution++;

            ret = Success;
        }
        else if (status == DeviceBusy) {
            rep.status = DeviceBusy;
            ret = Success;
        }
        else {
            ret = BadMatch;
        }
        break;
    case DEVICE_ABS_CALIB:
    case DEVICE_ABS_AREA:
        /* Calibration is now done through properties, and never had any effect
         * on anything (in the open-source world). Thus, be honest. */
        ret = BadMatch;
        break;
    case DEVICE_CORE:
        /* Sorry, no device core switching no more. If you want a device to
         * send core events, attach it to a master device */
        ret = BadMatch;
        break;
    case DEVICE_ENABLE:
        e = (xDeviceEnableCtl *) &stuff[1];

        status = ChangeDeviceControl(client, dev, (xDeviceCtl *) e);

        if (status == Success) {
            if (e->enable)
                EnableDevice(dev, TRUE);
            else
                DisableDevice(dev, TRUE);
            ret = Success;
        }
        else if (status == DeviceBusy) {
            rep.status = DeviceBusy;
            ret = Success;
        }
        else {
            ret = BadMatch;
        }

        break;
    default:
        ret = BadValue;
    }

 out:
    if (ret == Success) {
        devicePresenceNotify dpn = {
            .type = DevicePresenceNotify,
            .time = currentTime.milliseconds,
            .devchange = DeviceControlChanged,
            .deviceid = dev->id,
            .control = stuff->control
        };
        SendEventToAllWindows(dev, DevicePresenceNotifyMask,
                              (xEvent *) &dpn, 1);

        WriteReplyToClient(client, sizeof(xChangeDeviceControlReply), &rep);
    }

    return ret;
}

/***********************************************************************
 *
 * This procedure writes the reply for the xChangeDeviceControl function,
 * if the client and server have a different byte ordering.
 *
 */

void
SRepXChangeDeviceControl(ClientPtr client, int size,
                         xChangeDeviceControlReply * rep)
{
    swaps(&rep->sequenceNumber);
    swapl(&rep->length);
    WriteToClient(client, size, rep);
}