123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570 |
- #include <precomp.h>
- #include "keyboard.h"
- #include <api/locales/localesmgr.h>
- //#include <api/wac/main.h> // CUT !!!
- #include <api/script/objects/systemobj.h>
- #include <api/wnd/wndtrack.h>
- #ifdef WASABI_COMPILE_SCRIPT
- #include <api/script/vcpu.h>
- #endif
- #if !defined(WIN32) && !defined(LINUX)
- #error port me
- #endif
- Keyboard::vkEntry Keyboard::vkEntries[]={
- #ifdef WIN32
- //1, "lbutton", // fg> we don't want mouse messages in keyboard events, no.
- //2, "rbutton",
- 3, L"cancel",
- //4, L"mbutton",
- 8, L"backspace",
- 9, L"tab",
- 0xc, L"clear",
- 0xd, L"return",
- 0x10, L"shift",
- 0x11, L"ctrl",
- 0x12, L"alt",
- 0x13, L"pause",
- 0x14, L"capslock",
- 0x1b, L"esc",
- 0x20, L"space",
- 0x21, L"pgup",
- 0x22, L"pgdn",
- 0x23, L"end",
- 0x24, L"home",
- 0x25, L"left",
- 0x26, L"up",
- 0x27, L"right",
- 0x28, L"down",
- 0x29, L"select",
- 0x2b, L"execute",
- 0x2c, L"prtscr",
- 0x2d, L"insert",
- 0x2e, L"del",
- 0x2f, L"help",
- 0x5b, L"lwin",
- 0x5c, L"rwin",
- 0x5d, L"mwin",
- 0x60, L"n0",
- 0x61, L"n1",
- 0x62, L"n2",
- 0x63, L"n3",
- 0x64, L"n4",
- 0x65, L"n5",
- 0x66, L"n6",
- 0x67, L"n7",
- 0x68, L"n8",
- 0x69, L"n9",
- 0x6a, L"numpad_multiply",
- 0x6b, L"numpad_add",
- 0x6c, L"separator",
- 0x6d, L"numpad_substract",
- 0x6e, L"numpad_point",
- 0x6f, L"numpad_divide",
- 0x70, L"f1",
- 0x71, L"f2",
- 0x72, L"f3",
- 0x73, L"f4",
- 0x74, L"f5",
- 0x75, L"f6",
- 0x76, L"f7",
- 0x77, L"f8",
- 0x78, L"f9",
- 0x79, L"f10",
- 0x7a, L"f11",
- 0x7b, L"f12",
- 0x90, L"numlock",
- 0x91, L"scroll",
- 0xbb, L"equal",
- 0xbd, L"minus",
- 0xbf, L"slash",
- // 0xdb, L"minus", // seems to be the french code? --BU
- 0xf6, L"attn",
- 0xfe, L"clear",
- #endif
- #ifdef LINUX
- {XK_space, L"space"},
- {XK_Cancel, L"cancel"},
- {XK_BackSpace, L"backspace"},
- {XK_Tab, L"tab"},
- {XK_Clear, L"clear"},
- {XK_Return, L"return"},
- {XK_Shift_L, L"shift"},
- {XK_Shift_R, L"shift"},
- {XK_Control_L, L"ctrl"},
- {XK_Control_R, L"ctrl"},
- {XK_Alt_L, L"alt"},
- {XK_Alt_R, L"alt"},
- {XK_Pause, L"pause"},
- {XK_Caps_Lock, L"capslock"},
- {XK_Escape, L"esc"},
- {XK_Page_Up, L"pgup"},
- {XK_KP_Page_Up, L"pgup"},
- {XK_Page_Down, L"pgdn"},
- {XK_KP_Page_Down, L"pgdn"},
- {XK_End, L"end"},
- {XK_KP_End, L"end"},
- {XK_Home, L"home"},
- {XK_KP_Home, L"home"},
- {XK_Left, L"left"},
- {XK_KP_Left, L"left"},
- {XK_Up, L"up"},
- {XK_KP_Up, L"up"},
- {XK_Right, L"right"},
- {XK_KP_Right, L"right"},
- {XK_Down, L"down"},
- {XK_KP_Down, L"down"},
- {XK_Select, L"select"},
- {XK_Execute, L"execute"},
- {XK_Print, L"prtscr"},
- {XK_Insert, L"insert"},
- {XK_KP_Insert, L"insert"},
- {XK_Delete, L"del"},
- {XK_KP_Delete, L"del"},
- {XK_Help, L"help"},
- {XK_KP_0, L"n0"},
- {XK_KP_1, L"n1"},
- {XK_KP_2, L"n2"},
- {XK_KP_3, L"n3"},
- {XK_KP_4, L"n4"},
- {XK_KP_5, L"n5"},
- {XK_KP_6, L"n6"},
- {XK_KP_7, L"n7"},
- {XK_KP_8, L"n8"},
- {XK_KP_9, L"n9"},
- {XK_KP_Multiply, L"numpad_multiply"},
- {XK_KP_Add, L"numpad_add"},
- {XK_KP_Separator, L"separator"},
- {XK_KP_Subtract, L"numpad_substract"},
- {XK_KP_Decimal, L"numpad_point"},
- {XK_KP_Divide, L"numpad_divide"},
- {XK_F1, L"f1"},
- {XK_F2, L"f2"},
- {XK_F3, L"f3"},
- {XK_F4, L"f4"},
- {XK_F5, L"f5"},
- {XK_F6, L"f6"},
- {XK_F7, L"f7"},
- {XK_F8, L"f8"},
- {XK_F9, L"f9"},
- {XK_F10, L"f10"},
- {XK_F11, L"f11"},
- {XK_F12, L"f12"},
- {XK_Scroll_Lock, L"scroll"},
- #ifdef XK_3270
- {XK_3270_Attn, L"attn"}, // I don't know what this is...
- #endif
- {XK_Clear, L"clear"},
- #endif
- };
- //PORTME
- wchar_t *Keyboard::getVkName(int vkey)
- {
- if(vkey>=0x41 && vkey<=0x5A) { // letters
- static wchar_t key[2];
- key[0]=vkey+0x20;
- key[1]=0;
- return key;
- }
- if(vkey>=0x30 && vkey<=0x39) { // numbers
- static wchar_t key[2];
- key[0]=vkey;
- key[1]=0;
- return key;
- }
- for(int i=0;i<(sizeof(vkEntries)/sizeof(vkEntry));i++) {
- if(vkEntries[i].vk==vkey) return vkEntries[i].trans;
- }
- #ifdef _DEBUG
- //DebugString("undefined vk key pressed! (0x%x) :(\n",vkey);
- #endif
- return NULL;
- }
- int Keyboard::forwardKbdMessage(ifc_window *from, int msg, int wp, int lp)
- {
- OSWINDOWHANDLE wnd_to = WASABI_API_WND->main_getRootWnd()->gethWnd();
- // note to self:
- // this is necessary for winamp2's TranslateAccelerator call to work, it seems that this function will
- // use the mouse capture wnd to determine the keyboard focus, oh thank you microsoft, because of you
- // a script has to use "complete;" to be able to detect shift+ctrl+alt + click on a toggle button,
- // otherwise pressing a key will throw the capture away, and the button will think the mouse is gone.
- // this means that we can't be stealth doing that, we have to prevent anybody else getting shift+ctrl+alt
- // isn't that nice ?
- // we still avoid doing that if a mouse button is down, this will allow key+drags with capture
- #ifdef WIN32
- if (!(GetAsyncKeyState(VK_LBUTTON)&(1 << 31)) && !(GetAsyncKeyState(VK_RBUTTON)&(1 << 31)) && !(GetAsyncKeyState(VK_MBUTTON)&(1 << 31))) {
- SetCapture(NULL);
- }
-
- #endif
- #ifdef GET_KBDFORWARD_WND
- ifc_window *dp = from->getDesktopParent();
- if (dp) {
- Layout *l = static_cast<Layout *>(dp->getInterface(layoutGuid));
- if (l) {
- Container *c = l->getParentContainer();
- if (c) {
- GUID g = c->getDefaultContent();
- GET_KBDFORWARD_WND(g, wnd_to);
- }
- }
- }
- #endif
- if (infw) return 0;
- // if (from && from->gethWnd() == wnd_to) return 1;
- infw = 1;
-
- /* MSG winmsg;
- winmsg.message = msg;
- winmsg.hwnd = from->gethWnd();
- winmsg.wParam = wp;
- winmsg.lParam = lp;*/
- int r = 0;
- // int r = WASABI_API_APP->app_translateAccelerators(&winmsg);
- infw = 0;
- return r;
- }
- int Keyboard::onForwardOnChar(ifc_window *from, unsigned int c, int kd)
- {
- if (WASABI_API_WND->isKeyboardLocked()) return 1;
- return forwardKbdMessage(from, WM_CHAR, (WPARAM)c, (LPARAM)kd);
- }
- int MEMCMPC(void *m, char c, int size) {
- char *p = (char*)m;
- for (int i=0;i<size;i++) {
- if (*p != c) return 1;
- }
- return 0;
- }
- int Keyboard::onForwardOnKeyDown(ifc_window *from, int k, int kd, int nomsg)
- {
- if (WASABI_API_WND->isKeyboardLocked()) return 1;
- if (infw) return 0;
- if (k >= MAX_KEY) return 0;
- lastwasreset = 0;
- pressedKeys[k]=1;
- syncKeyTable();
- wchar_t s[64]={0,};
- int first=1;
- #ifdef LINUX
- for (int i=MAX_KEY-1; i >= 0; i--) {
- #else
- for (int i=0;i<MAX_KEY;i++) {
- #endif
- if (pressedKeys[i]) {
- wchar_t *n = getVkName(i);
- if (n) {
- if (!first) wcscat(s, L"+");
- else first=0;
- wcscat(s,n);
- }
- }
- }
- ifc_window *wnd = from;
- if(s[0]) {
- #ifdef _DEBUG
- DebugString("keyboard: key pressed: %s\n",s);
- #endif
- #ifdef WASABI_COMPILE_LOCALES
- const wchar_t *action;
- #endif
- int found=0;
- while(wnd!=NULL) {
- for(int i=0;i<accSecEntries.getNumItems();i++) {
- AccSec *ase = accSecEntries[i];
- if(ase->global || ase->wnd==wnd) {
- #ifdef WASABI_COMPILE_LOCALES
- if (action=LocalesManager::translateAccelerator(ase->name, s))
- {
- if(ase->wnd==wnd) found = 1;
- wnd->onAcceleratorEvent(action);
- #ifdef _DEBUG
- DebugString("keyboard: accelerator found\n");
- #endif
- continue;
- }
- #else
- wnd->onAcceleratorEvent(s);
- #endif
- }
- }
- wnd=wnd->getParent();
- }
- if (found) return 1;
-
- if (NULL != from)
- {
- const wchar_t *accelSec = from->getId();
- if (accelSec && *accelSec)
- {
- #ifdef WASABI_COMPILE_LOCALES
- if(action=LocalesManager::translateAccelerator(accelSec, s))
- {
- int r = 0;
- #ifdef WASABI_COMPILE_SCRIPT
- r = SystemObject::onAccelerator(action, accelSec, s);
- #endif
- #ifdef WASABI_COMPILE_ACTIONS
- if (r == 0)
- {
- int act=SkinParser::getAction(action);
- if(act) Main::doAction(act);
- }
- #endif
- #ifdef _DEBUG
- DebugString("keyboard: accelerator found\n");
- #endif
- return 1;
- }
- #endif
- }
- }
- #ifdef WASABI_COMPILE_LOCALES
- if(action=LocalesManager::translateAccelerator(L"general", s))
- {
- int r = 0;
- #ifdef WASABI_COMPILE_SCRIPT
- r = SystemObject::onAccelerator(action, L"general", s);
- #endif
- #ifdef WASABI_COMPILE_ACTIONS
- if (r == 0) {
- int act=SkinParser::getAction(action);
- if(act) Main::doAction(act);
- }
- #endif
- #ifdef _DEBUG
- DebugString("keyboard: accelerator found\n");
- #endif
- return 1;
- }
- #endif
- #ifdef _DEBUG
- DebugString("keyboard: accelerator not found\n");
- #endif
- #ifdef WASABI_COMPILE_SCRIPT
- DebugStringW(L"keyboard: sending \"%s\" to script\n", s);
- SystemObject::onKeyDown(s);
- if (VCPU::getComplete()) {
- DebugStringW(L"keyboard: %s trapped by script\n", s);
- return 1;
- }
- #endif
- if (pressedKeys[VK_CONTROL] && pressedKeys[VK_TAB])
- {
- int next = pressedKeys[VK_SHIFT] ? -1 : 1;
- HWND w = GetForegroundWindow();
- if (w == NULL) {
- WASABI_API_WND->main_getRootWnd()->setFocus();
- return 1;
- }
- ifc_window *cur = windowTracker->rootWndFromHwnd(w); // TODO: API_WNDMGR->
- if (cur != NULL) {
- ifc_window *nextwnd = windowTracker->getNextDesktopWindow(cur, next);
- if (nextwnd) nextwnd->setFocus();
- return 1;
- }
- WASABI_API_WND->main_getRootWnd()->setFocus();
- return 1;
- }
- if (from && pressedKeys[VK_CONTROL] && pressedKeys[VK_F4]) {
- ifc_window *dp = from->getDesktopParent();
- if (dp) {
- Layout *l = static_cast<Layout *>(dp->getInterface(layoutGuid));
- if (l) {
- Container *c = l->getParentContainer();
- if (c) {
- if (c->isMainContainer())
- c->setVisible(!c->isVisible());
- else
- c->close();
- return 1;
- }
- }
- }
- }
- if (pressedKeys[0x5D]) {
- #if defined(WA3COMPATIBILITY)
- Main::appContextMenu(from, TRUE, 0);
- #elif defined(WASABI_CUSTOM_CONTEXTMENUS)
- extern void appContextMenu(ifc_window *wnd);
- appContextMenu(windowTracker->rootWndFromHwnd(GetForegroundWindow()));
- #endif
- }
- if (s[0] && from) return forwardKbdMessage(from, WM_KEYDOWN, (WPARAM)k, (LPARAM)kd);
- }
- return 0;
- }
- void Keyboard::syncKeyTable() {
- for (int i=0;i<MAX_KEY;i++) {
- //if (pressedKeys[i] && !(GetAsyncKeyState(i) & (1 << 31))) pressedKeys[i] = 0;
- if (pressedKeys[i] && !Std::keyDown(i)) pressedKeys[i] = 0;
- }
- }
- int Keyboard::onForwardOnKeyUp(ifc_window *from, int k, int kd) {
- if (WASABI_API_WND->isKeyboardLocked()) return 1;
- if (infw) return 0;
- if (k >= MAX_KEY) return 0;
- /*int hadkey = */MEMCMPC(pressedKeys, 0, sizeof(pressedKeys));
- pressedKeys[k]=0;
- syncKeyTable();
- wchar_t s[64]={0,};
- int first=1;
- #ifdef LINUX
- for (int i=MAX_KEY-1; i >= 0; i--) {
- #else
- for (int i=0;i<MAX_KEY;i++) {
- #endif
- if (pressedKeys[i]) {
- wchar_t *n = getVkName(i);
- if (n) {
- if (!first) wcscat(s, L"+");
- else first=0;
- wcscat(s,n);
- }
- }
- }
- if (!*s) {
- if (!lastwasreset)
- {
- lastwasreset = 1;
- #ifdef WASABI_COMPILE_SCRIPT
- DebugStringW(L"keyboard: sending \"%s\" to script\n", s);
- SystemObject::onKeyDown(s);
- if (VCPU::getComplete()) {
- DebugStringW(L"keyboard: %s trapped by script\n", s);
- return 1;
- }
- #endif
- }
- }
- return forwardKbdMessage(from, WM_KEYUP, (WPARAM)k, (LPARAM)kd);
- }
- int Keyboard::onForwardOnSysKeyDown(ifc_window *from, int k, int kd) {
- if (WASABI_API_WND->isKeyboardLocked()) return 1;
- if (infw) return 0;
- if(kd&(1<<29)) pressedKeys[0x12]=1;
- int r = onForwardOnKeyDown(from, k, 1);
- if (r == 0) {
- if (from && forwardKbdMessage(from, WM_SYSKEYDOWN, (WPARAM)k, (LPARAM)kd)) return 1;
- }
- return r;
- }
- int Keyboard::onForwardOnSysKeyUp(ifc_window *from, int k, int kd)
- {
- if (WASABI_API_WND->isKeyboardLocked()) return 1;
- if (infw) return 0;
- if(kd&(1<<29)) pressedKeys[0x12]=0;
- pressedKeys[k]=0;
- int r = onForwardOnKeyUp(from, k, 1);
- if (r == 0) {
- if (forwardKbdMessage(from, WM_SYSKEYUP, (WPARAM)k, (WPARAM)kd)) return 1;
- }
- return r;
- }
- int Keyboard::onForwardOnKillFocus() {
- // FG> I don't think this is necessary anymore because onkeydown always resyncs the pressedKeys table
- // and supressing this allows scripts to trap ctrl/alt/shit + clicks (otherwise the click would reset
- // the modifiers by way of an automatic focus)
- //MEMSET(pressedKeys,0,sizeof(pressedKeys));
- return 0;
- }
- void Keyboard::registerAcceleratorSection(const wchar_t *name, ifc_window *wnd, int global)
- {
- accSecEntries.addItem(new AccSec(name,wnd,global));
- viewer.viewItem(wnd);
- }
- int Keyboard::interceptOnChar(unsigned int c) {
- if (hookers.getNumItems() > 0) {
- return hookers.getLast()->onChar(c);
- }
- return 0;
- }
- int Keyboard::interceptOnKeyDown(int k){
- if (hookers.getNumItems() > 0) {
- return hookers.getLast()->onKeyDown(k);
- }
- return 0;
- }
- int Keyboard::interceptOnKeyUp(int k){
- if (hookers.getNumItems() > 0) {
- return hookers.getLast()->onKeyUp(k);
- }
- return 0;
- }
- int Keyboard::interceptOnSysKeyDown(int k, int kd){
- if (hookers.getNumItems() > 0) {
- return hookers.getLast()->onSysKeyDown(k, kd);
- }
- return 0;
- }
- int Keyboard::interceptOnSysKeyUp(int k, int kd){
- if (hookers.getNumItems() > 0) {
- return hookers.getLast()->onSysKeyUp(k, kd);
- }
- return 0;
- }
- void Keyboard::hookKeyboard(ifc_window *hooker) {
- hookers.addItem(hooker);
- DebugString("hookKeyboard = %d\n", hookers.getNumItems());
- }
- void Keyboard::unhookKeyboard(ifc_window *hooker) {
- hookers.removeItem(hooker);
- DebugString("unhookKeyboard = %d\n", hookers.getNumItems());
- }
- void Keyboard::reset() {
- if (lastwasreset) return;
- DebugString("keyboard reset\n");
- MEMZERO(pressedKeys, sizeof(pressedKeys));
- if (!lastwasreset) {
- lastwasreset = 1;
- #ifdef WASABI_COMPILE_SCRIPT
- DebugString("keyboard: sending \"\" to script\n");
- SystemObject::onKeyDown(L"");
- #endif
- }
- }
- int AccSecViewer::viewer_onItemDeleted(ifc_window *item) {
- for(int i=0;i<Keyboard::accSecEntries.getNumItems();i++)
- if(Keyboard::accSecEntries[i]->wnd==item) {
- Keyboard::accSecEntries.removeByPos(i);
- i--;
- }
- return 1;
- }
- wchar_t Keyboard::pressedKeys[MAX_KEY]={0,};
- PtrList<AccSec> Keyboard::accSecEntries;
- AccSecViewer Keyboard::viewer;
- PtrList<ifc_window> Keyboard::hookers;
- int Keyboard::infw = 0;
- int Keyboard::lastwasreset = 0;
|