KeyboardEvent.java

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
    и других спецификаций для функционирования компактных приложений на языке
    Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

    Copyright © 2016–2017, 2019–2023 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package malik.emulator.application;

public class KeyboardEvent extends InputEvent
{
    public static final int KEY_BACKSPACE     =   8;
    public static final int KEY_TAB           =   9;
    public static final int KEY_ENTER         =  13;
    public static final int KEY_SHIFT         =  16;
    public static final int KEY_CTRL          =  17;
    public static final int KEY_ALT           =  18;
    public static final int KEY_PAUSE_BREAK   =  19;
    public static final int KEY_CAPS_LOCK     =  20;
    public static final int KEY_ESCAPE        =  27;
    public static final int KEY_SPACE         =  32;
    public static final int KEY_PAGE_UP       =  33;
    public static final int KEY_PAGE_DOWN     =  34;
    public static final int KEY_END           =  35;
    public static final int KEY_HOME          =  36;
    public static final int KEY_LEFT          =  37;
    public static final int KEY_UP            =  38;
    public static final int KEY_RIGHT         =  39;
    public static final int KEY_DOWN          =  40;
    public static final int KEY_INSERT        =  45;
    public static final int KEY_DELETE        =  46;
    public static final int KEY_0             =  48;
    public static final int KEY_1             =  49;
    public static final int KEY_2             =  50;
    public static final int KEY_3             =  51;
    public static final int KEY_4             =  52;
    public static final int KEY_5             =  53;
    public static final int KEY_6             =  54;
    public static final int KEY_7             =  55;
    public static final int KEY_8             =  56;
    public static final int KEY_9             =  57;
    public static final int KEY_A             =  65;
    public static final int KEY_B             =  66;
    public static final int KEY_C             =  67;
    public static final int KEY_D             =  68;
    public static final int KEY_E             =  69;
    public static final int KEY_F             =  70;
    public static final int KEY_G             =  71;
    public static final int KEY_H             =  72;
    public static final int KEY_I             =  73;
    public static final int KEY_J             =  74;
    public static final int KEY_K             =  75;
    public static final int KEY_L             =  76;
    public static final int KEY_M             =  77;
    public static final int KEY_N             =  78;
    public static final int KEY_O             =  79;
    public static final int KEY_P             =  80;
    public static final int KEY_Q             =  81;
    public static final int KEY_R             =  82;
    public static final int KEY_S             =  83;
    public static final int KEY_T             =  84;
    public static final int KEY_U             =  85;
    public static final int KEY_V             =  86;
    public static final int KEY_W             =  87;
    public static final int KEY_X             =  88;
    public static final int KEY_Y             =  89;
    public static final int KEY_Z             =  90;
    public static final int KEY_CONTEXT       =  93;
    public static final int KEY_NUM_0         =  96;
    public static final int KEY_NUM_1         =  97;
    public static final int KEY_NUM_2         =  98;
    public static final int KEY_NUM_3         =  99;
    public static final int KEY_NUM_4         = 100;
    public static final int KEY_NUM_5         = 101;
    public static final int KEY_NUM_6         = 102;
    public static final int KEY_NUM_7         = 103;
    public static final int KEY_NUM_8         = 104;
    public static final int KEY_NUM_9         = 105;
    public static final int KEY_NUM_STAR      = 106;
    public static final int KEY_NUM_PLUS      = 107;
    public static final int KEY_NUM_SEPARATOR = 108;
    public static final int KEY_NUM_MINUS     = 109;
    public static final int KEY_NUM_DECIMAL   = 110;
    public static final int KEY_NUM_DIVIDE    = 111;
    public static final int KEY_F1            = 112;
    public static final int KEY_F2            = 113;
    public static final int KEY_F3            = 114;
    public static final int KEY_F4            = 115;
    public static final int KEY_F5            = 116;
    public static final int KEY_F6            = 117;
    public static final int KEY_F7            = 118;
    public static final int KEY_F8            = 119;
    public static final int KEY_F9            = 120;
    public static final int KEY_F10           = 121;
    public static final int KEY_F11           = 122;
    public static final int KEY_F12           = 123;
    public static final int KEY_F13           = 124;
    public static final int KEY_F14           = 125;
    public static final int KEY_F15           = 126;
    public static final int KEY_F16           = 127;
    public static final int KEY_F17           = 128;
    public static final int KEY_F18           = 129;
    public static final int KEY_F19           = 130;
    public static final int KEY_F20           = 131;
    public static final int KEY_F21           = 132;
    public static final int KEY_F22           = 133;
    public static final int KEY_F23           = 134;
    public static final int KEY_F24           = 135;
    public static final int KEY_NUM_LOCK      = 144;
    public static final int KEY_SCROLL_LOCK   = 145;
    public static final int KEY_LSHIFT        = 160;
    public static final int KEY_RSHIFT        = 161;
    public static final int KEY_LCTRL         = 162;
    public static final int KEY_RCTRL         = 163;
    public static final int KEY_LALT          = 164;
    public static final int KEY_RALT          = 165;
    public static final int KEY_SEMICOLON     = 186;
    public static final int KEY_EQUAL         = 187;
    public static final int KEY_COMMA         = 188;
    public static final int KEY_MINUS         = 189;
    public static final int KEY_PERIOD        = 190;
    public static final int KEY_SLASH         = 191;
    public static final int KEY_GRAVE         = 192;
    public static final int KEY_LBRACKET      = 219;
    public static final int KEY_BACKSLASH     = 220;
    public static final int KEY_RBRACKET      = 221;
    public static final int KEY_APOSTROPHE    = 222;
    public static final int ACTION_KEY_PRESSED  = Requestable.ACTION_KEY_PRESSED;
    public static final int ACTION_KEY_REPEATED = Requestable.ACTION_KEY_REPEATED;
    public static final int ACTION_KEY_RELEASED = Requestable.ACTION_KEY_RELEASED;
    private static final int OFFSET_KEY             = 0x01;
    private static final int OFFSET_CHAR            = 0x02;
    private static final int OFFSET_SOURCE          = 0x03;
    private static final int OFFSET_KEY_PRESSED     = 0x04;
    private static final int OFFSET_EVENT_TIME_LO   = 0x0c;
    private static final int OFFSET_EVENT_TIME_HI   = 0x0d;
    private static final int OFFSET_VIRTUAL_DATA_LO = 0x0e;
    private static final int OFFSET_VIRTUAL_DATA_HI = 0x0f;
    private static final int ELEMENTS_PER_STORY = 0x10;

