aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/wnd/keyboard.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/wnd/keyboard.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/wnd/keyboard.cpp')
-rw-r--r--Src/Wasabi/api/wnd/keyboard.cpp570
1 files changed, 570 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wnd/keyboard.cpp b/Src/Wasabi/api/wnd/keyboard.cpp
new file mode 100644
index 00000000..8c06d861
--- /dev/null
+++ b/Src/Wasabi/api/wnd/keyboard.cpp
@@ -0,0 +1,570 @@
+#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;