diff --git a/src/client/cl_keyboard.c b/src/client/cl_keyboard.c index c3d5f2e5..c21b8d13 100644 --- a/src/client/cl_keyboard.c +++ b/src/client/cl_keyboard.c @@ -1419,7 +1419,8 @@ Key_Event(int key, qboolean down, qboolean special) /* FIXME: Better way to do CTRL+ actions in the console? special should be set to true in this case. */ - if (keydown[K_CTRL] && IsInConsole() && + if (keydown[K_CTRL] && + (IsInConsole() || cls.key_dest == key_menu) && key >= 'a' && key <= 'z') { special = true; diff --git a/src/client/input/sdl3.c b/src/client/input/sdl3.c index 49e41046..52b97535 100644 --- a/src/client/input/sdl3.c +++ b/src/client/input/sdl3.c @@ -864,7 +864,7 @@ IN_Update(void) break; case SDL_EVENT_GAMEPAD_REMOVED : - if (controller && event.gdevice.which == SDL_GetJoystickInstanceID(SDL_GetGamepadJoystick(controller))) { + if (controller && event.gdevice.which == SDL_GetJoystickID(SDL_GetGamepadJoystick(controller))) { Cvar_SetValue("paused", 1); IN_Controller_Shutdown(true); IN_Controller_Init(false); diff --git a/src/client/menu/header/qmenu.h b/src/client/menu/header/qmenu.h index f85da016..e7b87789 100644 --- a/src/client/menu/header/qmenu.h +++ b/src/client/menu/header/qmenu.h @@ -103,7 +103,6 @@ typedef struct int cursor; int length; int visible_length; - int visible_offset; } menufield_s; typedef struct @@ -139,6 +138,7 @@ typedef struct void M_PushMenu(menuframework_s* menu); +void Field_ResetCursor(menuframework_s *m); qboolean Field_Key(menufield_s *field, int key); void Menu_AddItem(menuframework_s *menu, void *item); diff --git a/src/client/menu/menu.c b/src/client/menu/menu.c index 4e456937..9de041ca 100644 --- a/src/client/menu/menu.c +++ b/src/client/menu/menu.c @@ -328,16 +328,13 @@ Default_MenuKey(menuframework_s *m, int key) if (m) { - menucommon_s *item; + menucommon_s *item = Menu_ItemAtCursor(m); - if ((item = Menu_ItemAtCursor(m)) != 0) + if (item && item->type == MTYPE_FIELD) { - if (item->type == MTYPE_FIELD) + if (Field_Key((menufield_s *)item, key)) { - if (Field_Key((menufield_s *)item, key)) - { - return NULL; - } + return NULL; } } } @@ -345,12 +342,19 @@ Default_MenuKey(menuframework_s *m, int key) switch (menu_key) { case K_ESCAPE: + if (m) + { + Field_ResetCursor(m); + } + M_PopMenu(); return menu_out_sound; case K_UPARROW: if (m) { + Field_ResetCursor(m); + m->cursor--; Menu_AdjustCursor(m, -1); sound = menu_move_sound; @@ -360,6 +364,8 @@ Default_MenuKey(menuframework_s *m, int key) case K_DOWNARROW: if (m) { + Field_ResetCursor(m); + m->cursor++; Menu_AdjustCursor(m, 1); sound = menu_move_sound; @@ -5247,6 +5253,7 @@ AddressBook_MenuInit(void) for (i = 0; i < NUM_ADDRESSBOOK_ENTRIES; i++) { + menufield_s *f; const cvar_t *adr; char buffer[20]; @@ -5254,19 +5261,22 @@ AddressBook_MenuInit(void) adr = Cvar_Get(buffer, "", CVAR_ARCHIVE); - s_addressbook_fields[i].generic.type = MTYPE_FIELD; - s_addressbook_fields[i].generic.name = 0; - s_addressbook_fields[i].generic.callback = 0; - s_addressbook_fields[i].generic.x = 0; - s_addressbook_fields[i].generic.y = i * 18 + 0; - s_addressbook_fields[i].generic.localdata[0] = i; - s_addressbook_fields[i].cursor = 0; - s_addressbook_fields[i].length = 60; - s_addressbook_fields[i].visible_length = 30; + f = &s_addressbook_fields[i]; - strcpy(s_addressbook_fields[i].buffer, adr->string); + f->generic.type = MTYPE_FIELD; + f->generic.name = 0; + f->generic.callback = 0; + f->generic.x = 0; + f->generic.y = i * 18 + 0; + f->generic.localdata[0] = i; - Menu_AddItem(&s_addressbook_menu, &s_addressbook_fields[i]); + f->length = 60; + f->visible_length = 30; + + Q_strlcpy(f->buffer, adr->string, f->length); + f->cursor = strlen(f->buffer); + + Menu_AddItem(&s_addressbook_menu, f); } } diff --git a/src/client/menu/qmenu.c b/src/client/menu/qmenu.c index f0e55815..92b8cd24 100644 --- a/src/client/menu/qmenu.c +++ b/src/client/menu/qmenu.c @@ -29,6 +29,9 @@ #include "../header/client.h" #include "header/qmenu.h" +void IN_GetClipboardText(char *out, size_t n); +int IN_SetClipboardText(const char *s); + static void Action_Draw(menuaction_s *a); static void Menu_DrawStatusBar(const char *string); static void MenuList_Draw(menulist_s *l); @@ -166,7 +169,8 @@ Field_Draw(menufield_s *f) n = sizeof(tempbuffer); } - Q_strlcpy(tempbuffer, f->buffer + f->visible_offset, n); + i = (f->cursor > f->visible_length) ? (f->cursor - f->visible_length) : 0; + Q_strlcpy(tempbuffer, f->buffer + i, n); Draw_CharScaled(x + (16 * scale), (y - 4) * scale, 18, scale); @@ -191,30 +195,36 @@ Field_Draw(menufield_s *f) if (Menu_ItemAtCursor(f->generic.parent) == f) { - int offset; - - if (f->visible_offset) - { - offset = f->visible_length; - } - - else - { - offset = f->cursor; - } - if (((int)(Sys_Milliseconds() / 250)) & 1) { + int offset; + + if (f->cursor > f->visible_length) + { + offset = f->visible_length; + } + else + { + offset = f->cursor; + } + Draw_CharScaled( x + (24 * scale) + (offset * (8 * scale)), y * scale, 11, scale); } - else - { - Draw_CharScaled( - x + (24 * scale) + (offset * (8 * scale)), - y * scale, ' ', scale); - } + } +} + +void +Field_ResetCursor(menuframework_s *m) +{ + menucommon_s *item = Menu_ItemAtCursor(m); + + if (item && item->type == MTYPE_FIELD) + { + menufield_s *f = (menufield_s *)item; + + f->cursor = strlen(f->buffer); } } @@ -223,36 +233,97 @@ extern int keydown[]; qboolean Field_Key(menufield_s *f, int key) { - if (key > 127) + char txt[256]; + + if (keydown[K_CTRL]) { - return false; + if (key == 'l') + { + *f->buffer = '\0'; + f->cursor = 0; + + return true; + } + + if (key == 'c' || key == 'x') + { + if (*f->buffer != '\0') + { + if (IN_SetClipboardText(f->buffer)) + { + Com_Printf("Copying menu field to clipboard failed.\n"); + } + else if (key == 'x') + { + *f->buffer = '\0'; + f->cursor = 0; + } + } + + return true; + } + + if (key == 'v') + { + IN_GetClipboardText(txt, sizeof(txt)); + + if (*txt != '\0') + { + if ((f->generic.flags & QMF_NUMBERSONLY) && !Q_strisnum(txt)) + { + return false; + } + + f->cursor += Q_strins(f->buffer, txt, f->cursor, f->length); + } + } + + return true; } switch (key) { case K_KP_LEFTARROW: case K_LEFTARROW: - case K_BACKSPACE: - if (f->cursor > 0) { - memmove(&f->buffer[f->cursor - 1], - &f->buffer[f->cursor], - strlen(&f->buffer[f->cursor]) + 1); f->cursor--; - - if (f->visible_offset) - { - f->visible_offset--; - } } + break; + case K_KP_RIGHTARROW: + case K_RIGHTARROW: + if (f->buffer[f->cursor] != '\0') + { + f->cursor++; + } + break; + + case K_BACKSPACE: + if (f->cursor > 0) + { + Q_strdel(f->buffer, f->cursor - 1, 1); + f->cursor--; + } + break; + + case K_END: + if (f->buffer[f->cursor] == '\0') + { + f->cursor = 0; + } + else + { + f->cursor = strlen(f->buffer); + } break; case K_KP_DEL: case K_DEL: - memmove(&f->buffer[f->cursor], &f->buffer[f->cursor + 1], - strlen(&f->buffer[f->cursor + 1]) + 1); + if (f->buffer[f->cursor] != '\0') + { + Q_strdel(f->buffer, f->cursor, 1); + } break; case K_KP_ENTER: @@ -261,24 +332,21 @@ Field_Key(menufield_s *f, int key) case K_TAB: return false; - case K_SPACE: default: + if (key > 127) + { + return false; + } if (!isdigit(key) && (f->generic.flags & QMF_NUMBERSONLY)) { return false; } - if (f->cursor < f->length) - { - f->buffer[f->cursor++] = key; - f->buffer[f->cursor] = 0; + *txt = key; + *(txt + 1) = '\0'; - if (f->cursor > f->visible_length) - { - f->visible_offset++; - } - } + f->cursor += Q_strins(f->buffer, txt, f->cursor, f->length); } return true; diff --git a/src/client/refresh/gl1/gl1_sdl.c b/src/client/refresh/gl1/gl1_sdl.c index 16f2cb01..3b320ffc 100644 --- a/src/client/refresh/gl1/gl1_sdl.c +++ b/src/client/refresh/gl1/gl1_sdl.c @@ -104,7 +104,11 @@ int RI_PrepareForWindow(void) SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); +#ifdef USE_SDL3 if (SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8) == 0) +#else + if (SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8)) +#endif { gl_state.stencil = true; } @@ -309,7 +313,11 @@ int RI_InitContext(void* win) if (gl_msaa_samples->value) { +#ifdef USE_SDL3 + if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaa_samples)) +#else if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaa_samples) == 0) +#endif { ri.Cvar_SetValue("r_msaa_samples", msaa_samples); } diff --git a/src/client/refresh/gl3/gl3_sdl.c b/src/client/refresh/gl3/gl3_sdl.c index 3302bbe7..16354abb 100644 --- a/src/client/refresh/gl3/gl3_sdl.c +++ b/src/client/refresh/gl3/gl3_sdl.c @@ -370,7 +370,11 @@ int GL3_InitContext(void* win) if (gl_msaa_samples->value) { +#ifdef USE_SDL3 + if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaa_samples)) +#else if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaa_samples) == 0) +#endif { ri.Cvar_SetValue("r_msaa_samples", msaa_samples); } diff --git a/src/client/vid/glimp_sdl3.c b/src/client/vid/glimp_sdl3.c index 78c884dc..215878bf 100644 --- a/src/client/vid/glimp_sdl3.c +++ b/src/client/vid/glimp_sdl3.c @@ -99,7 +99,7 @@ ClearDisplayIndices(void) } static qboolean -CreateSDLWindow(int flags, int fullscreen, int w, int h) +CreateSDLWindow(SDL_WindowFlags flags, int fullscreen, int w, int h) { if (SDL_WINDOWPOS_ISUNDEFINED(last_position_x) || SDL_WINDOWPOS_ISUNDEFINED(last_position_y) || last_position_x < 0 ||last_position_y < 24) { @@ -121,10 +121,7 @@ CreateSDLWindow(int flags, int fullscreen, int w, int h) SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, last_position_y); SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, w); SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, h); - SDL_SetNumberProperty(props, "flags", flags); - - if (flags & SDL_WINDOW_OPENGL) - SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true); + SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER, flags); window = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); @@ -457,7 +454,7 @@ GLimp_Shutdown(void) * compositor might scale us. */ static int -Glimp_DetermineHighDPISupport(int flags) +Glimp_DetermineHighDPISupport(SDL_WindowFlags flags) { /* Make sure that high dpi is never set when we don't want it. */ flags &= ~SDL_WINDOW_HIGH_PIXEL_DENSITY; @@ -484,11 +481,11 @@ Glimp_DetermineHighDPISupport(int flags) qboolean GLimp_InitGraphics(int fullscreen, int *pwidth, int *pheight) { - int flags; + SDL_WindowFlags flags; + SDL_WindowFlags fs_flag = 0; int curWidth, curHeight; int width = *pwidth; int height = *pheight; - unsigned int fs_flag = 0; if (fullscreen == FULLSCREEN_EXCLUSIVE || fullscreen == FULLSCREEN_DESKTOP) { @@ -767,18 +764,10 @@ GLimp_GrabInput(qboolean grab) SDL_SetWindowMouseGrab(window, grab ? true : false); } -#ifdef USE_SDL3 if(!SDL_SetWindowRelativeMouseMode(window, grab ? true : false)) { Com_Printf("WARNING: Setting Relative Mousemode failed, reason: %s\n", SDL_GetError()); } -#else - if(SDL_SetWindowRelativeMouseMode(window, grab ? true : false) < 0) - { - Com_Printf("WARNING: Setting Relative Mousemode failed, reason: %s\n", SDL_GetError()); - Com_Printf(" You should probably update to SDL 2.0.3 or newer!\n"); - } -#endif } /* diff --git a/src/common/header/shared.h b/src/common/header/shared.h index ba111eff..472bebda 100644 --- a/src/common/header/shared.h +++ b/src/common/header/shared.h @@ -340,6 +340,7 @@ void Q_strdel(char *s, size_t i, size_t n); /* Insert src into dest starting at index i, total, n is the total size of the buffer */ /* Returns length of src on success, 0 if there is not enough space in dest for src */ size_t Q_strins(char *dest, const char *src, size_t i, size_t n); +qboolean Q_strisnum(const char *s); /* ============================================= */ diff --git a/src/common/shared/shared.c b/src/common/shared/shared.c index 8738e18a..b7d6142f 100644 --- a/src/common/shared/shared.c +++ b/src/common/shared/shared.c @@ -1196,6 +1196,20 @@ Q_strins(char *dest, const char *src, size_t i, size_t n) return slen; } +qboolean +Q_strisnum(const char *s) +{ + for (; *s != '\0'; s++) + { + if (!isdigit(*s)) + { + return false; + } + } + + return true; +} + /* * An unicode compatible fopen() Wrapper for Windows. */