    private int base;
    private int length;
    private final int[] history;

    public KeyboardEvent() {
        this(0x0100);
    }

    public KeyboardEvent(int historyCapacity) {
        if(historyCapacity < 0x0002) historyCapacity = 0x0002;
        if(historyCapacity > 0x1000) historyCapacity = 0x1000;
        this.base = (historyCapacity <<= 4) - ELEMENTS_PER_STORY;
        this.length = ELEMENTS_PER_STORY;
        this.history = new int[historyCapacity];
    }

    public int getSource() {
        return history[base + OFFSET_SOURCE];
    }

    public long getEventTime() {
        int b = base;
        int[] h = history;
        return (long) h[b + OFFSET_EVENT_TIME_LO] & 0x00000000ffffffffL | (long) h[b + OFFSET_EVENT_TIME_HI] << 32;
    }

    public long getVirtualData() {
        int b = base;
        int[] h = history;
        return (long) h[b + OFFSET_VIRTUAL_DATA_LO] & 0x00000000ffffffffL | (long) h[b + OFFSET_VIRTUAL_DATA_HI] << 32;
    }

    public void addStory(int action, int key, int charCode, InputDevice device, int source, long virtualData) {
        int[] history;
        if(action != ACTION_KEY_REPEATED && action != ACTION_KEY_PRESSED && action != ACTION_KEY_RELEASED)
        {
            throw new IllegalArgumentException("KeyboardEvent.addStory: аргумент action имеет недопустимое значение.");
        }
        synchronized(history = this.history)
        {
            int capacity = history.length;
            int oldBase = base;
            int newBase = base = (oldBase + capacity - ELEMENTS_PER_STORY) % capacity;
            int length = this.length;
            long time = System.currentTimeMillis();
            if(length < capacity) this.length = length + ELEMENTS_PER_STORY;
            Array.copy(history, oldBase + OFFSET_KEY_PRESSED, history, newBase + OFFSET_KEY_PRESSED, 8);
            if(key >= 0x00 && key <= 0xff)
            {
                int index = newBase + OFFSET_KEY_PRESSED + (key >> 5);
                int bitkey = 1 << key;
                if(action == ACTION_KEY_RELEASED)
                {
                    history[index] &= ~bitkey;
                }
                else if((history[index] & bitkey) != 0)
                {
                    action = ACTION_KEY_REPEATED;
                }
                else
                {
                    action = ACTION_KEY_PRESSED;
                    history[index] |= bitkey;
                }
            }
            this.device = device;
            history[newBase] = action;
            history[newBase + OFFSET_KEY] = key;
            history[newBase + OFFSET_CHAR] = charCode;
            history[newBase + OFFSET_SOURCE] = source;
            history[newBase + OFFSET_EVENT_TIME_LO] = (int) time;
            history[newBase + OFFSET_EVENT_TIME_HI] = (int) (time >> 32);
            history[newBase + OFFSET_VIRTUAL_DATA_LO] = (int) virtualData;
            history[newBase + OFFSET_VIRTUAL_DATA_HI] = (int) (virtualData >> 32);
        }
    }

