forked from 12to11/12to11
Minor fixes to input method handling
* compositor.h (struct _TextInputFuncs): Make filter_input return a KeySym. (ConfigureWidth, ConfigureHeight): Remove macros. * seat.c (LookupKeysym): New function. (DispatchKey): Handle keysym return from filter input function. * text_input.c (CurrentCursorX, CurrentCursorY, CurrentCursorWidth) (CurrentCursorHeight): New functions. (DoGeometryAllocation, Commit): Handle scaling correctly. (ConvertWcharString, PreeditDrawCallback): Handle wide character strings. (CreateIC): Do geometry allocation before setting the focus, not after. (LookupString): Only prefer keysym if control chars were returned. (FilterInputCallback): Return keysym. (XLTextInputDispatchCoreEvent): Improve debugging code. * xdg_toplevel.c (HandleConfigureEvent): Fix scaling of event coordinates during resize.
This commit is contained in:
parent
b6dec13e99
commit
694952b7f7
4 changed files with 252 additions and 88 deletions
|
@ -1275,7 +1275,7 @@ struct _TextInputFuncs
|
||||||
void (*focus_out) (Seat *);
|
void (*focus_out) (Seat *);
|
||||||
|
|
||||||
/* The last argument is actually an XIDeviceEvent *. */
|
/* The last argument is actually an XIDeviceEvent *. */
|
||||||
Bool (*filter_input) (Seat *, Surface *, void *);
|
Bool (*filter_input) (Seat *, Surface *, void *, KeySym *);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void XLTextInputDispatchCoreEvent (Surface *, XEvent *);
|
extern void XLTextInputDispatchCoreEvent (Surface *, XEvent *);
|
||||||
|
@ -1518,6 +1518,3 @@ extern void XLInitSinglePixelBuffer (void);
|
||||||
#define IntSubtractWrapv(a, b, r) __builtin_sub_overflow (a, b, r)
|
#define IntSubtractWrapv(a, b, r) __builtin_sub_overflow (a, b, r)
|
||||||
#define IntMultiplyWrapv(a, b, r) __builtin_mul_overflow (a, b, r)
|
#define IntMultiplyWrapv(a, b, r) __builtin_mul_overflow (a, b, r)
|
||||||
|
|
||||||
#define ConfigureWidth(event) ((event)->xconfigure.width / global_scale_factor)
|
|
||||||
#define ConfigureHeight(event) ((event)->xconfigure.height / global_scale_factor)
|
|
||||||
|
|
||||||
|
|
49
seat.c
49
seat.c
|
@ -4017,10 +4017,31 @@ DispatchButton (Subcompositor *subcompositor, XIDeviceEvent *xev)
|
||||||
xev->event_x, xev->event_y);
|
xev->event_x, xev->event_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static KeySym
|
||||||
|
LookupKeysym (XIDeviceEvent *xev, KeyCode keycode)
|
||||||
|
{
|
||||||
|
unsigned int state, mods_return;
|
||||||
|
KeySym keysym;
|
||||||
|
|
||||||
|
/* Convert the state to a core state mask. */
|
||||||
|
state = ((xev->mods.effective & ~(1 << 13 | 1 << 14))
|
||||||
|
| (xev->group.effective << 13));
|
||||||
|
keysym = 0;
|
||||||
|
|
||||||
|
/* Look up the keysym. */
|
||||||
|
XkbLookupKeySym (compositor.display, keycode,
|
||||||
|
state, &mods_return, &keysym);
|
||||||
|
|
||||||
|
/* Return the keysym. */
|
||||||
|
return keysym;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DispatchKey (XIDeviceEvent *xev)
|
DispatchKey (XIDeviceEvent *xev)
|
||||||
{
|
{
|
||||||
Seat *seat;
|
Seat *seat;
|
||||||
|
KeySym keysym;
|
||||||
|
KeyCode keycode;
|
||||||
|
|
||||||
seat = XLLookUpAssoc (seats, xev->deviceid);
|
seat = XLLookUpAssoc (seats, xev->deviceid);
|
||||||
|
|
||||||
|
@ -4033,10 +4054,12 @@ DispatchKey (XIDeviceEvent *xev)
|
||||||
|
|
||||||
if (seat->focus_surface)
|
if (seat->focus_surface)
|
||||||
{
|
{
|
||||||
|
keysym = 0;
|
||||||
|
|
||||||
if (input_funcs
|
if (input_funcs
|
||||||
&& seat->flags & IsTextInputSeat
|
&& seat->flags & IsTextInputSeat
|
||||||
&& input_funcs->filter_input (seat, seat->focus_surface,
|
&& input_funcs->filter_input (seat, seat->focus_surface,
|
||||||
xev))
|
xev, &keysym))
|
||||||
/* The input method decided to filter the key. */
|
/* The input method decided to filter the key. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -4044,13 +4067,33 @@ DispatchKey (XIDeviceEvent *xev)
|
||||||
if (xev->flags & XIKeyRepeat)
|
if (xev->flags & XIKeyRepeat)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
keycode = xev->detail;
|
||||||
|
|
||||||
|
/* If the input method specified a keysym to use, use it. */
|
||||||
|
|
||||||
|
if (keysym)
|
||||||
|
{
|
||||||
|
/* If looking up the event keycode also results in the
|
||||||
|
keysym, then just use the keycode specified in the
|
||||||
|
event. */
|
||||||
|
if (LookupKeysym (xev, keycode) == keysym)
|
||||||
|
keycode = xev->detail;
|
||||||
|
else
|
||||||
|
keycode = XKeysymToKeycode (compositor.display, keysym);
|
||||||
|
|
||||||
|
/* But if no corresponding keycode could be found, use the
|
||||||
|
keycode provided in the event. */
|
||||||
|
if (!keycode)
|
||||||
|
keycode = xev->detail;
|
||||||
|
}
|
||||||
|
|
||||||
if (xev->evtype == XI_KeyPress)
|
if (xev->evtype == XI_KeyPress)
|
||||||
SendKeyboardKey (seat, seat->focus_surface,
|
SendKeyboardKey (seat, seat->focus_surface,
|
||||||
xev->time, WaylandKeycode (xev->detail),
|
xev->time, WaylandKeycode (keycode),
|
||||||
WL_KEYBOARD_KEY_STATE_PRESSED);
|
WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||||
else
|
else
|
||||||
SendKeyboardKey (seat, seat->focus_surface,
|
SendKeyboardKey (seat, seat->focus_surface,
|
||||||
xev->time, WaylandKeycode (xev->detail),
|
xev->time, WaylandKeycode (keycode),
|
||||||
WL_KEYBOARD_KEY_STATE_RELEASED);
|
WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
271
text_input.c
271
text_input.c
|
@ -241,6 +241,70 @@ static XIMStyle xim_style;
|
||||||
/* The order in which XIM input styles will be searched for. */
|
/* The order in which XIM input styles will be searched for. */
|
||||||
static XimStyleKind xim_style_order[5];
|
static XimStyleKind xim_style_order[5];
|
||||||
|
|
||||||
|
static int
|
||||||
|
CurrentCursorX (TextInput *input)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
XLAssert (input->client_info->focus_surface != NULL);
|
||||||
|
|
||||||
|
/* Scale these coordinates into window coordinates. */
|
||||||
|
TruncateSurfaceToWindow (input->client_info->focus_surface,
|
||||||
|
input->current_state.cursor_x,
|
||||||
|
input->current_state.cursor_y,
|
||||||
|
&x, &y);
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
CurrentCursorY (TextInput *input)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
XLAssert (input->client_info->focus_surface != NULL);
|
||||||
|
|
||||||
|
/* Scale these coordinates into window coordinates. */
|
||||||
|
TruncateSurfaceToWindow (input->client_info->focus_surface,
|
||||||
|
input->current_state.cursor_x,
|
||||||
|
input->current_state.cursor_y,
|
||||||
|
&x, &y);
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
CurrentCursorWidth (TextInput *input)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
XLAssert (input->client_info->focus_surface != NULL);
|
||||||
|
|
||||||
|
/* Scale these coordinates into window coordinates. */
|
||||||
|
TruncateScaleToWindow (input->client_info->focus_surface,
|
||||||
|
input->current_state.cursor_width,
|
||||||
|
input->current_state.cursor_height,
|
||||||
|
&width, &height);
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
CurrentCursorHeight (TextInput *input)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
XLAssert (input->client_info->focus_surface != NULL);
|
||||||
|
|
||||||
|
/* Scale these coordinates into window coordinates. */
|
||||||
|
TruncateScaleToWindow (input->client_info->focus_surface,
|
||||||
|
input->current_state.cursor_width,
|
||||||
|
input->current_state.cursor_height,
|
||||||
|
&width, &height);
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Byte-text position conversion. */
|
/* Byte-text position conversion. */
|
||||||
|
|
||||||
|
@ -558,7 +622,7 @@ static void
|
||||||
DoGeometryAllocation (TextInput *input)
|
DoGeometryAllocation (TextInput *input)
|
||||||
{
|
{
|
||||||
XPoint spot;
|
XPoint spot;
|
||||||
XRectangle area, needed;
|
XRectangle area, *needed;
|
||||||
XVaNestedList attr;
|
XVaNestedList attr;
|
||||||
View *view;
|
View *view;
|
||||||
char *rc;
|
char *rc;
|
||||||
|
@ -577,9 +641,9 @@ DoGeometryAllocation (TextInput *input)
|
||||||
|
|
||||||
if (input->current_state.pending & PendingCursorRectangle)
|
if (input->current_state.pending & PendingCursorRectangle)
|
||||||
{
|
{
|
||||||
spot.x = input->current_state.cursor_x;
|
spot.x = CurrentCursorX (input);
|
||||||
spot.y = (input->current_state.cursor_y
|
spot.y = (CurrentCursorY (input)
|
||||||
+ input->current_state.cursor_height - 1);
|
+ CurrentCursorHeight (input));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -611,44 +675,46 @@ DoGeometryAllocation (TextInput *input)
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
DebugPrint ("IM suggested the given size: %d %d",
|
DebugPrint ("IM suggested the given size: %d %d",
|
||||||
needed.width, needed.height);
|
needed->width, needed->height);
|
||||||
|
|
||||||
/* Place the rectangle below and to the right of the
|
/* Place the rectangle below and to the right of the
|
||||||
caret. */
|
caret. */
|
||||||
|
|
||||||
if (input->current_state.pending & PendingCursorRectangle)
|
if (input->current_state.pending & PendingCursorRectangle)
|
||||||
{
|
{
|
||||||
needed.x = (input->current_state.cursor_x
|
needed->x = (CurrentCursorX (input)
|
||||||
+ input->current_state.cursor_width);
|
+ CurrentCursorWidth (input));
|
||||||
needed.y = (input->current_state.cursor_y
|
needed->y = (CurrentCursorY (input)
|
||||||
+ input->current_state.cursor_height);
|
+ CurrentCursorHeight (input));
|
||||||
|
|
||||||
FitRect (&needed, ViewWidth (view), ViewHeight (view),
|
FitRect (needed, ViewWidth (view), ViewHeight (view),
|
||||||
input->current_state.cursor_x,
|
CurrentCursorX (input), CurrentCursorY (input),
|
||||||
input->current_state.cursor_y,
|
CurrentCursorWidth (input),
|
||||||
input->current_state.cursor_width,
|
CurrentCursorHeight (input));
|
||||||
input->current_state.cursor_height);
|
|
||||||
|
|
||||||
DebugPrint ("filled rectangle: %d %d %d %d",
|
DebugPrint ("filled rectangle: %d %d %d %d",
|
||||||
needed.x, needed.y, needed.width,
|
needed->x, needed->y, needed->width,
|
||||||
needed.height);
|
needed->height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* No caret was specified... Place the preedit window on
|
/* No caret was specified... Place the preedit window on
|
||||||
the bottom right corner of the view. */
|
the bottom left corner of the view. */
|
||||||
needed.x = ViewWidth (view);
|
needed->x = 0;
|
||||||
needed.y = ViewHeight (view);
|
needed->y = ViewHeight (view) - needed->height;
|
||||||
|
|
||||||
DebugPrint ("placed rectangle: %d %d %d %d",
|
DebugPrint ("placed rectangle: %d %d %d %d",
|
||||||
needed.x, needed.y, needed.width,
|
needed->x, needed->y, needed->width,
|
||||||
needed.height);
|
needed->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the geometry. */
|
/* Set the geometry. */
|
||||||
attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
|
attr = XVaCreateNestedList (0, XNArea, needed, NULL);
|
||||||
XSetICValues (input->xic, XNPreeditAttributes, attr, NULL);
|
XSetICValues (input->xic, XNPreeditAttributes, attr, NULL);
|
||||||
XFree (attr);
|
XFree (attr);
|
||||||
|
|
||||||
|
/* Free the rectangle returned. */
|
||||||
|
XFree (needed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,44 +737,23 @@ DoGeometryAllocation (TextInput *input)
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
DebugPrint ("IM suggested the given size: %d %d",
|
DebugPrint ("IM suggested the given size: %d %d",
|
||||||
needed.width, needed.height);
|
needed->width, needed->height);
|
||||||
|
|
||||||
/* Place the rectangle below and to the right of the
|
/* Place the rectangle at the bottom of the window. */
|
||||||
caret. */
|
needed->x = ViewWidth (view) - needed->width;
|
||||||
|
needed->y = ViewHeight (view) - needed->height;
|
||||||
|
|
||||||
if (input->current_state.pending & PendingCursorRectangle)
|
DebugPrint ("placed rectangle at bottom right: %d %d %d %d",
|
||||||
{
|
needed->x, needed->y, needed->width,
|
||||||
needed.x = (input->current_state.cursor_x
|
needed->height);
|
||||||
+ input->current_state.cursor_width);
|
|
||||||
needed.y = (input->current_state.cursor_y
|
|
||||||
+ input->current_state.cursor_height);
|
|
||||||
|
|
||||||
FitRect (&needed, ViewWidth (view), ViewHeight (view),
|
|
||||||
input->current_state.cursor_x,
|
|
||||||
input->current_state.cursor_y,
|
|
||||||
input->current_state.cursor_width,
|
|
||||||
input->current_state.cursor_height);
|
|
||||||
|
|
||||||
DebugPrint ("filled rectangle: %d %d %d %d",
|
|
||||||
needed.x, needed.y, needed.width,
|
|
||||||
needed.height);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No caret was specified... Place the preedit window on
|
|
||||||
the bottom right corner of the view. */
|
|
||||||
needed.x = ViewWidth (view);
|
|
||||||
needed.y = ViewHeight (view);
|
|
||||||
|
|
||||||
DebugPrint ("placed rectangle: %d %d %d %d",
|
|
||||||
needed.x, needed.y, needed.width,
|
|
||||||
needed.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the geometry. */
|
/* Set the geometry. */
|
||||||
attr = XVaCreateNestedList (0, XNArea, &needed, NULL);
|
attr = XVaCreateNestedList (0, XNArea, needed, NULL);
|
||||||
XSetICValues (input->xic, XNStatusAttributes, attr, NULL);
|
XSetICValues (input->xic, XNStatusAttributes, attr, NULL);
|
||||||
XFree (attr);
|
XFree (attr);
|
||||||
|
|
||||||
|
/* Free the needed rectangle. */
|
||||||
|
XFree (needed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -770,11 +815,11 @@ Commit (struct wl_client *client, struct wl_resource *resource)
|
||||||
else
|
else
|
||||||
XFree (XmbResetIC (input->xic));
|
XFree (XmbResetIC (input->xic));
|
||||||
|
|
||||||
if (input->xic)
|
|
||||||
XSetICFocus (input->xic);
|
|
||||||
|
|
||||||
/* Perform geometry/position allocation on the IC. */
|
/* Perform geometry/position allocation on the IC. */
|
||||||
DoGeometryAllocation (input);
|
DoGeometryAllocation (input);
|
||||||
|
|
||||||
|
if (input->xic)
|
||||||
|
XSetICFocus (input->xic);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1512,12 +1557,62 @@ PreeditDoneCallback (XIC ic, XPointer client_data, XPointer call_data)
|
||||||
UpdatePreedit (input);
|
UpdatePreedit (input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ConvertWcharString (PreeditBuffer *buffer, const wchar_t *input,
|
||||||
|
size_t input_size, size_t *string_size)
|
||||||
|
{
|
||||||
|
char *output, *oldlocale;
|
||||||
|
int rc;
|
||||||
|
size_t bytes;
|
||||||
|
|
||||||
|
/* Since the text is intended for BUFFER, switch to BUFFER's
|
||||||
|
locale. */
|
||||||
|
oldlocale = XLStrdup (setlocale (LC_CTYPE, NULL));
|
||||||
|
|
||||||
|
/* Switch to the new locale. */
|
||||||
|
if (!setlocale (LC_CTYPE, buffer->locale))
|
||||||
|
{
|
||||||
|
/* Setting the locale failed. Return an empty string. */
|
||||||
|
XLFree (oldlocale);
|
||||||
|
*string_size = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = XLCalloc (input_size + 1, MB_CUR_MAX);
|
||||||
|
bytes = 0;
|
||||||
|
|
||||||
|
while (input_size)
|
||||||
|
{
|
||||||
|
input_size--;
|
||||||
|
rc = wctomb (output + bytes, *input++);
|
||||||
|
|
||||||
|
if (rc == -1)
|
||||||
|
/* Invalid wide character code. */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Otherwise, move the string forward this much. */
|
||||||
|
bytes += rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the string and the number of bytes put in it. */
|
||||||
|
*string_size = bytes;
|
||||||
|
|
||||||
|
/* Clear shift state. */
|
||||||
|
wctomb (NULL, L'\0');
|
||||||
|
|
||||||
|
/* Restore the old locale. */
|
||||||
|
setlocale (LC_CTYPE, oldlocale);
|
||||||
|
XLFree (oldlocale);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
PreeditDrawCallback (XIC ic, XPointer client_data,
|
PreeditDrawCallback (XIC ic, XPointer client_data,
|
||||||
XIMPreeditDrawCallbackStruct *call_data)
|
XIMPreeditDrawCallbackStruct *call_data)
|
||||||
{
|
{
|
||||||
TextInput *input;
|
TextInput *input;
|
||||||
size_t string_size;
|
size_t string_size;
|
||||||
|
char *multi_byte_string;
|
||||||
|
|
||||||
input = (TextInput *) client_data;
|
input = (TextInput *) client_data;
|
||||||
DebugPrint ("text input: %p", input);
|
DebugPrint ("text input: %p", input);
|
||||||
|
@ -1529,13 +1624,6 @@ PreeditDrawCallback (XIC ic, XPointer client_data,
|
||||||
call_data->chg_first,
|
call_data->chg_first,
|
||||||
call_data->chg_length);
|
call_data->chg_length);
|
||||||
|
|
||||||
if (call_data->text
|
|
||||||
&& call_data->text->encoding_is_wchar)
|
|
||||||
{
|
|
||||||
DebugPrint ("wchar encoding not yet implemented");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete text between chg_first and chg_first + chg_length. */
|
/* Delete text between chg_first and chg_first + chg_length. */
|
||||||
if (call_data->chg_length
|
if (call_data->chg_length
|
||||||
&& !PreeditDeleteChars (input->buffer, call_data->chg_first,
|
&& !PreeditDeleteChars (input->buffer, call_data->chg_first,
|
||||||
|
@ -1547,17 +1635,35 @@ PreeditDrawCallback (XIC ic, XPointer client_data,
|
||||||
|
|
||||||
if (call_data->text)
|
if (call_data->text)
|
||||||
{
|
{
|
||||||
/* The multibyte string should be NULL terminated. */
|
if (call_data->text->encoding_is_wchar)
|
||||||
string_size = strlen (call_data->text->string.multi_byte);
|
{
|
||||||
|
DebugPrint ("converting wide character string");
|
||||||
|
|
||||||
|
multi_byte_string
|
||||||
|
= ConvertWcharString (input->buffer,
|
||||||
|
call_data->text->string.wide_char,
|
||||||
|
call_data->text->length,
|
||||||
|
&string_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The multibyte string should be NULL terminated. */
|
||||||
|
string_size = strlen (call_data->text->string.multi_byte);
|
||||||
|
multi_byte_string = call_data->text->string.multi_byte;
|
||||||
|
}
|
||||||
|
|
||||||
DebugPrint ("inserting text of size %d, %zu",
|
DebugPrint ("inserting text of size %d, %zu",
|
||||||
call_data->text->length, string_size);
|
call_data->text->length, string_size);
|
||||||
|
|
||||||
/* Now, insert whatever text was specified at chg_first. */
|
/* Now, insert whatever text was specified at chg_first. */
|
||||||
if (!PreeditInsertChars (input->buffer, call_data->chg_first,
|
if (!PreeditInsertChars (input->buffer, call_data->chg_first,
|
||||||
call_data->text->string.multi_byte,
|
multi_byte_string, string_size,
|
||||||
string_size, call_data->text->length))
|
call_data->text->length))
|
||||||
DebugPrint ("insertion failed");
|
DebugPrint ("insertion failed");
|
||||||
|
|
||||||
|
if (call_data->text->encoding_is_wchar)
|
||||||
|
/* We must free the conversion results. */
|
||||||
|
XLFree (multi_byte_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now set the caret position. */
|
/* Now set the caret position. */
|
||||||
|
@ -2279,9 +2385,9 @@ CreateIC (TextInput *input)
|
||||||
|
|
||||||
if (input->current_state.pending & PendingCursorRectangle)
|
if (input->current_state.pending & PendingCursorRectangle)
|
||||||
{
|
{
|
||||||
spot.x = input->current_state.cursor_x;
|
spot.x = CurrentCursorX (input);
|
||||||
spot.y = (input->current_state.cursor_y
|
spot.y = (CurrentCursorY (input)
|
||||||
+ input->current_state.cursor_height - 1);
|
+ CurrentCursorHeight (input));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3021,6 +3127,12 @@ LookupString (TextInput *input, XEvent *event, KeySym *keysym_return)
|
||||||
Status status;
|
Status status;
|
||||||
KeySym keysym;
|
KeySym keysym;
|
||||||
|
|
||||||
|
if (event->xkey.type != KeyPress)
|
||||||
|
{
|
||||||
|
DebugPrint ("ignoring key release event");
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
/* First, do XmbLookupString with the default buffer size. */
|
/* First, do XmbLookupString with the default buffer size. */
|
||||||
buffer = alloca (256);
|
buffer = alloca (256);
|
||||||
nbytes = XmbLookupString (input->xic, &event->xkey,
|
nbytes = XmbLookupString (input->xic, &event->xkey,
|
||||||
|
@ -3059,11 +3171,12 @@ LookupString (TextInput *input, XEvent *event, KeySym *keysym_return)
|
||||||
/* Convert the string. */
|
/* Convert the string. */
|
||||||
buffer = ConvertString (buffer, nbytes, &buffer_size);
|
buffer = ConvertString (buffer, nbytes, &buffer_size);
|
||||||
|
|
||||||
/* If the string happens to consist of only 1 character and a keysym
|
/* If the string happens to consist of only 1 control character and
|
||||||
was also found, give preference to the keysym. */
|
a keysym was also found, give preference to the keysym. */
|
||||||
if (buffer_size == 1 && status == XLookupBoth)
|
if (buffer_size == 1 && status == XLookupBoth
|
||||||
|
&& buffer[0] > 0 && buffer[0] < 32)
|
||||||
{
|
{
|
||||||
DebugPrint ("using keysym in preference to single char");
|
DebugPrint ("using keysym in preference to single control char");
|
||||||
|
|
||||||
XFree (buffer);
|
XFree (buffer);
|
||||||
|
|
||||||
|
@ -3081,7 +3194,8 @@ LookupString (TextInput *input, XEvent *event, KeySym *keysym_return)
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
FilterInputCallback (Seat *seat, Surface *surface, void *event)
|
FilterInputCallback (Seat *seat, Surface *surface, void *event,
|
||||||
|
KeySym *keysym)
|
||||||
{
|
{
|
||||||
XIDeviceEvent *xev;
|
XIDeviceEvent *xev;
|
||||||
XEvent xkey;
|
XEvent xkey;
|
||||||
|
@ -3118,7 +3232,7 @@ FilterInputCallback (Seat *seat, Surface *surface, void *event)
|
||||||
/* Otherwise, call XmbLookupString. If a keysym is returned,
|
/* Otherwise, call XmbLookupString. If a keysym is returned,
|
||||||
return False. Otherwise, commit the string looked up and
|
return False. Otherwise, commit the string looked up and
|
||||||
return True. */
|
return True. */
|
||||||
return LookupString (input, &xkey, NULL);
|
return LookupString (input, &xkey, keysym);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise, do nothing. */
|
/* Otherwise, do nothing. */
|
||||||
|
@ -3204,7 +3318,8 @@ XLTextInputDispatchCoreEvent (Surface *surface, XEvent *event)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Since that failed, dispatch the event to the seat. */
|
/* Since that failed, dispatch the event to the seat. */
|
||||||
DebugPrint ("lookup failed; dispatching event to seat");
|
DebugPrint ("lookup failed; dispatching event to seat; "
|
||||||
|
"keysym is: %lu", keysym);
|
||||||
|
|
||||||
XLSeatDispatchCoreKeyEvent (im_seat, surface, event, keysym);
|
XLSeatDispatchCoreKeyEvent (im_seat, surface, event, keysym);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1316,7 +1316,7 @@ RestoreStateTo (XdgToplevel *toplevel, int width, int height)
|
||||||
static Bool
|
static Bool
|
||||||
HandleConfigureEvent (XdgToplevel *toplevel, XEvent *event)
|
HandleConfigureEvent (XdgToplevel *toplevel, XEvent *event)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height, configure_width, configure_height;
|
||||||
|
|
||||||
if (event->xconfigure.send_event)
|
if (event->xconfigure.send_event)
|
||||||
/* Handle only synthetic events, since that's what the
|
/* Handle only synthetic events, since that's what the
|
||||||
|
@ -1357,9 +1357,18 @@ HandleConfigureEvent (XdgToplevel *toplevel, XEvent *event)
|
||||||
|
|
||||||
if (!MaybePostDelayedConfigure (toplevel, StatePendingConfigureSize))
|
if (!MaybePostDelayedConfigure (toplevel, StatePendingConfigureSize))
|
||||||
{
|
{
|
||||||
|
/* Scale the configure event width and height to the
|
||||||
|
surface. */
|
||||||
|
TruncateScaleToSurface (toplevel->role->surface,
|
||||||
|
event->xconfigure.width,
|
||||||
|
event->xconfigure.height,
|
||||||
|
&configure_width,
|
||||||
|
&configure_height);
|
||||||
|
|
||||||
|
/* Calculate the new window size. */
|
||||||
XLXdgRoleCalcNewWindowSize (toplevel->role,
|
XLXdgRoleCalcNewWindowSize (toplevel->role,
|
||||||
ConfigureWidth (event),
|
configure_width,
|
||||||
ConfigureHeight (event),
|
configure_height,
|
||||||
&width, &height);
|
&width, &height);
|
||||||
|
|
||||||
SendConfigure (toplevel, width, height);
|
SendConfigure (toplevel, width, height);
|
||||||
|
|
Loading…
Add table
Reference in a new issue