66 */
77
88#include " xim.h"
9+ #include < sys/types.h>
910#include < unistd.h>
1011#include < cstdarg>
12+ #include < cstdint>
1113#include < cstdio>
14+ #include < cstdlib>
15+ #include < cstring>
16+ #include < iterator>
17+ #include < memory>
18+ #include < string>
19+ #include < unordered_map>
20+ #include < unordered_set>
21+ #include < vector>
1222#include < xcb-imdkit/encoding.h>
23+ #include < xcb-imdkit/imdkit.h>
24+ #include < xcb-imdkit/ximproto.h>
25+ #include < xcb/xcb.h>
1326#include < xcb/xcb_aux.h>
27+ #include < xcb/xcb_ewmh.h>
28+ #include < xcb/xproto.h>
1429#include < xkbcommon/xkbcommon.h>
30+ #include " fcitx-config/iniparser.h"
31+ #include " fcitx-utils/capabilityflags.h"
32+ #include " fcitx-utils/handlertable.h"
33+ #include " fcitx-utils/key.h"
34+ #include " fcitx-utils/keysym.h"
35+ #include " fcitx-utils/log.h"
36+ #include " fcitx-utils/macros.h"
1537#include " fcitx-utils/misc.h"
1638#include " fcitx-utils/misc_p.h"
39+ #include " fcitx-utils/rect.h"
1740#include " fcitx-utils/stringutils.h"
41+ #include " fcitx-utils/textformatflags.h"
1842#include " fcitx-utils/utf8.h"
43+ #include " fcitx/addonfactory.h"
44+ #include " fcitx/addoninstance.h"
45+ #include " fcitx/event.h"
1946#include " fcitx/inputcontext.h"
2047#include " fcitx/instance.h"
2148#include " fcitx/userinterface.h"
49+ #include " xcb_public.h"
2250
2351FCITX_DEFINE_LOG_CATEGORY (xim, " xim" )
2452FCITX_DEFINE_LOG_CATEGORY(xim_key, " xim_key" )
@@ -104,7 +132,7 @@ class XIMServer {
104132 conn, XCB_COPY_FROM_PARENT, serverWindow_, screen->root , 0 , 0 , 1 , 1 ,
105133 1 , XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual , 0 , nullptr );
106134
107- auto inputStyles =
135+ auto * inputStyles =
108136 (*parent_->config ().useOnTheSpot ? &onthespot_styles : &styles);
109137 for (uint32_t i = 0 ; i < inputStyles->nStyles ; i++) {
110138 supportedStyles_.insert (inputStyles->styles [i]);
@@ -152,7 +180,7 @@ class XIMServer {
152180 }
153181 }
154182
155- static void callback (xcb_im_t *, xcb_im_client_t *client,
183+ static void callback (xcb_im_t * /* unused */ , xcb_im_client_t *client,
156184 xcb_im_input_context_t *xic,
157185 const xcb_im_packet_header_fr_t *hdr, void *frame,
158186 void *arg, void *user_data) {
@@ -378,7 +406,8 @@ class XIMInputContext final : public InputContext {
378406 xcb_im_commit_string (server_->im (), xic_, XCB_XIM_LOOKUP_CHARS, commit,
379407 length, 0 );
380408 }
381- void deleteSurroundingTextImpl (int , unsigned int ) override {}
409+ void deleteSurroundingTextImpl (int /* offset*/ ,
410+ unsigned int /* size*/ ) override {}
382411 void forwardKeyImpl (const ForwardKeyEvent &key) override {
383412 xcb_key_press_event_t xcbEvent;
384413 memset (&xcbEvent, 0 , sizeof (xcb_key_press_event_t ));
@@ -392,8 +421,8 @@ class XIMInputContext final : public InputContext {
392421 xkb_state *xkbState = server_->xkbState ();
393422 if (xkbState) {
394423 auto *map = xkb_state_get_keymap (xkbState);
395- auto min = xkb_keymap_min_keycode (map),
396- max = xkb_keymap_max_keycode (map);
424+ auto min = xkb_keymap_min_keycode (map);
425+ auto max = xkb_keymap_max_keycode (map);
397426 for (auto keyCode = min; keyCode < max; keyCode++) {
398427 if (xkb_state_key_get_one_sym (xkbState, keyCode) ==
399428 static_cast <uint32_t >(key.rawKey ().sym ())) {
@@ -405,8 +434,7 @@ class XIMInputContext final : public InputContext {
405434 }
406435 xcbEvent.root = server_->root ();
407436 xcbEvent.event = xcb_im_input_context_get_focus_window (xic_);
408- if ((xcbEvent.event = xcb_im_input_context_get_focus_window (xic_)) ==
409- XCB_WINDOW_NONE) {
437+ if (xcbEvent.event == XCB_WINDOW_NONE) {
410438 xcbEvent.event = xcb_im_input_context_get_client_window (xic_);
411439 }
412440 xcbEvent.child = XCB_WINDOW_NONE;
@@ -532,6 +560,8 @@ void XIMServer::callback(xcb_im_client_t *client, xcb_im_input_context_t *xic,
532560 XIM_DEBUG () << " Client disconnect: " << client;
533561 clientEncodingMapping_.erase (client);
534562 return ;
563+ default :
564+ break ;
535565 }
536566
537567 if (!xic) {
@@ -551,7 +581,7 @@ void XIMServer::callback(xcb_im_client_t *client, xcb_im_input_context_t *xic,
551581 switch (hdr->major_opcode ) {
552582 case XCB_XIM_CREATE_IC: {
553583 bool useUtf8 = false ;
554- if (auto entry = findValue (clientEncodingMapping_, client);
584+ if (auto * entry = findValue (clientEncodingMapping_, client);
555585 entry && *entry) {
556586 useUtf8 = true ;
557587 }
@@ -576,14 +606,22 @@ void XIMServer::callback(xcb_im_client_t *client, xcb_im_input_context_t *xic,
576606 xkb_state_get_keymap (state)) {
577607 localState_.reset (xkb_state_new (keymap));
578608 }
579- xcb_key_press_event_t *xevent =
580- static_cast <xcb_key_press_event_t *>(arg);
609+ auto *xevent = static_cast <xcb_key_press_event_t *>(arg);
581610 auto layout =
582611 xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE);
583612 // Always use the state that is forwarded by client.
584613 // For xkb_state_key_get_one_sym, no need to distinguish
585614 // depressed/latched/locked.
586- xkb_state_update_mask (localState_.get (), xevent->state , 0 , 0 , 0 , 0 ,
615+
616+ // Remove all button mask before send to XKB.
617+ // XKB May have internal virtual state bit, which collides with this
618+ // bits. See: https://github.com/fcitx/fcitx5/issues/1106
619+ constexpr uint16_t button_mask = XCB_BUTTON_MASK_1 | XCB_BUTTON_MASK_2 |
620+ XCB_BUTTON_MASK_3 | XCB_BUTTON_MASK_4 |
621+ XCB_BUTTON_MASK_5;
622+
623+ xkb_state_update_mask (localState_.get (),
624+ (xevent->state & (~button_mask)), 0 , 0 , 0 , 0 ,
587625 layout);
588626 KeyEvent event (ic,
589627 Key (static_cast <KeySym>(xkb_state_key_get_one_sym (
@@ -594,6 +632,8 @@ void XIMServer::callback(xcb_im_client_t *client, xcb_im_input_context_t *xic,
594632 XIM_KEY_DEBUG () << " XIM Key Event: "
595633 << static_cast <int >(xevent->response_type ) << " "
596634 << event.rawKey ().toString () << " time:" << xevent->time
635+ << " detail: " << static_cast <int >(xevent->detail )
636+ << " state: " << xevent->state
597637 << " sequence:" << xevent->sequence ;
598638 if (!ic->hasFocus ()) {
599639 ic->focusIn ();
@@ -620,6 +660,8 @@ void XIMServer::callback(xcb_im_client_t *client, xcb_im_input_context_t *xic,
620660 ic->resetAutoRepeatState ();
621661 ic->focusOut ();
622662 break ;
663+ default :
664+ break ;
623665 }
624666}
625667
@@ -642,10 +684,10 @@ XIMModule::XIMModule(Instance *instance) : instance_(instance) {
642684 EventType::InputContextFlushUI, EventWatcherPhase::PreInputMethod,
643685 [](Event &event) {
644686 auto &uiEvent = static_cast <InputContextFlushUIEvent &>(event);
645- auto ic = uiEvent.inputContext ();
687+ auto * ic = uiEvent.inputContext ();
646688 if (uiEvent.component () == UserInterfaceComponent::InputPanel &&
647689 ic->frontendName () == " xim" ) {
648- auto xic = static_cast <XIMInputContext *>(ic);
690+ auto * xic = static_cast <XIMInputContext *>(ic);
649691 xic->maybeUpdateCursorLocationForRootStyle ();
650692 }
651693 });
0 commit comments