1 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
2 /*
3 * im-nimf-qt5.cpp
4 * This file is part of Nimf.
5 *
6 * Copyright (C) 2015-2019 Hodong Kim <cogniti@gmail.com>
7 *
8 * Nimf is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published
10 * by the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Nimf is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <QTextFormat>
23 #include <QInputMethodEvent>
24 #include <QtGui/qpa/qplatforminputcontext.h>
25 #include <QtGui/qpa/qplatforminputcontextplugin_p.h>
26 #include <QtWidgets/QApplication>
27 #include <QtWidgets/QWidget>
28 #include "nimf-im.h"
29 #include <gio/gio.h>
30
31 #ifdef USE_DLFCN
32
33 #include <dlfcn.h>
34
35 typedef struct
36 {
37 NimfIM * (* im_new) (void);
38 void (* im_focus_in) (NimfIM *im);
39 void (* im_focus_out) (NimfIM *im);
40 void (* im_reset) (NimfIM *im);
41 gboolean (* im_filter_event) (NimfIM *im,
42 NimfEvent *event);
43 void (* im_get_preedit_string) (NimfIM *im,
44 gchar **str,
45 NimfPreeditAttr ***attrs,
46 gint *cursor_pos);
47 void (* im_set_cursor_location) (NimfIM *im,
48 const NimfRectangle *area);
49 void (* im_set_use_preedit) (NimfIM *im,
50 gboolean use_preedit);
51 void (* im_set_surrounding) (NimfIM *im,
52 const char *text,
53 gint len,
54 gint cursor_index);
55 NimfEvent * (* event_new) (NimfEventType type);
56 void (* event_free) (NimfEvent *event);
57 void (* preedit_attr_freev) (NimfPreeditAttr **attrs);
58 } NimfAPI;
59
60 typedef struct
61 {
62 void (* free) (gpointer mem);
63 } GLibAPI;
64
65 typedef struct
66 {
67 gulong (* signal_connect_data) (gpointer instance,
68 const gchar *detailed_signal,
69 GCallback c_handler,
70 gpointer data,
71 GClosureNotify destroy_data,
72 GConnectFlags connect_flags);
73 void (* signal_emit_by_name) (gpointer instance,
74 const gchar *detailed_signal,
75 ...);
76 void (* object_unref) (gpointer object);
77 } GObjectAPI;
78
79 typedef struct
80 {
81 GSettings * (* settings_new) (const gchar *schema_id);
82 gboolean (* settings_get_boolean) (GSettings *settings,
83 const gchar *key);
84 GSettingsSchemaSource *
85 (* settings_schema_source_get_default) (void);
86 GSettingsSchema *
87 (* settings_schema_source_lookup)
88 (GSettingsSchemaSource *source,
89 const gchar *schema_id,
90 gboolean recursive);
91 void (* settings_schema_unref) (GSettingsSchema *schema);
92 } GIOAPI;
93
94 void *libnimf = NULL;
95 void *libglib = NULL;
96 void *libgobject = NULL;
97 void *libgio = NULL;
98 NimfAPI *nimf_api = NULL;
99 GLibAPI *glib_api = NULL;
100 GObjectAPI *gobject_api = NULL;
101 GIOAPI *gio_api = NULL;
102
103 #endif
104
105 class NimfEventHandler : public QObject
106 {
107 Q_OBJECT
108
109 public:
NimfEventHandler(NimfIM * im)110 NimfEventHandler(NimfIM *im)
111 {
112 m_im = im;
113 };
114
~NimfEventHandler()115 ~NimfEventHandler()
116 {};
117
118 protected:
119 bool eventFilter(QObject *obj, QEvent *event);
120
121 private:
122 NimfIM *m_im;
123 };
124
eventFilter(QObject * obj,QEvent * event)125 bool NimfEventHandler::eventFilter(QObject *obj, QEvent *event)
126 {
127 if (event->type() == QEvent::MouseButtonPress)
128 #ifndef USE_DLFCN
129 nimf_im_reset (m_im);
130 #else
131 nimf_api->im_reset (m_im);
132 #endif
133
134 return QObject::eventFilter(obj, event);
135 }
136
137 class NimfInputContext : public QPlatformInputContext
138 {
139 Q_OBJECT
140 public:
141 NimfInputContext ();
142 ~NimfInputContext ();
143
144 virtual bool isValid () const;
145 virtual void reset ();
146 virtual void commit ();
147 virtual void update (Qt::InputMethodQueries);
148 virtual void invokeAction (QInputMethod::Action, int cursorPosition);
149 virtual bool filterEvent (const QEvent *event);
150 virtual QRectF keyboardRect () const;
151 virtual bool isAnimating () const;
152 virtual void showInputPanel ();
153 virtual void hideInputPanel ();
154 virtual bool isInputPanelVisible () const;
155 virtual QLocale locale () const;
156 virtual Qt::LayoutDirection inputDirection() const;
157 virtual void setFocusObject (QObject *object);
158
159 // nimf signal callbacks
160 static void on_preedit_start (NimfIM *im,
161 gpointer user_data);
162 static void on_preedit_end (NimfIM *im,
163 gpointer user_data);
164 static void on_preedit_changed (NimfIM *im,
165 gpointer user_data);
166 static void on_commit (NimfIM *im,
167 const gchar *text,
168 gpointer user_data);
169 static gboolean on_retrieve_surrounding (NimfIM *im,
170 gpointer user_data);
171 static gboolean on_delete_surrounding (NimfIM *im,
172 gint offset,
173 gint n_chars,
174 gpointer user_data);
175 static void on_beep (NimfIM *im,
176 gpointer user_data);
177 // settings
178 static void on_changed_reset_on_mouse_button_press (GSettings *settings,
179 gchar *key,
180 gpointer user_data);
181 private:
182 NimfIM *m_im;
183 GSettings *m_settings;
184 NimfEventHandler *m_handler;
185 NimfRectangle m_cursor_area;
186 };
187
188 /* nimf signal callbacks */
189 void
on_preedit_start(NimfIM * im,gpointer user_data)190 NimfInputContext::on_preedit_start (NimfIM *im, gpointer user_data)
191 {
192 #ifndef USE_DLFCN
193 g_debug (G_STRLOC ": %s", G_STRFUNC);
194 #endif
195 }
196
197 void
on_preedit_end(NimfIM * im,gpointer user_data)198 NimfInputContext::on_preedit_end (NimfIM *im, gpointer user_data)
199 {
200 #ifndef USE_DLFCN
201 g_debug (G_STRLOC ": %s", G_STRFUNC);
202 #endif
203 }
204
205 void
on_preedit_changed(NimfIM * im,gpointer user_data)206 NimfInputContext::on_preedit_changed (NimfIM *im, gpointer user_data)
207 {
208 #ifndef USE_DLFCN
209 g_debug (G_STRLOC ": %s", G_STRFUNC);
210 #endif
211
212 NimfPreeditAttr **preedit_attrs;
213 gchar *str;
214 gint cursor_pos;
215 gint offset = 0;
216 guint i, j, len;
217
218 #ifndef USE_DLFCN
219 nimf_im_get_preedit_string (im, &str, &preedit_attrs, &cursor_pos);
220 #else
221 nimf_api->im_get_preedit_string (im, &str, &preedit_attrs, &cursor_pos);
222 #endif
223
224 QString preeditText = QString::fromUtf8 (str);
225 #ifndef USE_DLFCN
226 g_free (str);
227 #else
228 glib_api->free (str);
229 #endif
230 QList <QInputMethodEvent::Attribute> attrs;
231
232 for (i = 0; i < (guint) preeditText.size(); i++)
233 {
234 if (preeditText.at(i).isLowSurrogate())
235 {
236 offset++;
237 continue;
238 }
239
240 QTextCharFormat format;
241
242 for (j = 0; preedit_attrs[j]; j++)
243 {
244 switch (preedit_attrs[j]->type)
245 {
246 case NIMF_PREEDIT_ATTR_HIGHLIGHT:
247 if (preedit_attrs[j]->start_index <= i - offset &&
248 preedit_attrs[j]->end_index > i - offset)
249 {
250 format.setBackground(Qt::green);
251 format.setForeground(Qt::black);
252 }
253 break;
254 case NIMF_PREEDIT_ATTR_UNDERLINE:
255 if (preedit_attrs[j]->start_index <= i - offset &&
256 preedit_attrs[j]->end_index > i - offset)
257 format.setUnderlineStyle(QTextCharFormat::DashUnderline);
258 break;
259 default:
260 break;
261 }
262 }
263
264 preeditText.at(i).isHighSurrogate() ? len = 2 : len = 1;
265 QInputMethodEvent::Attribute attr (QInputMethodEvent::TextFormat,
266 i, len, format);
267 attrs << attr;
268 }
269
270 #ifndef USE_DLFCN
271 nimf_preedit_attr_freev (preedit_attrs);
272 #else
273 nimf_api->preedit_attr_freev (preedit_attrs);
274 #endif
275
276 // cursor attribute
277 attrs << QInputMethodEvent::Attribute (QInputMethodEvent::Cursor,
278 cursor_pos + offset, true, 0);
279
280 QInputMethodEvent event (preeditText, attrs);
281 QObject *object = qApp->focusObject ();
282
283 if (!object)
284 return;
285
286 QCoreApplication::sendEvent (object, &event);
287 }
288
289 void
on_commit(NimfIM * im,const gchar * text,gpointer user_data)290 NimfInputContext::on_commit (NimfIM *im,
291 const gchar *text,
292 gpointer user_data)
293 {
294 #ifndef USE_DLFCN
295 g_debug (G_STRLOC ": %s", G_STRFUNC);
296 #endif
297
298 QString str = QString::fromUtf8 (text);
299 QInputMethodEvent event;
300 event.setCommitString (str);
301
302 QObject *obj = qApp->focusObject();
303
304 if (!obj)
305 return;
306
307 QCoreApplication::sendEvent (obj, &event);
308 }
309
310 gboolean
on_retrieve_surrounding(NimfIM * im,gpointer user_data)311 NimfInputContext::on_retrieve_surrounding (NimfIM *im, gpointer user_data)
312 {
313 #ifndef USE_DLFCN
314 g_debug (G_STRLOC ": %s", G_STRFUNC);
315 #endif
316
317 QObject *object = qApp->focusObject();
318
319 if (!object)
320 return FALSE;
321
322 NimfInputContext *context = static_cast<NimfInputContext *>(user_data);
323
324 QInputMethodQueryEvent surrounding_query (Qt::ImSurroundingText);
325 QInputMethodQueryEvent position_query (Qt::ImCursorPosition);
326
327 QCoreApplication::sendEvent (object, &surrounding_query);
328 QCoreApplication::sendEvent (object, &position_query);
329
330 QString string = surrounding_query.value (Qt::ImSurroundingText).toString();
331 uint pos = position_query.value (Qt::ImCursorPosition).toUInt();
332
333 #ifndef USE_DLFCN
334 nimf_im_set_surrounding (context->m_im,
335 string.toUtf8().constData(), -1, pos);
336 #else
337 nimf_api->im_set_surrounding (context->m_im,
338 string.toUtf8().constData(), -1, pos);
339 #endif
340
341 return TRUE;
342 }
343
344 gboolean
on_delete_surrounding(NimfIM * im,gint offset,gint n_chars,gpointer user_data)345 NimfInputContext::on_delete_surrounding (NimfIM *im,
346 gint offset,
347 gint n_chars,
348 gpointer user_data)
349 {
350 #ifndef USE_DLFCN
351 g_debug (G_STRLOC ": %s", G_STRFUNC);
352 #endif
353
354 QObject *object = qApp->focusObject();
355
356 if (!object)
357 return FALSE;
358
359 QInputMethodEvent event;
360 event.setCommitString ("", offset, n_chars);
361 QCoreApplication::sendEvent (object, &event);
362
363 return TRUE;
364 }
365
366 void
on_beep(NimfIM * im,gpointer user_data)367 NimfInputContext::on_beep (NimfIM *im, gpointer user_data)
368 {
369 #ifndef USE_DLFCN
370 g_debug (G_STRLOC ": %s", G_STRFUNC);
371 #endif
372
373 QApplication::beep();
374 }
375
376 void
on_changed_reset_on_mouse_button_press(GSettings * settings,gchar * key,gpointer user_data)377 NimfInputContext::on_changed_reset_on_mouse_button_press (GSettings *settings,
378 gchar *key,
379 gpointer user_data)
380 {
381 #ifndef USE_DLFCN
382 g_debug (G_STRLOC ": %s", G_STRFUNC);
383 #endif
384
385 NimfInputContext *context = static_cast<NimfInputContext *>(user_data);
386
387 #ifndef USE_DLFCN
388 if (g_settings_get_boolean (settings, key))
389 #else
390 if (gio_api->settings_get_boolean (settings, key))
391 #endif
392 {
393 if (context->m_handler == NULL)
394 {
395 context->m_handler = new NimfEventHandler(context->m_im);
396 qApp->installEventFilter(context->m_handler);
397 }
398 }
399 else
400 {
401 if (context->m_handler)
402 {
403 qApp->removeEventFilter(context->m_handler);
404 delete context->m_handler;
405 context->m_handler = NULL;
406 }
407 }
408 }
409
NimfInputContext()410 NimfInputContext::NimfInputContext ()
411 {
412 #ifndef USE_DLFCN
413 g_debug (G_STRLOC ": %s", G_STRFUNC);
414 #endif
415
416 m_im = NULL;
417 m_settings = NULL;
418 m_handler = NULL;
419 m_cursor_area.x = 0;
420 m_cursor_area.y = 0;
421 m_cursor_area.width = 0;
422 m_cursor_area.height = 0;
423
424 #ifndef USE_DLFCN
425 m_im = nimf_im_new ();
426 m_settings = g_settings_new ("org.nimf.clients.qt5");
427 g_signal_connect (m_im, "preedit-start",
428 G_CALLBACK (NimfInputContext::on_preedit_start), this);
429 g_signal_connect (m_im, "preedit-end",
430 G_CALLBACK (NimfInputContext::on_preedit_end), this);
431 g_signal_connect (m_im, "preedit-changed",
432 G_CALLBACK (NimfInputContext::on_preedit_changed), this);
433 g_signal_connect (m_im, "commit",
434 G_CALLBACK (NimfInputContext::on_commit), this);
435 g_signal_connect (m_im, "retrieve-surrounding",
436 G_CALLBACK (NimfInputContext::on_retrieve_surrounding),
437 this);
438 g_signal_connect (m_im, "delete-surrounding",
439 G_CALLBACK (NimfInputContext::on_delete_surrounding),
440 this);
441 g_signal_connect (m_im, "beep",
442 G_CALLBACK (NimfInputContext::on_beep), this);
443
444 g_signal_connect (m_settings, "changed::reset-on-mouse-button-press",
445 G_CALLBACK (NimfInputContext::on_changed_reset_on_mouse_button_press), this);
446 g_signal_emit_by_name (m_settings, "changed::reset-on-mouse-button-press",
447 "reset-on-mouse-button-press");
448 #else
449 if (!nimf_api || !glib_api || !gobject_api || !gio_api)
450 {
451 qWarning("The libraries for nimf are not ready.");
452 return;
453 }
454
455 GSettingsSchemaSource *source;
456 GSettingsSchema *schema;
457
458 source = gio_api->settings_schema_source_get_default ();
459 schema = gio_api->settings_schema_source_lookup (source, "org.nimf.clients.qt5", TRUE);
460
461 if (schema == NULL)
462 {
463 qWarning("org.nimf.clients.qt5 schema is not found.");
464 return;
465 }
466
467 gio_api->settings_schema_unref (schema);
468
469 m_im = nimf_api->im_new ();
470 m_settings = gio_api->settings_new ("org.nimf.clients.qt5");
471 gobject_api->signal_connect_data (m_im, "preedit-start",
472 G_CALLBACK (NimfInputContext::on_preedit_start), this, NULL, (GConnectFlags) 0);
473 gobject_api->signal_connect_data (m_im, "preedit-end",
474 G_CALLBACK (NimfInputContext::on_preedit_end), this, NULL, (GConnectFlags) 0);
475 gobject_api->signal_connect_data (m_im, "preedit-changed",
476 G_CALLBACK (NimfInputContext::on_preedit_changed), this, NULL, (GConnectFlags) 0);
477 gobject_api->signal_connect_data (m_im, "commit",
478 G_CALLBACK (NimfInputContext::on_commit), this, NULL, (GConnectFlags) 0);
479 gobject_api->signal_connect_data (m_im, "retrieve-surrounding",
480 G_CALLBACK (NimfInputContext::on_retrieve_surrounding),
481 this, NULL, (GConnectFlags) 0);
482 gobject_api->signal_connect_data (m_im, "delete-surrounding",
483 G_CALLBACK (NimfInputContext::on_delete_surrounding),
484 this, NULL, (GConnectFlags) 0);
485 gobject_api->signal_connect_data (m_im, "beep",
486 G_CALLBACK (NimfInputContext::on_beep), this, NULL, (GConnectFlags) 0);
487 gobject_api->signal_connect_data (m_settings, "changed::reset-on-mouse-button-press",
488 G_CALLBACK (NimfInputContext::on_changed_reset_on_mouse_button_press), this, NULL, (GConnectFlags) 0);
489 gobject_api->signal_emit_by_name (m_settings, "changed::reset-on-mouse-button-press",
490 "reset-on-mouse-button-press");
491 #endif
492 }
493
~NimfInputContext()494 NimfInputContext::~NimfInputContext ()
495 {
496 #ifndef USE_DLFCN
497 g_debug (G_STRLOC ": %s", G_STRFUNC);
498 #endif
499
500 if (m_handler)
501 delete m_handler;
502
503 if (m_im)
504 #ifndef USE_DLFCN
505 g_object_unref (m_im);
506 #else
507 gobject_api->object_unref (m_im);
508 #endif
509
510 if (m_settings)
511 #ifndef USE_DLFCN
512 g_object_unref (m_settings);
513 #else
514 gobject_api->object_unref (m_settings);
515 #endif
516 }
517
518 bool
isValid() const519 NimfInputContext::isValid () const
520 {
521 #ifndef USE_DLFCN
522 g_debug (G_STRLOC ": %s", G_STRFUNC);
523 #endif
524
525 if (m_im == NULL)
526 return false;
527
528 return true;
529 }
530
531 void
reset()532 NimfInputContext::reset ()
533 {
534 #ifndef USE_DLFCN
535 g_debug (G_STRLOC ": %s", G_STRFUNC);
536
537 nimf_im_reset (m_im);
538 #else
539 nimf_api->im_reset (m_im);
540 #endif
541 }
542
543 void
commit()544 NimfInputContext::commit ()
545 {
546 #ifndef USE_DLFCN
547 g_debug (G_STRLOC ": %s", G_STRFUNC);
548
549 nimf_im_reset (m_im);
550 #else
551 nimf_api->im_reset (m_im);
552 #endif
553 }
554
555 void
update(Qt::InputMethodQueries queries)556 NimfInputContext::update (Qt::InputMethodQueries queries)
557 {
558 #ifndef USE_DLFCN
559 g_debug (G_STRLOC ": %s", G_STRFUNC);
560 #endif
561
562 if (queries & Qt::ImCursorRectangle)
563 {
564 QWidget *widget = qApp->focusWidget ();
565
566 if (widget == NULL)
567 return;
568
569 QRect rect = widget->inputMethodQuery(Qt::ImCursorRectangle).toRect();
570 QPoint point = widget->mapToGlobal (QPoint (0, 0));
571 rect.translate (point);
572
573 if (m_cursor_area.x != rect.x () ||
574 m_cursor_area.y != rect.y () ||
575 m_cursor_area.width != rect.width () ||
576 m_cursor_area.height != rect.height ())
577 {
578 m_cursor_area.x = rect.x ();
579 m_cursor_area.y = rect.y ();
580 m_cursor_area.width = rect.width ();
581 m_cursor_area.height = rect.height ();
582
583 #ifndef USE_DLFCN
584 nimf_im_set_cursor_location (m_im, &m_cursor_area);
585 #else
586 nimf_api->im_set_cursor_location (m_im, &m_cursor_area);
587 #endif
588 }
589 }
590 }
591
592 void
invokeAction(QInputMethod::Action,int cursorPosition)593 NimfInputContext::invokeAction(QInputMethod::Action, int cursorPosition)
594 {
595 #ifndef USE_DLFCN
596 g_debug (G_STRLOC ": %s", G_STRFUNC);
597 #endif
598 }
599
600 bool
filterEvent(const QEvent * event)601 NimfInputContext::filterEvent (const QEvent *event)
602 {
603 #ifndef USE_DLFCN
604 g_debug (G_STRLOC ": %s", G_STRFUNC);
605 #endif
606
607 if (G_UNLIKELY (!qApp->focusObject() || !inputMethodAccepted()))
608 return false;
609
610 gboolean retval;
611 const QKeyEvent *key_event = static_cast<const QKeyEvent *>( event );
612 NimfEvent *nimf_event;
613 NimfEventType type = NIMF_EVENT_NOTHING;
614
615 switch (event->type ())
616 {
617 #undef KeyPress
618 case QEvent::KeyPress:
619 type = NIMF_EVENT_KEY_PRESS;
620 break;
621 #undef KeyRelease
622 case QEvent::KeyRelease:
623 type = NIMF_EVENT_KEY_RELEASE;
624 break;
625 default:
626 return false;
627 }
628
629 #ifndef USE_DLFCN
630 nimf_event = nimf_event_new (type);
631 #else
632 nimf_event = nimf_api->event_new (type);
633 #endif
634
635 nimf_event->key.state = key_event->nativeModifiers ();
636 nimf_event->key.keyval = key_event->nativeVirtualKey ();
637 nimf_event->key.hardware_keycode = key_event->nativeScanCode ();
638
639 #ifndef USE_DLFCN
640 retval = nimf_im_filter_event (m_im, nimf_event);
641 nimf_event_free (nimf_event);
642 #else
643 retval = nimf_api->im_filter_event (m_im, nimf_event);
644 nimf_api->event_free (nimf_event);
645 #endif
646
647 return retval;
648 }
649
650 QRectF
keyboardRect() const651 NimfInputContext::keyboardRect() const
652 {
653 #ifndef USE_DLFCN
654 g_debug (G_STRLOC ": %s", G_STRFUNC);
655 #endif
656 return QRectF ();
657 }
658
659 bool
isAnimating() const660 NimfInputContext::isAnimating() const
661 {
662 #ifndef USE_DLFCN
663 g_debug (G_STRLOC ": %s", G_STRFUNC);
664 #endif
665 return false;
666 }
667
668 void
showInputPanel()669 NimfInputContext::showInputPanel()
670 {
671 #ifndef USE_DLFCN
672 g_debug (G_STRLOC ": %s", G_STRFUNC);
673 #endif
674 }
675
676 void
hideInputPanel()677 NimfInputContext::hideInputPanel()
678 {
679 #ifndef USE_DLFCN
680 g_debug (G_STRLOC ": %s", G_STRFUNC);
681 #endif
682 }
683
684 bool
isInputPanelVisible() const685 NimfInputContext::isInputPanelVisible() const
686 {
687 #ifndef USE_DLFCN
688 g_debug (G_STRLOC ": %s", G_STRFUNC);
689 #endif
690 return false;
691 }
692
693 QLocale
locale() const694 NimfInputContext::locale() const
695 {
696 #ifndef USE_DLFCN
697 g_debug (G_STRLOC ": %s", G_STRFUNC);
698 #endif
699 return QLocale ();
700 }
701
702 Qt::LayoutDirection
inputDirection() const703 NimfInputContext::inputDirection() const
704 {
705 #ifndef USE_DLFCN
706 g_debug (G_STRLOC ": %s", G_STRFUNC);
707 #endif
708 return Qt::LayoutDirection ();
709 }
710
711 void
setFocusObject(QObject * object)712 NimfInputContext::setFocusObject (QObject *object)
713 {
714 #ifndef USE_DLFCN
715 g_debug (G_STRLOC ": %s", G_STRFUNC);
716 #endif
717
718 if (!object || !inputMethodAccepted())
719 #ifndef USE_DLFCN
720 nimf_im_focus_out (m_im);
721 #else
722 nimf_api->im_focus_out (m_im);
723 #endif
724
725 QPlatformInputContext::setFocusObject (object);
726
727 if (object && inputMethodAccepted())
728 #ifndef USE_DLFCN
729 nimf_im_focus_in (m_im);
730 #else
731 nimf_api->im_focus_in (m_im);
732 #endif
733
734 update (Qt::ImCursorRectangle);
735 }
736
737 /*
738 * class NimfInputContextPlugin
739 */
740 class NimfInputContextPlugin : public QPlatformInputContextPlugin
741 {
742 Q_OBJECT
743 Q_PLUGIN_METADATA(IID
744 QPlatformInputContextFactoryInterface_iid
745 FILE "./nimf.json")
746
747 public:
NimfInputContextPlugin()748 NimfInputContextPlugin ()
749 {
750 #ifndef USE_DLFCN
751 g_debug (G_STRLOC ": %s", G_STRFUNC);
752 #endif
753
754 #ifdef USE_DLFCN
755 libnimf = dlopen ("libnimf.so.1", RTLD_LAZY);
756 libglib = dlopen ("libglib-2.0.so.0", RTLD_LAZY);
757 libgobject = dlopen ("libgobject-2.0.so.0", RTLD_LAZY);
758 libgio = dlopen ("libgio-2.0.so.0", RTLD_LAZY);
759
760 if (libnimf)
761 {
762 nimf_api = new NimfAPI;
763 nimf_api->im_new = reinterpret_cast<NimfIM* (*) ()> (dlsym (libnimf, "nimf_im_new"));
764 nimf_api->im_focus_in = reinterpret_cast<void (*) (NimfIM*)> (dlsym (libnimf, "nimf_im_focus_in"));
765 nimf_api->im_focus_out = reinterpret_cast<void (*) (NimfIM*)> (dlsym (libnimf, "nimf_im_focus_out"));
766 nimf_api->im_reset = reinterpret_cast<void (*) (NimfIM*)> (dlsym (libnimf, "nimf_im_reset"));
767 nimf_api->im_filter_event = reinterpret_cast<gboolean (*) (NimfIM*, NimfEvent*)> (dlsym (libnimf, "nimf_im_filter_event"));
768 nimf_api->im_get_preedit_string = reinterpret_cast<void (*) (NimfIM*, gchar**, NimfPreeditAttr***, gint*)> (dlsym (libnimf, "nimf_im_get_preedit_string"));
769 nimf_api->im_set_cursor_location = reinterpret_cast<void (*) (NimfIM*, const NimfRectangle*)> (dlsym (libnimf, "nimf_im_set_cursor_location"));
770 nimf_api->im_set_use_preedit = reinterpret_cast<void (*) (NimfIM*, gboolean)> (dlsym (libnimf, "nimf_im_set_use_preedit"));
771 nimf_api->im_set_surrounding = reinterpret_cast<void (*) (NimfIM*, const char*, gint, gint)> (dlsym (libnimf, "nimf_im_set_surrounding"));
772 nimf_api->event_new = reinterpret_cast<NimfEvent * (*) (NimfEventType)> (dlsym (libnimf, "nimf_event_new"));
773 nimf_api->event_free = reinterpret_cast<void (*) (NimfEvent*)> (dlsym (libnimf, "nimf_event_free"));
774 nimf_api->preedit_attr_freev = reinterpret_cast<void (*) (NimfPreeditAttr**)> (dlsym (libnimf, "nimf_preedit_attr_freev"));
775 }
776
777 if (libglib)
778 {
779 glib_api = new GLibAPI;
780 glib_api->free = reinterpret_cast<void (*) (gpointer)> (dlsym (libglib, "g_free"));
781 }
782
783 if (libgobject)
784 {
785 gobject_api = new GObjectAPI;
786 gobject_api->signal_connect_data = reinterpret_cast<gulong (*) (gpointer, const gchar*, GCallback, gpointer, GClosureNotify, GConnectFlags)> (dlsym (libgobject, "g_signal_connect_data"));
787 gobject_api->signal_emit_by_name = reinterpret_cast<void (*) (gpointer, const gchar*, ...)> (dlsym (libgobject, "g_signal_emit_by_name"));
788 gobject_api->object_unref = reinterpret_cast<void (*) (gpointer)> (dlsym (libgobject, "g_object_unref"));
789 }
790
791 if (libgio)
792 {
793 gio_api = new GIOAPI;
794 gio_api->settings_new = reinterpret_cast<GSettings* (*) (const gchar*)> (dlsym (libgio, "g_settings_new"));
795 gio_api->settings_get_boolean = reinterpret_cast<gboolean (*) (GSettings*, const gchar*)> (dlsym (libgio, "g_settings_get_boolean"));
796 gio_api->settings_schema_source_get_default
797 = reinterpret_cast<GSettingsSchemaSource* (*) ()> (dlsym (libgio, "g_settings_schema_source_get_default"));
798 gio_api->settings_schema_source_lookup
799 = reinterpret_cast<GSettingsSchema* (*) (GSettingsSchemaSource *, const gchar*, gboolean)> (dlsym (libgio, "g_settings_schema_source_lookup"));
800 gio_api->settings_schema_unref = reinterpret_cast<void (*) (GSettingsSchema*)> (dlsym (libgio, "g_settings_schema_unref"));
801 }
802 #endif
803 }
804
~NimfInputContextPlugin()805 ~NimfInputContextPlugin ()
806 {
807 #ifndef USE_DLFCN
808 g_debug (G_STRLOC ": %s", G_STRFUNC);
809 #endif
810
811 #ifdef USE_DLFCN
812 delete nimf_api;
813 delete glib_api;
814 delete gobject_api;
815 delete gio_api;
816
817 nimf_api = NULL;
818 glib_api = NULL;
819 gobject_api = NULL;
820 gio_api = NULL;
821
822 if (libnimf)
823 {
824 dlclose (libnimf);
825 libnimf = NULL;
826 }
827
828 if (libglib)
829 {
830 dlclose (libglib);
831 libglib = NULL;
832 }
833
834 if (libgobject)
835 {
836 dlclose (libgobject);
837 libgobject = NULL;
838 }
839
840 if (libgio)
841 {
842 dlclose (libgio);
843 libgio = NULL;
844 }
845 #endif
846 }
847
keys() const848 virtual QStringList keys () const
849 {
850 #ifndef USE_DLFCN
851 g_debug (G_STRLOC ": %s", G_STRFUNC);
852 #endif
853
854 return QStringList () << "nimf";
855 }
856
create(const QString & key,const QStringList & paramList)857 virtual QPlatformInputContext *create (const QString &key,
858 const QStringList ¶mList)
859 {
860 #ifndef USE_DLFCN
861 g_debug (G_STRLOC ": %s", G_STRFUNC);
862 #endif
863
864 return new NimfInputContext ();
865 }
866 };
867
868 #include "im-nimf-qt5.moc"
869