From 0025e606854e9156008cc33953f3994597c05e59 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 21 Oct 2023 19:45:56 +0300 Subject: [PATCH] on screen keyboard --- aks.def | 1 + include/inputdevice.h | 3 + include/uae.h | 2 + inputdevice.cpp | 146 +++++++--- inputevents.def | 2 + od-win32/dinput.cpp | 16 +- od-win32/win32gfx.cpp | 605 +++++++++++++++++++++++++++++++++++++++++- od-win32/win32gfx.h | 5 +- od-win32/win32gui.cpp | 3 + 9 files changed, 731 insertions(+), 52 deletions(-) diff --git a/aks.def b/aks.def index 9690194d..277f117d 100644 --- a/aks.def +++ b/aks.def @@ -134,4 +134,5 @@ AKS(CUBOCOIN1) AKS(CUBOCOIN2) AKS(CUBOCOIN3) AKS(CUBOCOIN4) +AKS(OSK) diff --git a/include/inputdevice.h b/include/inputdevice.h index 44d08cec..072ad8fe 100644 --- a/include/inputdevice.h +++ b/include/inputdevice.h @@ -378,6 +378,9 @@ bool key_shiftpressed(void); bool key_altpressed(void); bool key_ctrlpressed(void); +void osk_setup(int, int); +bool osk_status(void); + extern int key_swap_hack, key_swap_hack2; #endif /* UAE_INPUTDEVICE_H */ diff --git a/include/uae.h b/include/uae.h index a4e871a9..2fd0982f 100644 --- a/include/uae.h +++ b/include/uae.h @@ -53,6 +53,8 @@ extern bool is_mainthread(void); extern void fpu_reset(void); extern void fpux_save(int*); extern void fpux_restore(int*); +extern bool target_osd_keyboard(int); +extern void target_osk_control(int, int, int, int); extern int quit_program; extern bool console_emulation; diff --git a/inputdevice.cpp b/inputdevice.cpp index d3787dc0..7ef17809 100644 --- a/inputdevice.cpp +++ b/inputdevice.cpp @@ -195,6 +195,50 @@ static struct temp_uids temp_uid; static int temp_uid_index[MAX_INPUT_DEVICES][IDTYPE_MAX]; static int temp_uid_cnt[IDTYPE_MAX]; static int gp_swappeddevices[MAX_INPUT_DEVICES][IDTYPE_MAX]; +static int osk_state; + +bool osk_status(void) +{ + return osk_state != 0; +} + +static void osk_control(int x, int y, int button, int buttonstate) +{ + if (!osk_state) { + return; + } + target_osk_control(x, y, button, buttonstate); +} + +void osk_setup(int monid, int state) +{ + if (monid) { + return; + } + if (state < -1) { + if (osk_state) { + target_osd_keyboard(0); + if (!target_osd_keyboard(1)) { + target_osd_keyboard(0); + } + } + return; + } + if (state == -1) { + osk_state = osk_state ? 0 : 1; + } else { + osk_state = state; + } + if (!osk_state) { + target_osd_keyboard(0); + return; + } + if (!target_osd_keyboard(1)) { + target_osd_keyboard(0); + osk_state = 0; + return; + } +} static int isdevice (struct uae_input_device *id) { @@ -4753,6 +4797,9 @@ static bool inputdevice_handle_inputcode2(int monid, int code, int state, const switch (code) { + case AKS_OSK: + osk_setup(0, -1); + break; case AKS_ENTERGUI: gui_display (-1); setsystime (); @@ -5299,25 +5346,27 @@ static int handle_input_event2(int nr, int state, int max, int flags, int extra) case 4: /* ->Parallel port joystick adapter port #2 */ joy = ie->unit - 1; if (ie->type & 4) { - int old = joybutton[joy] & (1 << ie->data); - - if (state) { - joybutton[joy] |= 1 << ie->data; - gui_gameport_button_change (joy, ie->data, 1); + if (osk_state) { + osk_control(0, 0, 1 << ie->data, state); } else { - joybutton[joy] &= ~(1 << ie->data); - gui_gameport_button_change (joy, ie->data, 0); - } + int old = joybutton[joy] & (1 << ie->data); + if (state) { + joybutton[joy] |= 1 << ie->data; + gui_gameport_button_change (joy, ie->data, 1); + } else { + joybutton[joy] &= ~(1 << ie->data); + gui_gameport_button_change (joy, ie->data, 0); + } - if (ie->data == 0 && old != (joybutton[joy] & (1 << ie->data)) && currprefs.cpu_cycle_exact) { - if (!input_record && !input_play && currprefs.input_contact_bounce) { - // emulate contact bounce, 1st button only, others have capacitors - bouncy = 1; - bouncy_cycles = get_cycles () + CYCLE_UNIT * currprefs.input_contact_bounce; + if (ie->data == 0 && old != (joybutton[joy] & (1 << ie->data)) && currprefs.cpu_cycle_exact) { + if (!input_record && !input_play && currprefs.input_contact_bounce) { + // emulate contact bounce, 1st button only, others have capacitors + bouncy = 1; + bouncy_cycles = get_cycles () + CYCLE_UNIT * currprefs.input_contact_bounce; + } } } - } else if (ie->type & 8) { /* real mouse / analog stick mouse emulation */ @@ -5546,38 +5595,53 @@ static int handle_input_event2(int nr, int state, int max, int flags, int extra) } mouse_deltanoreset[joy][0] = 1; mouse_deltanoreset[joy][1] = 1; - joydir[joy] = 0; - if (left) { - if (!allowoppositestick) { - joydir[joy] &= ~DIR_RIGHT; + if (osk_state) { + if (left) { + osk_control(-1, 0, 0, 0); } - joydir[joy] |= DIR_LEFT; - } - if (right) { - if (!allowoppositestick) { - joydir[joy] &= ~DIR_LEFT; + if (right) { + osk_control(1, 0, 0, 0); } - joydir[joy] |= DIR_RIGHT; - } - if (top) { - if (!allowoppositestick) { - joydir[joy] &= ~DIR_DOWN; + if (top) { + osk_control(0, -1, 0, 0); } - joydir[joy] |= DIR_UP; - } - if (bot) { - if (!allowoppositestick) { - joydir[joy] &= ~DIR_UP; + if (bot) { + osk_control(0, 1, 0, 0); } - joydir[joy] |= DIR_DOWN; - } - if (joy == 0 || joy == 1) - joymousecounter (joy); + } else { + joydir[joy] = 0; + if (left) { + if (!allowoppositestick) { + joydir[joy] &= ~DIR_RIGHT; + } + joydir[joy] |= DIR_LEFT; + } + if (right) { + if (!allowoppositestick) { + joydir[joy] &= ~DIR_LEFT; + } + joydir[joy] |= DIR_RIGHT; + } + if (top) { + if (!allowoppositestick) { + joydir[joy] &= ~DIR_DOWN; + } + joydir[joy] |= DIR_UP; + } + if (bot) { + if (!allowoppositestick) { + joydir[joy] &= ~DIR_UP; + } + joydir[joy] |= DIR_DOWN; + } + if (joy == 0 || joy == 1) + joymousecounter (joy); - gui_gameport_axis_change (joy, DIR_LEFT_BIT, left, 0); - gui_gameport_axis_change (joy, DIR_RIGHT_BIT, right, 0); - gui_gameport_axis_change (joy, DIR_UP_BIT, top, 0); - gui_gameport_axis_change (joy, DIR_DOWN_BIT, bot, 0); + gui_gameport_axis_change (joy, DIR_LEFT_BIT, left, 0); + gui_gameport_axis_change (joy, DIR_RIGHT_BIT, right, 0); + gui_gameport_axis_change (joy, DIR_UP_BIT, top, 0); + gui_gameport_axis_change (joy, DIR_DOWN_BIT, bot, 0); + } } break; case 0: /* ->KEY */ diff --git a/inputevents.def b/inputevents.def index 76930bf7..d9629b2b 100644 --- a/inputevents.def +++ b/inputevents.def @@ -453,4 +453,6 @@ DEFEVENT(SPC_VIDEOGRAB_PAUSE,_T("VideoGrab Pause"),AM_K,0,0,AKS_VIDEOGRAB_PAUSE) DEFEVENT(SPC_VIDEOGRAB_PREV,_T("VideoGrab Previous Frame"),AM_K,0,0,AKS_VIDEOGRAB_PREV) DEFEVENT(SPC_VIDEOGRAB_NEXT,_T("VideoGrab Next Frame"),AM_K,0,0,AKS_VIDEOGRAB_NEXT) +DEFEVENT(SPC_OSK,_T("On screen keyboard"),AM_K,0,0,AKS_OSK) + DEFEVENT(SPC_LAST, _T(""), AM_DUMMY, 0,0,0) diff --git a/od-win32/dinput.cpp b/od-win32/dinput.cpp index 670e434d..ceff6deb 100644 --- a/od-win32/dinput.cpp +++ b/od-win32/dinput.cpp @@ -4580,6 +4580,8 @@ int input_get_default_joystick (struct uae_input_device *uid, int i, int port, i if (isrealbutton (did, 2)) setid (uid, i, ID_BUTTON_OFFSET + 2, 0, port, port ? INPUTEVENT_JOY2_3RD_BUTTON : INPUTEVENT_JOY1_3RD_BUTTON, gp); } + if (isrealbutton(did, 3)) + setid(uid, i, ID_BUTTON_OFFSET + 3, 0, port, INPUTEVENT_SPC_OSK, gp); } for (j = 2; j < MAX_MAPPINGS - 1; j++) { @@ -4629,12 +4631,14 @@ int input_get_default_joystick_analog (struct uae_input_device *uid, int i, int setid (uid, i, ID_AXIS_OFFSET + 0, 0, port, port ? INPUTEVENT_JOY2_HORIZ_POT : INPUTEVENT_JOY1_HORIZ_POT, gp); setid (uid, i, ID_AXIS_OFFSET + 1, 0, port, port ? INPUTEVENT_JOY2_VERT_POT : INPUTEVENT_JOY1_VERT_POT, gp); setid (uid, i, ID_BUTTON_OFFSET + 0, 0, port, port ? INPUTEVENT_JOY2_LEFT : INPUTEVENT_JOY1_LEFT, af, gp); - if (isrealbutton (did, 1)) - setid (uid, i, ID_BUTTON_OFFSET + 1, 0, port, port ? INPUTEVENT_JOY2_RIGHT : INPUTEVENT_JOY1_RIGHT, gp); - if (isrealbutton (did, 2)) - setid (uid, i, ID_BUTTON_OFFSET + 2, 0, port, port ? INPUTEVENT_JOY2_UP : INPUTEVENT_JOY1_UP, gp); - if (isrealbutton (did, 3)) - setid (uid, i, ID_BUTTON_OFFSET + 3, 0, port, port ? INPUTEVENT_JOY2_DOWN : INPUTEVENT_JOY1_DOWN, gp); + if (isrealbutton(did, 1)) + setid(uid, i, ID_BUTTON_OFFSET + 1, 0, port, port ? INPUTEVENT_JOY2_RIGHT : INPUTEVENT_JOY1_RIGHT, gp); + if (isrealbutton(did, 2)) + setid(uid, i, ID_BUTTON_OFFSET + 2, 0, port, port ? INPUTEVENT_JOY2_UP : INPUTEVENT_JOY1_UP, gp); + if (isrealbutton(did, 3)) + setid(uid, i, ID_BUTTON_OFFSET + 3, 0, port, port ? INPUTEVENT_JOY2_DOWN : INPUTEVENT_JOY1_DOWN, gp); + if (isrealbutton(did, 4)) + setid(uid, i, ID_BUTTON_OFFSET + 4, 0, port, INPUTEVENT_SPC_OSK, gp); for (j = 2; j < MAX_MAPPINGS - 1; j++) { int type = did->axistype[j]; diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index 5dcc1a79..ca69f854 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -1,4 +1,4 @@ -/* +/* /* * UAE - The Un*x Amiga Emulator * @@ -57,6 +57,7 @@ #include "gfxboard.h" #include "cpuboard.h" #include "x86.h" +#include "keybuf.h" #ifdef RETROPLATFORM #include "rp.h" #endif @@ -4112,9 +4113,12 @@ retry: if (isfullscreen () != 0) setmouseactive(mon->monitor_id, -1); + osk_setup(mon->monitor_id, -2); + return 1; oops: + osk_setup(mon->monitor_id, 0); close_hwnds(mon); return ret; } @@ -4140,8 +4144,10 @@ bool target_graphics_buffer_update(int monid) h = vb->outheight; } - if (oldtex_w[monid] == w && oldtex_h[monid] == h && oldtex_rtg[monid] == mon->screen_is_picasso && D3D_alloctexture(mon->monitor_id, -1, -1)) + if (oldtex_w[monid] == w && oldtex_h[monid] == h && oldtex_rtg[monid] == mon->screen_is_picasso && D3D_alloctexture(mon->monitor_id, -1, -1)) { + osk_setup(monid, -2); return false; + } if (!w || !h) { oldtex_w[monid] = w; @@ -4159,6 +4165,7 @@ bool target_graphics_buffer_update(int monid) oldtex_w[monid] = w; oldtex_h[monid] = h; oldtex_rtg[monid] = mon->screen_is_picasso; + osk_setup(monid, -2); write_log (_T("Buffer %d size (%d*%d) %s\n"), monid, w, h, mon->screen_is_picasso ? _T("RTG") : _T("Native")); @@ -4413,3 +4420,597 @@ const TCHAR *DXError(HRESULT ddrval) HRESULT_CODE(ddrval)); return dderr; } + +struct osd_kb +{ + uae_s16 x, y; + uae_s16 w, h; + uae_u16 code; + uae_s8 pressed; + uae_s8 inverted; +}; + +static struct osd_kb *osd_kb_data; +static int osd_kb_selected = 11, osd_kb_x, osd_kb_y; +struct extoverlay osd_kb_eo = { 0 }; + +#define OSD_KB_TRANSPARENCY 0xee +#define OSD_KB_ACTIVE_TRANSPARENCY 0xee +#define OSD_KB_PRESSED_TRANSPARENCY 0xff +#define OSD_KB_COLOR 0xeeeeee +#define OSD_KB_ACTIVE_COLOR 0x44cc44 +#define OSD_KB_PRESSED_COLOR 0x222222 +#define OSD_KB_PRESSED_COLOR2 0x444444 + +static void drawpixel(uae_u8 *p, uae_u32 c, uae_u8 trans) +{ + ((uae_u32*)p)[0] = (c & 0x00ffffff) | (trans << 24); +} + +static void drawline(struct extoverlay *eo, int x1, int y1, int x2, int y2) +{ + uae_u8 *p = eo->data + y1 * eo->width * 4 + x1 * 4; + if (x1 != x2) { + x2++; + } + if (y1 != y2) { + y2++; + } + while (x1 != x2) { + drawpixel(p, OSD_KB_COLOR, OSD_KB_TRANSPARENCY); + if (x1 < x2) { + x1++; + p += 4; + } else { + x1--; + p -= 4; + } + } + while (y1 != y2) { + drawpixel(p, OSD_KB_COLOR, OSD_KB_TRANSPARENCY); + if (y1 < y2) { + y1++; + p += eo->width * 4; + } else { + y1--; + p -= eo->width * 4; + } + } +} + +static void highlight(struct extoverlay *eo, struct osd_kb *kb, bool mode) +{ + if (kb->inverted) { + kb->inverted = false; + highlight(eo, kb, true); + kb->inverted = false; + } + int x1 = kb->x; + int x2 = kb->x + kb->w; + int y1 = kb->y; + int y2 = kb->y + kb->h; + uae_u8 *p = eo->data + y1 * eo->width * 4; + uae_u32 color = 0; + uae_u8 tr = 0; + if (mode) { + kb->inverted = true; + color = OSD_KB_COLOR; + tr = OSD_KB_TRANSPARENCY; + } else { + color = !mode ? OSD_KB_COLOR : OSD_KB_ACTIVE_COLOR; + tr = !mode ? OSD_KB_TRANSPARENCY : OSD_KB_ACTIVE_TRANSPARENCY; + if (kb->pressed) { + color = OSD_KB_PRESSED_COLOR; + tr = OSD_KB_PRESSED_TRANSPARENCY; + } + } + while (y1 <= y2) { + uae_u8 *pp = p + x1 * 4; + for (int x = x1; x <= x2; x++) { + if (kb->inverted) { + uae_u32 *p32 = (uae_u32*)pp; + *p32 ^= 0xffffff; + } else { + if (pp[0] || pp[1] || pp[2]) { + drawpixel(pp, color, tr); + } else { + pp[3] = tr; + } + } + pp += 4; + } + p += eo->width * 4; + y1++; + } + if (mode) { + if (osd_kb_x < kb->x || osd_kb_x > kb->x + kb->w) { + osd_kb_x = kb->x + kb->w / 2; + } + if (osd_kb_y < kb->y || osd_kb_y > kb->y + kb->h) { + osd_kb_y = kb->y + kb->h / 2; + } + } +} + +static const uae_s16 layout[] = { + 10,-5,13,13,13,13,13,-5,13,13,13,13,13,-5,13,13,13,13,0, + 15,10,10,10,10,10,10,10,10,10,10,10,10,10,10,-5,15,15,-5,10,10,10,10,0, + 23,10,10,10,10,10,10,10,10,10,10,10,10,12 + 256,-40,10,10,10,10,0, + 13,10,10,10,10,10,10,10,10,10,10,10,10,10,-27,10,-15,10,10,10,10,0, + 18,10,10,10,10,10,10,10,10,10,10,10,27,-5,10,10,10,-5,10,10,10,10 + 256,0, + -8,13,13,90,13,13,-45,20,10,0, + 0 +}; +static const TCHAR *key_labels[] = { + L"Esc",L"F1",L"F2",L"F3",L"F4",L"F5",L"F6",L"F7",L"F8",L"F9",L"F10",L"GUI",L"J<>M",L"↑↓",L"X", + L"~|´",L"!|1",L"@|2",L"#|3",L"$|4",L"%|5",L"^|6",L"&|7",L"*|8",L"(|9",L")|0",L"_|-",L"+|=",L"\\||\\\\",L"←",L"Del",L"Help",L"(",L")",L"/",L"*", + L"←|→",L"Q",L"W",L"E",L"R",L"T",L"Y",L"U",L"I",L"O",L"P",L"{|[",L"}|]",L"Ret",L"7",L"8",L"9",L"-", + L"Ctrl",L"Caps|Lock",L"A",L"S",L"D",L"F",L"G",L"H",L"J",L"K",L"L",L":|;",L"*|'",L"",L"↑",L"4",L"5",L"6",L"+", + L"Shift",L"",L"Z",L"X",L"C",L"V",L"B",L"N",L"M",L"<|,",L">|.",L"?|/",L"Shift",L"←",L"↓",L"→",L"1",L"2",L"3",L"E|n|t|e|r", + L"Alt",L"\\iA",L"",L"\\iA",L"Alt",L"0",L".", + 0,0 +}; +static const uae_u16 key_codes[] = { + 0x45, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, AKS_ENTERGUI | 0x8000, AKS_SWAPJOYPORTS | 0x8000, 0xf001, AKS_OSK | 0x8000, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x41, 0x46, 0x5f, 0x5a, 0x5b, 0x5c, 0x5d, + 0x42, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x44, 0x3d, 0x3e, 0x3f, 0x4a, + 0x63, 0x62, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x4c, 0x2d, 0x2e, 0x2f, 0x5e, + 0x60, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x61, 0x4f, 0x4d, 0x4e, 0x1d, 0x1e, 0x1f, 0x43, + 0x64, 0x66, 0x40, 0x67, 0x64, 0x0f, 0x3c, + 0 +}; + +static void draw_key(HDC hdc, void *bm, int bmw, int bmh, struct extoverlay *eo, float sx, float sy, const TCHAR *key, int len, int fw, int fh) +{ + SetBkMode(hdc, OPAQUE); + BitBlt(hdc, 0, 0, bmw, bmh, NULL, 0, 0, BLACKNESS); + TextOut(hdc, 10, 10, key, len); + int offsetx = 10; + int offsety = 10 - 1; + for (int y = 0; y < fh + 2; y++) { + uae_u8 *src = (uae_u8 *)bm + (y + offsety) * bmw + offsetx; + uae_u8 *dst = eo->data + (int)(sx + 0.5f) * 4 + ((int)(sy + 0.5f) + y) * eo->width * 4; + for (int x = 0; x < bmw; x++) { + uae_u8 b = *src++; + if (b == 2) { + drawpixel(dst, OSD_KB_COLOR, OSD_KB_TRANSPARENCY); + } + dst += 4; + } + } +} + +static bool draw_keyboard(HDC hdc, HFONT *fonts, void *bm, int bmw, int bmh, struct extoverlay *eo, int fw, int fh) +{ + int num = 0, knum = 0; + int maxcols = 240; + + float space = (float)eo->width / maxcols; + float colwidth = (float)eo->width / maxcols; + float rowheight = colwidth * 7.5f; + + int theight = (int)((rowheight + space) * 6 + 2 * space); + if (eo->height < theight) { + eo->height = theight; + } + eo->data = xcalloc(uae_u8, eo->width * eo->height * 4); + if (!eo->data) { + return false; + } + + for (int y = 0; y < eo->height; y++) { + uae_u8 *p = eo->data + y * eo->width * 4; + for (int x = 0; x < eo->width; x++) { + p[3] = OSD_KB_TRANSPARENCY; + p += 4; + } + } + + float y = 2.0f * space; + float x = 2.0f * space; + const uae_s16 *lp = layout; + const TCHAR **ll = key_labels; + while (*lp) { + uae_s16 v = *lp++; + float w = (abs(v) & 255) * colwidth - space; + float h = rowheight; + if ((abs(v) >> 8) > 0) { + h += rowheight; + h += space; + } + if (v > 0) { + const TCHAR *lab = key_labels[knum]; + if (lab) { + float kx = x; + float ky = y; + int i = 0; + bool esc = false; + TCHAR out[10]; + TCHAR *outp = out; + bool italic = false; + for (;;) { + bool skip = false; + TCHAR c = lab[i]; + TCHAR cn = lab[i + 1]; + if (c == '\\' && cn != '\\' && !esc) { + esc = true; + } else if (c == 'i' && esc) { + italic = true; + esc = false; + } else if (c == '|' && esc) { + *outp++ = c; + esc = false; + skip = true; + } else if (c != '|' && c) { + *outp++ = c; + esc = false; + } + if ((c == '|' && !esc && !skip) || c == 0) { + SelectObject(hdc, italic ? fonts[1] : fonts[0]); + draw_key(hdc, bm, bmw, bmh, eo, kx + space, ky + space, out, outp - out, fw, fh); + ky += fh + 2; + outp = out; + italic = false; + } + if (!c) { + break; + } + i++; + } + } + if (key_labels[knum] != NULL || key_labels[knum + 1] != NULL) { + knum++; + } + + struct osd_kb *kb = &osd_kb_data[num]; + kb->x = (int)(x + 0.5f); + kb->y = (int)(y + 0.5f); + kb->w = (int)(w + 0.5f); + kb->h = (int)(h + 0.5f); + kb->code = key_codes[num]; + + drawline(eo, kb->x, kb->y, kb->x + kb->w, kb->y); + drawline(eo, kb->x, kb->y + 1, kb->x + kb->w, kb->y + 1); + + drawline(eo, kb->x, kb->y + kb->h, kb->x + kb->w, kb->y + kb->h); + drawline(eo, kb->x, kb->y + kb->h - 1, kb->x + kb->w, kb->y + kb->h - 1); + + drawline(eo, kb->x, kb->y, kb->x, kb->y + kb->h); + drawline(eo, kb->x + 1, kb->y, kb->x + 1, kb->y + kb->h); + + drawline(eo, kb->x + kb->w, kb->y, kb->x + kb->w, kb->y + kb->h); + drawline(eo, kb->x + kb->w - 1, kb->y, kb->x + kb->w - 1, kb->y + kb->h); + + if (num == osd_kb_selected) { + highlight(eo, kb, true); + } + num++; + } + x += w + space; + + if (*lp == 0) { + y += rowheight + space; + x = 2 * space; + lp++; + } + } + + return true; +} + +static const TCHAR *ab = _T("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); + +static bool drawkeys(HWND parent, struct extoverlay *eo) +{ + bool ret = false; + HDC hdc; + LPLOGPALETTE lp; + HPALETTE hpal; + BITMAPINFO *bi; + BITMAPINFOHEADER *bih; + HBITMAP bitmap = NULL; + int width = 128; + int height = 128; + void *bm; + int fsize = eo->height / 30; + + if (fsize < 4) { + return false; + } + + hdc = CreateCompatibleDC(NULL); + if (hdc) { + int y = getdpiforwindow(parent); + int fontsize = -MulDiv(fsize, y, 72); + fontsize = fontsize * statusline_get_multiplier(0) / 100; + lp = (LOGPALETTE *)xcalloc(uae_u8, sizeof(LOGPALETTE) + 3 * sizeof(PALETTEENTRY)); + if (lp) { + lp->palNumEntries = 4; + lp->palVersion = 0x300; + lp->palPalEntry[1].peBlue = lp->palPalEntry[1].peGreen = lp->palPalEntry[0].peRed = 0x10; + lp->palPalEntry[2].peBlue = lp->palPalEntry[2].peGreen = lp->palPalEntry[2].peRed = 0xff; + lp->palPalEntry[3].peBlue = lp->palPalEntry[3].peGreen = lp->palPalEntry[3].peRed = 0x7f; + hpal = CreatePalette(lp); + if (hpal) { + SelectPalette(hdc, hpal, FALSE); + bi = (BITMAPINFO *)xcalloc(uae_u8, sizeof(BITMAPINFOHEADER) + 4 * sizeof(RGBQUAD)); + if (bi) { + bih = &bi->bmiHeader; + bih->biSize = sizeof(BITMAPINFOHEADER); + bih->biWidth = width; + bih->biHeight = -height; + bih->biPlanes = 1; + bih->biBitCount = 8; + bih->biCompression = BI_RGB; + bih->biClrUsed = 4; + bih->biClrImportant = 4; + bi->bmiColors[1].rgbBlue = bi->bmiColors[1].rgbGreen = bi->bmiColors[1].rgbRed = 0x10; + bi->bmiColors[2].rgbBlue = bi->bmiColors[2].rgbGreen = bi->bmiColors[2].rgbRed = 0xff; + bi->bmiColors[3].rgbBlue = bi->bmiColors[3].rgbGreen = bi->bmiColors[3].rgbRed = 0x7f; + bitmap = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bm, NULL, 0); + if (bitmap) { + SelectObject(hdc, bitmap); + RealizePalette(hdc); + HFONT fonts[3] = { 0, 0, 0 }; + fonts[0] = CreateFont(fontsize, 0, + 0, 0, + FW_BOLD, + FALSE, + FALSE, + FALSE, + DEFAULT_CHARSET, + OUT_TT_PRECIS, + CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, + FIXED_PITCH | FF_DONTCARE, + _T("Lucida Console")); + fonts[1] = CreateFont(fontsize, 0, + 0, 0, + FW_BOLD, + TRUE, + FALSE, + FALSE, + DEFAULT_CHARSET, + OUT_TT_PRECIS, + CLIP_DEFAULT_PRECIS, + PROOF_QUALITY, + FIXED_PITCH | FF_DONTCARE, + _T("Lucida Console")); + if (fonts[0] && fonts[1]) { + SelectObject(hdc, fonts[0]); + SetTextColor(hdc, PALETTEINDEX(2)); + SetBkColor(hdc, PALETTEINDEX(1)); + + TEXTMETRIC tm; + GetTextMetrics(hdc, &tm); + int w = 0; + int h = tm.tmAscent + 2; + for (int i = 0; i < ab[i]; i++) { + SIZE sz; + if (GetTextExtentPoint32(hdc, &ab[i], 1, &sz)) { + if (sz.cx > w) + w = sz.cx; + } + } + w += 1; + + if (draw_keyboard(hdc, fonts, bm, width, height, eo, w, h)) { + ret = true; + } + } + if (fonts[0]) { + DeleteObject(fonts[0]); + } + if (fonts[1]) { + DeleteObject(fonts[1]); + } + DeleteObject(bitmap); + } + xfree(bi); + } + DeleteObject(hpal); + } + xfree(lp); + } + ReleaseDC(NULL, hdc); + } + return ret; +} + +void target_osk_control(int x, int y, int button, int buttonstate) +{ + if (button == 2) { + if (buttonstate) { + struct osd_kb *kb = &osd_kb_data[osd_kb_selected]; + kb->pressed = kb->pressed ? 0 : 1; + highlight(&osd_kb_eo, kb, false); + D3D_extoverlay(&osd_kb_eo, 0); + if ((kb->code & 0xf000) != 0xf000) { + if (kb->pressed) { + record_key((kb->code << 1) | 0); + } else { + record_key((kb->code << 1) | 1); + } + } + } + return; + } + if (button == 1) { + struct osd_kb *kb = &osd_kb_data[osd_kb_selected]; + if (kb->pressed) { + kb->pressed = 0; + highlight(&osd_kb_eo, kb, true); + D3D_extoverlay(&osd_kb_eo, 0); + if (kb->code != 0x62) { + record_key((kb->code << 1) | 1); + } + } + if (buttonstate) { + kb->pressed = -1; + highlight(&osd_kb_eo, kb, false); + D3D_extoverlay(&osd_kb_eo, 0); + } + + if (kb->code & 0x8000) { + if ((kb->code & 0xf000) != 0xf000) { + inputdevice_add_inputcode(kb->code & 0x7fff, buttonstate, NULL); + } else { + int c = kb->code & 0xfff; + if (c == 1) { + if (buttonstate) { + struct AmigaMonitor *amon = &AMonitors[0]; + if (osd_kb_eo.ypos == 0) { + osd_kb_eo.ypos = (amon->amigawin_rect.bottom - amon->amigawin_rect.top) - osd_kb_eo.height; + } else { + osd_kb_eo.ypos = 0; + } + D3D_extoverlay(&osd_kb_eo, 0); + } + } + } + } else { + // capslock? + if (kb->code == 0x62) { + if (buttonstate) { + int capsstate = getcapslockstate(); + capsstate = capsstate ? 0 : 1; + record_key((kb->code << 1) | capsstate); + setcapslockstate(capsstate); + } + } else { + if (buttonstate) { + record_key((kb->code << 1) | 0); + } else { + record_key((kb->code << 1) | 1); + } + } + } + return; + } + + if (x > 1) { + x = 1; + } + if (x < -1) { + x = -1; + } + if (y > 1) { + y = 1; + } + if (y < -1) { + y = -1; + } + + if (x || y) { + for (int i = 0; osd_kb_data[i].w; i++) { + struct osd_kb *kb = &osd_kb_data[i]; + if (kb->pressed < 0) { + return; + } + } + } + + int max = 1000; + while (x || y) { + osd_kb_x += x * 5; + osd_kb_y += y * 5; + if (osd_kb_x < 0) { + for (int i = 0; osd_kb_data[i].w; i++) { + struct osd_kb *kb = &osd_kb_data[i]; + if (kb->x + kb->w > osd_kb_x) { + osd_kb_x = kb->x + kb->w; + } + } + } + if (osd_kb_y < 0) { + for (int i = 0; osd_kb_data[i].w; i++) { + struct osd_kb *kb = &osd_kb_data[i]; + if (kb->y + kb->h > osd_kb_y) { + osd_kb_y = kb->y + kb->h; + } + } + } + int xmax = 0, ymax = 0; + int i; + for (i = 0; osd_kb_data[i].w; i++) { + struct osd_kb *kb = &osd_kb_data[i]; + if (osd_kb_x > kb->x + kb->w) { + xmax++; + } + if (osd_kb_y > kb->y + kb->h) { + ymax++; + } + if (i != osd_kb_selected) { + if (kb->x <= osd_kb_x && kb->x + kb->w >= osd_kb_x && kb->y <= osd_kb_y && kb->y + kb->h >= osd_kb_y) { + highlight(&osd_kb_eo, &osd_kb_data[osd_kb_selected], false); + highlight(&osd_kb_eo, kb, true); + osd_kb_selected = i; + D3D_extoverlay(&osd_kb_eo, 0); + return; + } + } + } + if (xmax >= i) { + osd_kb_x = 0; + } + if (ymax >= i) { + osd_kb_y = 0; + } + max--; + if (max < 0) { + highlight(&osd_kb_eo, &osd_kb_data[osd_kb_selected], false); + osd_kb_selected = 0; + highlight(&osd_kb_eo, &osd_kb_data[osd_kb_selected], true); + D3D_extoverlay(&osd_kb_eo, 0); + return; + } + } + +} + +bool target_osd_keyboard(int show) +{ + struct AmigaMonitor *amon = &AMonitors[0]; + static bool first; + + xfree(osd_kb_data); + osd_kb_data = NULL; + osd_kb_eo.idx = 0x7f7f0000; + if (!show) { + osd_kb_eo.width = -1; + osd_kb_eo.height = -1; + D3D_extoverlay(&osd_kb_eo, 0); + return true; + } + + int w = amon->amigawin_rect.right - amon->amigawinclip_rect.left; + int h = amon->amigawin_rect.bottom - amon->amigawinclip_rect.top; + + if (w > h * 4 / 3) { + w = h * 4 / 3; + } + osd_kb_eo.width = w; + osd_kb_eo.height = w * 10 / 44; + osd_kb_data = xcalloc(struct osd_kb, 120); + if (osd_kb_data) { + if (!drawkeys(amon->hAmigaWnd, &osd_kb_eo)) { + return false; + } + } + if (!first) { + osd_kb_eo.ypos = (amon->amigawin_rect.bottom - amon->amigawin_rect.top) - osd_kb_eo.height; + } + if (osd_kb_eo.ypos) { + osd_kb_eo.ypos = (amon->amigawin_rect.bottom - amon->amigawin_rect.top) - osd_kb_eo.height; + } + osd_kb_eo.xpos = ((amon->amigawin_rect.right - amon->amigawinclip_rect.left) - w) / 2; + if (!osd_kb_eo.data) { + return false; + } + if (!D3D_extoverlay(&osd_kb_eo, 0)) { + return false; + } + + first = true; + return true; +} diff --git a/od-win32/win32gfx.h b/od-win32/win32gfx.h index 8ceecdc6..73bef122 100644 --- a/od-win32/win32gfx.h +++ b/od-win32/win32gfx.h @@ -30,16 +30,15 @@ extern HDC gethdc(int monid); extern void releasehdc(int monid, HDC hdc); extern void close_windows(struct AmigaMonitor*); extern void updatewinfsmode(int monid, struct uae_prefs *p); -extern int is3dmode(void); extern void gfx_lock(void); extern void gfx_unlock(void); extern bool lockscr3d(struct vidbuffer *vb); extern void unlockscr3d(struct vidbuffer *vb); -void DX_Fill(struct AmigaMonitor*, int dstx, int dsty, int width, int height, uae_u32 color); -void DX_Blit(int x, int y, int w, int h); void centerdstrect(struct AmigaMonitor*, RECT *); struct MultiDisplay *getdisplay(struct uae_prefs *p, int monid); extern int getrefreshrate(int monid, int width, int height); + +bool osd_keyboard(int show); #endif diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 45d99b16..b3b37b85 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -23357,6 +23357,9 @@ static int GetSettings (int all_options, HWND hwnd) int resetcount = 0; bool boxart_reopen = false; int use_gui_control = gui_control > 0 ? 2 : -1; + if (osk_status()) { + use_gui_control = 2; + } setdefaultguisize(0); getstoredguisize(); scaleresource_setsize(-1, -1, -1); -- 2.47.3