WM: Remove ASCII members from wmEvent & GHOST_TEventKeyData
The `ascii` member was only kept for historic reason as some platforms didn't support utf8 when it was first introduced. Remove the `ascii` struct members since many checks used this as a fall-back for utf8_buf not being set which isn't needed. There are a few cases where it's convenient to access the ASCII value of an event (or nil) so a function has been added to do that. *Details* - WM_event_utf8_to_ascii() has been added for the few cases an events ASCII value needs to be accessed, this just avoids having to do multi-byte character checks in-line. - RNA Event.ascii remains, using utf8_buf[0] for single byte characters. - GHOST_TEventKeyData.ascii has been removed. - To avoid regressions non-ASCII Latin1 characters from GHOST are converted into multi-byte UTF8, when building X11 without XInput & X_HAVE_UTF8_STRING it seems like could still occur.
This commit is contained in:
@@ -547,17 +547,6 @@ typedef struct {
|
||||
/** The key code. */
|
||||
GHOST_TKey key;
|
||||
|
||||
/* ascii / utf8: both should always be set when possible,
|
||||
* - ascii may be '\0' however if the user presses a non ascii key
|
||||
* - unicode may not be set if the system has no unicode support
|
||||
*
|
||||
* These values are intended to be used as follows.
|
||||
* For text input use unicode when available, fallback to ascii.
|
||||
* For areas where unicode is not needed, number input for example, always
|
||||
* use ascii, unicode is ignored - campbell.
|
||||
*/
|
||||
/** The ascii code for the key event ('\0' if none). */
|
||||
char ascii;
|
||||
/** The unicode character. if the length is 6, not NULL terminated if all 6 are set. */
|
||||
char utf8_buf[6];
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ class GHOST_EventKey : public GHOST_Event {
|
||||
: GHOST_Event(msec, type, window)
|
||||
{
|
||||
m_keyEventData.key = key;
|
||||
m_keyEventData.ascii = '\0';
|
||||
m_keyEventData.utf8_buf[0] = '\0';
|
||||
m_keyEventData.is_repeat = is_repeat;
|
||||
m_data = &m_keyEventData;
|
||||
@@ -51,11 +50,17 @@ class GHOST_EventKey : public GHOST_Event {
|
||||
: GHOST_Event(msec, type, window)
|
||||
{
|
||||
m_keyEventData.key = key;
|
||||
m_keyEventData.ascii = ascii;
|
||||
if (utf8_buf)
|
||||
if (utf8_buf) {
|
||||
memcpy(m_keyEventData.utf8_buf, utf8_buf, sizeof(m_keyEventData.utf8_buf));
|
||||
else
|
||||
}
|
||||
else {
|
||||
m_keyEventData.utf8_buf[0] = '\0';
|
||||
}
|
||||
/* TODO(@campbellbarton): phase out `ascii` and always use `utf8_buf`, this needs to be done
|
||||
* on all platforms though, so for now write the ascii into the utf8_buf. */
|
||||
if (m_keyEventData.utf8_buf[0] == '\0' && ascii) {
|
||||
m_keyEventData.utf8_buf[0] = ascii;
|
||||
}
|
||||
m_keyEventData.is_repeat = is_repeat;
|
||||
m_data = &m_keyEventData;
|
||||
}
|
||||
|
||||
@@ -218,8 +218,10 @@ void event_to_buf(GHOST_EventHandle evt, char buf[128])
|
||||
case GHOST_kEventKeyUp: {
|
||||
GHOST_TEventKeyData *kd = data;
|
||||
pos += sprintf(pos, " - key: %s (%d)", keytype_to_string(kd->key), kd->key);
|
||||
if (kd->ascii)
|
||||
pos += sprintf(pos, " ascii: '%c' (%d)", kd->ascii, kd->ascii);
|
||||
/* TODO: ideally this would print the unicode character. */
|
||||
if (kd->utf8_buf[0]) {
|
||||
pos += sprintf(pos, " ascii: '%c' (%d)", kd->utf8_buf[0], kd->utf8_buf[0]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1578,7 +1578,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
|
||||
case EVT_PADMINUS:
|
||||
if (pld->searchstr[0]) {
|
||||
/* searching... */
|
||||
poselib_preview_handle_search(pld, event->type, event->ascii);
|
||||
poselib_preview_handle_search(pld, event->type, WM_event_utf8_to_ascii(event));
|
||||
}
|
||||
else {
|
||||
/* view manipulation (see above) */
|
||||
@@ -1589,7 +1589,7 @@ static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, con
|
||||
|
||||
/* otherwise, assume that searching might be able to handle it */
|
||||
default:
|
||||
poselib_preview_handle_search(pld, event->type, event->ascii);
|
||||
poselib_preview_handle_search(pld, event->type, WM_event_utf8_to_ascii(event));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1639,7 +1639,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
Curve *cu = obedit->data;
|
||||
EditFont *ef = cu->editfont;
|
||||
static int accentcode = 0;
|
||||
uintptr_t ascii = event->ascii;
|
||||
uintptr_t ascii = WM_event_utf8_to_ascii(event);
|
||||
const bool alt = event->modifier & KM_ALT;
|
||||
const bool shift = event->modifier & KM_SHIFT;
|
||||
const bool ctrl = event->modifier & KM_CTRL;
|
||||
|
||||
@@ -3172,21 +3172,6 @@ static bool ui_textedit_insert_buf(uiBut *but,
|
||||
return changed;
|
||||
}
|
||||
|
||||
static bool ui_textedit_insert_ascii(uiBut *but, uiHandleButtonData *data, char ascii)
|
||||
{
|
||||
const char buf[2] = {ascii, '\0'};
|
||||
|
||||
if (UI_but_is_utf8(but) && (BLI_str_utf8_size(buf) == -1)) {
|
||||
printf(
|
||||
"%s: entering invalid ascii char into an ascii key (%d)\n", __func__, (int)(uchar)ascii);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* in some cases we want to allow invalid utf8 chars */
|
||||
return ui_textedit_insert_buf(but, data, buf, 1);
|
||||
}
|
||||
|
||||
static void ui_textedit_move(uiBut *but,
|
||||
uiHandleButtonData *data,
|
||||
eStrCursorJumpDirection direction,
|
||||
@@ -3897,30 +3882,27 @@ static void ui_do_but_textedit(
|
||||
}
|
||||
}
|
||||
|
||||
if ((event->ascii || event->utf8_buf[0]) && (retval == WM_UI_HANDLER_CONTINUE)
|
||||
if ((event->utf8_buf[0]) && (retval == WM_UI_HANDLER_CONTINUE)
|
||||
#ifdef WITH_INPUT_IME
|
||||
&& !is_ime_composing && !WM_event_is_ime_switch(event)
|
||||
#endif
|
||||
) {
|
||||
char ascii = event->ascii;
|
||||
char utf8_buf_override[2] = {'\0', '\0'};
|
||||
const char *utf8_buf = event->utf8_buf;
|
||||
|
||||
/* Exception that's useful for number buttons, some keyboard
|
||||
* numpads have a comma instead of a period. */
|
||||
if (ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER)) { /* Could use `data->min`. */
|
||||
if (event->type == EVT_PADPERIOD && ascii == ',') {
|
||||
ascii = '.';
|
||||
utf8_buf = NULL; /* force ascii fallback */
|
||||
if ((event->type == EVT_PADPERIOD) && (utf8_buf[0] == ',')) {
|
||||
utf8_buf_override[0] = '.';
|
||||
utf8_buf = utf8_buf_override;
|
||||
}
|
||||
}
|
||||
|
||||
if (utf8_buf && utf8_buf[0]) {
|
||||
if (utf8_buf[0]) {
|
||||
const int utf8_buf_len = BLI_str_utf8_size(utf8_buf);
|
||||
BLI_assert(utf8_buf_len != -1);
|
||||
changed = ui_textedit_insert_buf(but, data, event->utf8_buf, utf8_buf_len);
|
||||
}
|
||||
else {
|
||||
changed = ui_textedit_insert_ascii(but, data, ascii);
|
||||
changed = ui_textedit_insert_buf(but, data, utf8_buf, utf8_buf_len);
|
||||
}
|
||||
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
|
||||
@@ -413,16 +413,8 @@ static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *eve
|
||||
}
|
||||
|
||||
char str[BLI_UTF8_MAX + 1];
|
||||
size_t len;
|
||||
|
||||
if (event->utf8_buf[0]) {
|
||||
len = BLI_str_utf8_size_safe(event->utf8_buf);
|
||||
memcpy(str, event->utf8_buf, len);
|
||||
}
|
||||
else {
|
||||
/* in theory, ghost can set value to extended ascii here */
|
||||
len = BLI_str_utf8_from_unicode(event->ascii, str, sizeof(str) - 1);
|
||||
}
|
||||
const size_t len = BLI_str_utf8_size_safe(event->utf8_buf);
|
||||
memcpy(str, event->utf8_buf, len);
|
||||
str[len] = '\0';
|
||||
RNA_string_set(op->ptr, "text", str);
|
||||
}
|
||||
|
||||
@@ -3396,7 +3396,8 @@ static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), const wm
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
if (!(event->ascii >= '0' && event->ascii <= '9')) {
|
||||
const char event_ascii = WM_event_utf8_to_ascii(event);
|
||||
if (!(event_ascii >= '0' && event_ascii <= '9')) {
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
@@ -3406,7 +3407,7 @@ static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), const wm
|
||||
}
|
||||
|
||||
jump_to *= 10;
|
||||
jump_to += (int)(event->ascii - '0');
|
||||
jump_to += (int)(event_ascii - '0');
|
||||
|
||||
txt_move_toline(text, jump_to - 1, 0);
|
||||
last_jump = time;
|
||||
@@ -3495,16 +3496,8 @@ static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
}
|
||||
|
||||
char str[BLI_UTF8_MAX + 1];
|
||||
size_t len;
|
||||
|
||||
if (event->utf8_buf[0]) {
|
||||
len = BLI_str_utf8_size_safe(event->utf8_buf);
|
||||
memcpy(str, event->utf8_buf, len);
|
||||
}
|
||||
else {
|
||||
/* in theory, ghost can set value to extended ascii here */
|
||||
len = BLI_str_utf8_from_unicode(event->ascii, str, sizeof(str) - 1);
|
||||
}
|
||||
const size_t len = BLI_str_utf8_size_safe(event->utf8_buf);
|
||||
memcpy(str, event->utf8_buf, len);
|
||||
str[len] = '\0';
|
||||
RNA_string_set(op->ptr, "text", str);
|
||||
|
||||
|
||||
@@ -311,6 +311,7 @@ static bool editstr_is_simple_numinput(const char ascii)
|
||||
bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
|
||||
{
|
||||
const char *utf8_buf = NULL;
|
||||
const char event_ascii = WM_event_utf8_to_ascii(event);
|
||||
char ascii[2] = {'\0', '\0'};
|
||||
bool updated = false;
|
||||
short idx = n->idx, idx_max = n->idx_max;
|
||||
@@ -321,8 +322,8 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
|
||||
if (U.flag & USER_FLAG_NUMINPUT_ADVANCED)
|
||||
#endif
|
||||
{
|
||||
if (((event->modifier & (KM_CTRL | KM_ALT)) == 0) && (event->ascii != '\0') &&
|
||||
strchr("01234567890@%^&*-+/{}()[]<>.|", event->ascii)) {
|
||||
if (((event->modifier & (KM_CTRL | KM_ALT)) == 0) && (event_ascii != '\0') &&
|
||||
strchr("01234567890@%^&*-+/{}()[]<>.|", event_ascii)) {
|
||||
if (!(n->flag & NUM_EDIT_FULL)) {
|
||||
n->flag |= NUM_EDITED;
|
||||
n->flag |= NUM_EDIT_FULL;
|
||||
@@ -333,7 +334,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
|
||||
|
||||
#ifdef USE_FAKE_EDIT
|
||||
/* XXX Hack around keyboards without direct access to '=' nor '*'... */
|
||||
if (ELEM(event->ascii, '=', '*')) {
|
||||
if (ELEM(event_ascii, '=', '*')) {
|
||||
if (!(n->flag & NUM_EDIT_FULL)) {
|
||||
n->flag |= NUM_EDIT_FULL;
|
||||
n->val_flag[idx] |= NUM_EDITED;
|
||||
@@ -357,7 +358,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
|
||||
else {
|
||||
/* might be a char too... */
|
||||
utf8_buf = event->utf8_buf;
|
||||
ascii[0] = event->ascii;
|
||||
ascii[0] = event_ascii;
|
||||
}
|
||||
break;
|
||||
case EVT_BACKSPACEKEY:
|
||||
@@ -523,9 +524,9 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!updated && !utf8_buf && (event->utf8_buf[0] || event->ascii)) {
|
||||
if (!updated && !utf8_buf && event->utf8_buf[0]) {
|
||||
utf8_buf = event->utf8_buf;
|
||||
ascii[0] = event->ascii;
|
||||
ascii[0] = event_ascii;
|
||||
}
|
||||
|
||||
/* Up to this point, if we have a ctrl modifier, skip.
|
||||
|
||||
@@ -607,14 +607,14 @@ static PointerRNA rna_OperatorMacro_properties_get(PointerRNA *ptr)
|
||||
static void rna_Event_ascii_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
const wmEvent *event = ptr->data;
|
||||
value[0] = event->ascii;
|
||||
value[0] = WM_event_utf8_to_ascii(event);
|
||||
value[1] = '\0';
|
||||
}
|
||||
|
||||
static int rna_Event_ascii_length(PointerRNA *ptr)
|
||||
{
|
||||
const wmEvent *event = ptr->data;
|
||||
return (event->ascii) ? 1 : 0;
|
||||
return WM_event_utf8_to_ascii(event) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void rna_Event_unicode_get(PointerRNA *ptr, char *value)
|
||||
|
||||
@@ -639,16 +639,12 @@ static wmEvent *rna_Window_event_add_simulate(wmWindow *win,
|
||||
}
|
||||
/* TODO: validate NDOF. */
|
||||
|
||||
char ascii = 0;
|
||||
if (unicode != NULL) {
|
||||
int len = BLI_str_utf8_size(unicode);
|
||||
if (len == -1 || unicode[len] != '\0') {
|
||||
BKE_report(reports, RPT_ERROR, "Only a single character supported");
|
||||
return NULL;
|
||||
}
|
||||
if (len == 1 && isascii(unicode[0])) {
|
||||
ascii = unicode[0];
|
||||
}
|
||||
}
|
||||
|
||||
wmEvent e = *win->eventstate;
|
||||
@@ -672,10 +668,8 @@ static wmEvent *rna_Window_event_add_simulate(wmWindow *win,
|
||||
e.modifier |= KM_OSKEY;
|
||||
}
|
||||
|
||||
e.ascii = '\0';
|
||||
e.utf8_buf[0] = '\0';
|
||||
if (unicode != NULL) {
|
||||
e.ascii = ascii;
|
||||
STRNCPY(e.utf8_buf, unicode);
|
||||
}
|
||||
|
||||
|
||||
@@ -1530,6 +1530,7 @@ bool WM_event_is_modal_drag_exit(const struct wmEvent *event,
|
||||
bool WM_event_is_mouse_drag(const struct wmEvent *event);
|
||||
bool WM_event_is_mouse_drag_or_press(const wmEvent *event);
|
||||
int WM_event_drag_direction(const wmEvent *event);
|
||||
char WM_event_utf8_to_ascii(const struct wmEvent *event) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* Detect motion between selection (callers should only use this for selection picking),
|
||||
|
||||
@@ -683,13 +683,11 @@ typedef struct wmEvent {
|
||||
/** Region relative mouse position (name convention before Blender 2.5). */
|
||||
int mval[2];
|
||||
/**
|
||||
* From, ghost if utf8 is enabled for the platform,
|
||||
* #BLI_str_utf8_size() must _always_ be valid, check
|
||||
* when assigning s we don't need to check on every access after.
|
||||
* A single UTF8 encoded character.
|
||||
* #BLI_str_utf8_size() must _always_ return a valid value,
|
||||
* check when assigning so we don't need to check on every access after.
|
||||
*/
|
||||
char utf8_buf[6];
|
||||
/** From ghost, fallback if utf8 isn't set. */
|
||||
char ascii;
|
||||
|
||||
/** Modifier states: #KM_SHIFT, #KM_CTRL, #KM_ALT & #KM_OSKEY. */
|
||||
uint8_t modifier;
|
||||
|
||||
@@ -112,7 +112,7 @@ void WM_event_print(const wmEvent *event)
|
||||
"wmEvent type:%d/%s, val:%d/%s, "
|
||||
"prev_type:%d/%s, prev_val:%d/%s, "
|
||||
"modifier=%s, keymodifier:%d, flag:%s, "
|
||||
"mouse:(%d,%d), ascii:'%c', utf8:'%.*s', pointer:%p",
|
||||
"mouse:(%d,%d), utf8:'%.*s', pointer:%p",
|
||||
event->type,
|
||||
type_id,
|
||||
event->val,
|
||||
@@ -126,7 +126,6 @@ void WM_event_print(const wmEvent *event)
|
||||
flag_id,
|
||||
event->xy[0],
|
||||
event->xy[1],
|
||||
event->ascii,
|
||||
BLI_str_utf8_size(event->utf8_buf),
|
||||
event->utf8_buf,
|
||||
(const void *)event);
|
||||
@@ -400,6 +399,20 @@ void WM_event_drag_start_xy(const wmEvent *event, int r_xy[2])
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Event Text Queries
|
||||
* \{ */
|
||||
|
||||
char WM_event_utf8_to_ascii(const struct wmEvent *event)
|
||||
{
|
||||
if (BLI_str_utf8_size(event->utf8_buf) == 1) {
|
||||
return event->utf8_buf[0];
|
||||
}
|
||||
return '\0';
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Event Preference Mapping
|
||||
* \{ */
|
||||
|
||||
@@ -2088,7 +2088,7 @@ static bool wm_eventmatch(const wmEvent *winevent, const wmKeyMapItem *kmi)
|
||||
if (winevent->val == KM_PRESS) { /* Prevent double clicks. */
|
||||
/* Not using #ISTEXTINPUT anymore because (at least on Windows) some key codes above 255
|
||||
* could have printable ascii keys, See T30479. */
|
||||
if (ISKEYBOARD(winevent->type) && (winevent->ascii || winevent->utf8_buf[0])) {
|
||||
if (ISKEYBOARD(winevent->type) && winevent->utf8_buf[0]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -5042,7 +5042,6 @@ static wmEvent *wm_event_add_mousemove_to_head(wmWindow *win)
|
||||
tevent = *event_last;
|
||||
|
||||
tevent.flag = (eWM_EventFlag)0;
|
||||
tevent.ascii = '\0';
|
||||
tevent.utf8_buf[0] = '\0';
|
||||
|
||||
wm_event_custom_clear(&tevent);
|
||||
@@ -5329,7 +5328,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
|
||||
break;
|
||||
}
|
||||
|
||||
event.ascii = kd->ascii;
|
||||
/* Might be not nullptr terminated. */
|
||||
memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf));
|
||||
if (kd->is_repeat) {
|
||||
@@ -5341,8 +5339,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
|
||||
|
||||
/* Exclude arrow keys, escape, etc from text input. */
|
||||
if (type == GHOST_kEventKeyUp) {
|
||||
event.ascii = '\0';
|
||||
|
||||
/* Ghost should do this already for key up. */
|
||||
if (event.utf8_buf[0]) {
|
||||
CLOG_ERROR(WM_LOG_EVENTS,
|
||||
@@ -5351,15 +5347,28 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void
|
||||
event.utf8_buf[0] = '\0';
|
||||
}
|
||||
else {
|
||||
if (event.ascii < 32 && event.ascii > 0) {
|
||||
event.ascii = '\0';
|
||||
}
|
||||
if (event.utf8_buf[0] < 32 && event.utf8_buf[0] > 0) {
|
||||
event.utf8_buf[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (event.utf8_buf[0]) {
|
||||
/* NOTE(@campbellbarton): Detect non-ASCII characters stored in `utf8_buf`,
|
||||
* ideally this would never happen but it can't be ruled out for X11 which has
|
||||
* special handling of Latin1 when building without UTF8 support.
|
||||
* Avoid regressions by adding this conversions, it should eventually be removed. */
|
||||
if ((event.utf8_buf[0] >= 0x80) && (event.utf8_buf[1] == '\0')) {
|
||||
const uint c = (uint)event.utf8_buf[0];
|
||||
int utf8_buf_len = BLI_str_utf8_from_unicode(c, event.utf8_buf, sizeof(event.utf8_buf));
|
||||
CLOG_ERROR(WM_LOG_EVENTS,
|
||||
"ghost detected non-ASCII single byte character '%u', converting to utf8 "
|
||||
"('%.*s', length=%d)",
|
||||
c,
|
||||
utf8_buf_len,
|
||||
event.utf8_buf,
|
||||
utf8_buf_len);
|
||||
}
|
||||
|
||||
if (BLI_str_utf8_size(event.utf8_buf) == -1) {
|
||||
CLOG_ERROR(WM_LOG_EVENTS,
|
||||
"ghost detected an invalid unicode character '%d'",
|
||||
|
||||
@@ -1148,7 +1148,6 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_pt
|
||||
*/
|
||||
GHOST_TEventKeyData kdata = {
|
||||
.key = GHOST_kKeyUnknown,
|
||||
.ascii = '\0',
|
||||
.utf8_buf = {'\0'},
|
||||
.is_repeat = false,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user