    public boolean historicalFromSource(int storyIndex, int source) {
        int b;
        int[] h;
        if(storyIndex < 0 || storyIndex >= (length >> 4))
        {
            throw new IndexOutOfBoundsException("KeyboardEvent.historicalFromSource: аргумент storyIndex выходит из диапазона.");
        }
        h = history;
        b = (base + (storyIndex << 4)) % h.length;
        return (h[b + OFFSET_SOURCE] & source) == source;
    }

    public int historicalSource(int storyIndex) {
        int b;
        int[] h;
        if(storyIndex < 0 || storyIndex >= (length >> 4))
        {
            throw new IndexOutOfBoundsException("KeyboardEvent.historicalSource: аргумент storyIndex выходит из диапазона.");
        }
        h = history;
        b = (base + (storyIndex << 4)) % h.length;
        return h[b + OFFSET_SOURCE];
    }

    public long historicalEventTime(int storyIndex) {
        int b;
        int[] h;
        if(storyIndex < 0 || storyIndex >= (length >> 4))
        {
            throw new IndexOutOfBoundsException("KeyboardEvent.historicalEventTime: аргумент storyIndex выходит из диапазона.");
        }
        h = history;
        b = (base + (storyIndex << 4)) % h.length;
        return (long) h[b + OFFSET_EVENT_TIME_LO] & 0x00000000ffffffffL | (long) h[b + OFFSET_EVENT_TIME_HI] << 32;
    }

    public long historicalVirtualData(int storyIndex) {
        int b;
        int[] h;
        if(storyIndex < 0 || storyIndex >= (length >> 4))
        {
            throw new IndexOutOfBoundsException("KeyboardEvent.historicalVirtualData: аргумент storyIndex выходит из диапазона.");
        }
        h = history;
        b = (base + (storyIndex << 4)) % h.length;
        return (long) h[b + OFFSET_VIRTUAL_DATA_LO] & 0x00000000ffffffffL | (long) h[b + OFFSET_VIRTUAL_DATA_HI] << 32;
    }

    public final boolean isKeyPressed(int key) {
        return key >= 0x00 && key <= 0xff && (history[base + OFFSET_KEY_PRESSED + (key >> 5)] & (1 << key)) != 0;
    }

    public final boolean historicalKeyPressed(int storyIndex, int key) {
        int b;
        int[] h;
        if(storyIndex < 0 || storyIndex >= (length >> 4))
        {
            throw new IndexOutOfBoundsException("KeyboardEvent.historicalKeyPressed: аргумент storyIndex выходит из диапазона.");
        }
        h = history;
        b = (base + (storyIndex << 4)) % h.length;
        return key >= 0x00 && key <= 0xff && (h[b + OFFSET_KEY_PRESSED + (key >> 5)] & (1 << key)) != 0;
    }

    public final int historicalCharCode(int storyIndex) {
        int b;
        int[] h;
        if(storyIndex < 0 || storyIndex >= (length >> 4))
        {
            throw new IndexOutOfBoundsException("KeyboardEvent.historicalCharCode: аргумент storyIndex выходит из диапазона.");
        }
        h = history;
        b = (base + (storyIndex << 4)) % h.length;
        return h[b + OFFSET_CHAR];
    }

    public final int historicalAction(int storyIndex) {
        int b;
        int[] h;
        if(storyIndex < 0 || storyIndex >= (length >> 4))
        {
            throw new IndexOutOfBoundsException("KeyboardEvent.historicalAction: аргумент storyIndex выходит из диапазона.");
        }
        h = history;
        b = (base + (storyIndex << 4)) % h.length;
        return h[b];
    }

    public final int historicalKey(int storyIndex) {
        int b;
        int[] h;
        if(storyIndex < 0 || storyIndex >= (length >> 4))
        {
            throw new IndexOutOfBoundsException("KeyboardEvent.historicalKey: аргумент storyIndex выходит из диапазона.");
        }
        h = history;
        b = (base + (storyIndex << 4)) % h.length;
        return h[b + OFFSET_KEY];
    }

    public final int historyCapacity() {
        return history.length >> 4;
    }

    public final int historyLength() {
        return length >> 4;
    }

    public final int getCharCode() {
        return history[base + OFFSET_CHAR];
    }

    public final int getAction() {
        return history[base];
    }

    public final int getKey() {
        return history[base + OFFSET_KEY];
    }
}