1 /*
2 SPDX-FileCopyrightText: 2009 Wang Hoi <zealot.hoi@gmail.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 /** @file scim_panel_dbus.cpp
8 */
9
10 #define KDE_signal signal
11
12 #undef QT_NO_STL
13 #define QT_STL
14
15 #define QT_NO_KEYWORDS
16
17 #include <config-scim.h>
18 #include <errno.h>
19 #include <list>
20 #include <signal.h>
21 #include <stdlib.h>
22 #include <sys/time.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <unistd.h>
26
27 #include <QCoreApplication>
28 #include <QDBusConnection>
29 #include <QDBusMessage>
30 #include <QMutex>
31 #include <QObject>
32 #include <QProcess>
33 #include <QString>
34 #include <QStringList>
35 #include <QThread>
36
37 #define Uses_C_STDIO
38 #define Uses_C_STDLIB
39 #define Uses_SCIM_LOOKUP_TABLE
40 #define Uses_SCIM_SOCKET
41 #define Uses_SCIM_TRANSACTION
42 #define Uses_SCIM_TRANS_COMMANDS
43 #define Uses_SCIM_CONFIG
44 #define Uses_SCIM_CONFIG_MODULE
45 //#define Uses_SCIM_DEBUG
46 #define Uses_SCIM_HELPER
47 #define Uses_SCIM_HELPER_MODULE
48 #define Uses_SCIM_PANEL_AGENT
49 #define Uses_STL_MAP
50
51 #define ENABLE_DEBUG 9
52 // scim use exceptions and template, so it doesn't work in hidden visibility
53 #pragma GCC visibility push(default)
54 #include <scim.h>
55 #pragma GCC visibility pop
56
57 Q_DECLARE_METATYPE(scim::Property)
58 Q_DECLARE_METATYPE(scim::PanelFactoryInfo)
59 Q_DECLARE_METATYPE(scim::HelperInfo)
60
61 using namespace scim;
62
63 // PanelAgent related functions
64 static bool initialize_panel_agent(const String &config, const String &display, bool resident);
65 static bool run_panel_agent(void);
66 static void start_auto_start_helpers(void);
67
68 static void slot_transaction_start(void);
69 static void slot_transaction_end(void);
70 static void slot_reload_config(void);
71 static void slot_turn_on(void);
72 static void slot_turn_off(void);
73 static void slot_update_screen(int screen);
74 static void slot_update_spot_location(int x, int y);
75 static void slot_update_factory_info(const PanelFactoryInfo &info);
76 static void slot_show_help(const String &help);
77 static void slot_show_factory_menu(const std::vector<PanelFactoryInfo> &menu);
78
79 static void slot_show_preedit_string(void);
80 static void slot_show_aux_string(void);
81 static void slot_show_lookup_table(void);
82 static void slot_hide_preedit_string(void);
83 static void slot_hide_aux_string(void);
84 static void slot_hide_lookup_table(void);
85 static void slot_update_preedit_string(const String &str, const AttributeList &attrs);
86 static void slot_update_preedit_caret(int caret);
87 static void slot_update_aux_string(const String &str, const AttributeList &attrs);
88 static void slot_update_lookup_table(const LookupTable &table);
89 static void slot_register_properties(const PropertyList &props);
90 static void slot_update_property(const Property &prop);
91
92 static void slot_register_helper_properties(int id, const PropertyList &props);
93 static void slot_update_helper_property(int id, const Property &prop);
94 static void slot_register_helper(int id, const HelperInfo &helper);
95 static void slot_remove_helper(int id);
96 static void slot_lock(void);
97 static void slot_unlock(void);
98
99 /////////////////////////////////////////////////////////////////////////////
100 // Declaration of internal variables.
101 /////////////////////////////////////////////////////////////////////////////
102 // static bool _ui_initialized = false;
103
104 static ConfigModule *_config_module = nullptr;
105 static ConfigPointer _config;
106
107 static std::vector<HelperInfo> _helper_list;
108
109 static bool _should_exit = false;
110
111 // static bool _panel_is_on = false;
112
113 static PanelAgent *_panel_agent = nullptr;
114
115 static QList<PanelFactoryInfo> _factory_list;
116
117 class PanelAgentThread;
118 PanelAgentThread *_panel_agent_thread;
119
120 class DBusHandler;
121 DBusHandler *_dbus_handler;
122
123 static QMutex _panel_agent_lock;
124 static QMutex _global_resource_lock;
125 static QMutex _transaction_lock;
126
127 /////////////////////////////////////////////////////////////////////////////
128 // Implementation of internal functions.
129 /////////////////////////////////////////////////////////////////////////////
130
ui_config_reload_callback(const ConfigPointer & config)131 static void ui_config_reload_callback(const ConfigPointer &config)
132 {
133 _config = config;
134 }
135
AttrList2String(const AttributeList & attr_list)136 static QString AttrList2String(const AttributeList &attr_list)
137 {
138 QString result;
139 Q_FOREACH (const Attribute &attr, attr_list) {
140 int type = (int)attr.get_type();
141 unsigned int start = attr.get_start();
142 unsigned int length = attr.get_length();
143 unsigned int value = attr.get_value();
144 result += QString("%1:%2:%3:%4;").arg(type).arg(start).arg(length).arg(value);
145 }
146 return result;
147 }
148
LookupTable2VariantList(const LookupTable & lookup_table)149 static QVariantList LookupTable2VariantList(const LookupTable &lookup_table)
150 {
151 QVariantList result;
152 QStringList labels;
153 QStringList candidates;
154 QStringList attrlist_list;
155 int current_page_size = lookup_table.get_current_page_size();
156
157 for (int i = 0; i < current_page_size; ++i) {
158 labels << QString::fromStdWString(lookup_table.get_candidate_label(i));
159 }
160 for (int i = 0; i < current_page_size; ++i) {
161 candidates << QString::fromStdWString(lookup_table.get_candidate_in_current_page(i));
162 attrlist_list << AttrList2String(lookup_table.get_attributes_in_current_page(i));
163 }
164
165 result << labels << candidates << attrlist_list << lookup_table.get_current_page_start()
166 << (lookup_table.get_current_page_start() + lookup_table.get_current_page_size() < ((int)lookup_table.number_of_candidates()));
167
168 // result << labels << candidates << attrlist_list;
169 return result;
170 }
171
Property2String(const Property & prop)172 static QString Property2String(const Property &prop)
173 {
174 QString result;
175 int state = 0;
176 if (prop.active())
177 state |= SCIM_PROPERTY_ACTIVE;
178 if (prop.visible())
179 state |= SCIM_PROPERTY_VISIBLE;
180 result = QString("%1:%2:%3:%4:%5")
181 .arg(QString::fromUtf8(prop.get_key().c_str()))
182 .arg(QString::fromUtf8(prop.get_label().c_str()))
183 .arg(QString::fromUtf8(prop.get_icon().c_str()))
184 .arg(QString::fromUtf8(prop.get_tip().c_str()))
185 .arg(state);
186 return result;
187 }
188
189 #if 0
190 static QString
191 PanelFactoryInfo2String(const PanelFactoryInfo &info)
192 {
193 QString result = QString("%1:%2:%3:%4")
194 .arg(QString::fromUtf8(info.uuid.c_str()))
195 .arg(QString::fromUtf8(info.name.c_str()))
196 .arg(QString::fromUtf8(info.icon.c_str()))
197 .arg(QString::fromUtf8(info.lang.c_str()));
198 return result;
199 }
200 #endif
201
PropertyList2LeafOnlyStringList(const QList<Property> & props)202 static QStringList PropertyList2LeafOnlyStringList(const QList<Property> &props)
203 {
204 QStringList list;
205 list.clear();
206 for (int i = 0; i < props.size(); ++i) {
207 bool ok = true;
208 for (int j = 0; j < props.size(); ++j) {
209 if (props.at(i).is_a_leaf_of(props.at(j))) {
210 SCIM_DEBUG_MAIN(1) << "Leaf" << props.at(i).get_key() << " " << props.at(j).get_key() << "\n";
211 ok = false;
212 }
213 }
214 if (ok)
215 list << Property2String(props.at(i));
216 }
217 return list;
218 }
219
220 static int dbus_event_type = QEvent::registerEventType(1988);
221 class DBusEvent : public QEvent
222 {
223 public:
224 enum SCIM_EVENT_TYPE {
225 TURN_ON,
226 TURN_OFF,
227 UP_SCREEN,
228 UP_SPOT_LOC,
229 UP_AUX,
230 UP_PREEDIT_STR,
231 UP_PREEDIT_CARET,
232 UP_LOOKUPTABLE,
233 UP_LOOKUPTABLE_CURSOR,
234 UP_FACTORY_INFO,
235 UP_PROPERTY,
236 UP_HELPER_PROPERTY,
237 REG_PROPERTIES,
238 REG_HELPER_PROPERTIES,
239 REG_HELPER,
240 RM_HELPER,
241 RM_PROPERTY,
242 SHOW_LOOKUPTABLE,
243 HIDE_LOOKUPTABLE,
244 SHOW_PREEDIT,
245 HIDE_PREEDIT,
246 SHOW_AUX,
247 HIDE_AUX,
248 SHOW_HELP,
249 SHOW_FACTORY_MENU,
250 };
DBusEvent(SCIM_EVENT_TYPE t,const QVariantList & arglist=QVariantList ())251 DBusEvent(SCIM_EVENT_TYPE t, const QVariantList &arglist = QVariantList())
252 : QEvent((QEvent::Type)dbus_event_type)
253 , m_evtype(t)
254 , m_data(arglist)
255 {
256 }
scim_event_type() const257 SCIM_EVENT_TYPE scim_event_type() const
258 {
259 return m_evtype;
260 }
data() const261 QVariantList data() const
262 {
263 return m_data;
264 }
265
266 private:
267 SCIM_EVENT_TYPE m_evtype;
268 QVariantList m_data;
269 };
270 class DBusHandler : public QObject
271 {
272 Q_OBJECT
273 public:
DBusHandler(QObject * parent=nullptr)274 explicit DBusHandler(QObject *parent = nullptr)
275 : QObject(parent)
276 {
277 QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "MovePreeditCaret", this, SLOT(MovePreeditCaret(int)));
278 QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "SelectCandidate", this, SLOT(SelectCandidate(int)));
279 QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "LookupTablePageUp", this, SLOT(LookupTablePageUp()));
280 QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "LookupTablePageDown", this, SLOT(LookupTablePageDown()));
281 QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "TriggerProperty", this, SLOT(TriggerProperty(QString)));
282 QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "PanelCreated", this, SLOT(PanelCreated()));
283 QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "Exit", this, SLOT(Exit()));
284 QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "ReloadConfig", this, SLOT(ReloadConfig()));
285 QDBusConnection("scim_panel").connect("", "", "org.kde.impanel", "Configure", this, SLOT(Configure()));
286
287 logo_prop = Property("/Logo", "SCIM", String(SCIM_ICON_DIR) + "/trademark.png", "SCIM Input Method");
288 show_help_prop = Property("/StartHelp", "Help", "help-about", "About SCIM…");
289 factory_prop_prefix = QString::fromUtf8("/Factory/");
290 helper_prop_prefix = QString::fromUtf8("/Helper/");
291 }
~DBusHandler()292 ~DBusHandler()
293 {
294 }
295
setInitialHelpers(const std::vector<HelperInfo> & _helper_list)296 void setInitialHelpers(const std::vector<HelperInfo> &_helper_list)
297 {
298 QList<Property> props;
299 Q_FOREACH (const HelperInfo &info, _helper_list) {
300 if (((info.option & SCIM_HELPER_STAND_ALONE) != 0) && ((info.option & SCIM_HELPER_AUTO_START) == 0)) {
301 props << Property(String(helper_prop_prefix.toUtf8().constData()) + info.uuid, info.name, info.icon, info.description);
302 }
303 }
304 if (!props.isEmpty()) {
305 helper_props_map.insert(0, props);
306 }
307 }
308 public Q_SLOTS:
MovePreeditCaret(int pos)309 void MovePreeditCaret(int pos)
310 {
311 SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << pos << "\n";
312 _panel_agent->move_preedit_caret(pos);
313 }
SelectCandidate(int idx)314 void SelectCandidate(int idx)
315 {
316 SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << idx << "\n";
317 _panel_agent->select_candidate(idx);
318 }
LookupTablePageUp()319 void LookupTablePageUp()
320 {
321 SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << "\n";
322 _panel_agent->lookup_table_page_up();
323 }
LookupTablePageDown()324 void LookupTablePageDown()
325 {
326 SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << "\n";
327 _panel_agent->lookup_table_page_down();
328 }
TriggerProperty(const QString & key)329 void TriggerProperty(const QString &key)
330 {
331 SCIM_DEBUG_MAIN(1) << qPrintable(key) << "\n";
332 if (key == show_help_prop.get_key().c_str()) {
333 SCIM_DEBUG_MAIN(1) << "about_to_show_help"
334 << "\n";
335 _panel_agent->request_help();
336 return;
337 }
338 if (key == logo_prop.get_key().c_str()) {
339 SCIM_DEBUG_MAIN(1) << "about_to_show_factory_menu"
340 << "\n";
341 _panel_agent->request_factory_menu();
342 return;
343 }
344 if (key.startsWith(factory_prop_prefix)) {
345 QString factory_uuid = key;
346 factory_uuid.remove(0, factory_prop_prefix.size());
347 SCIM_DEBUG_MAIN(1) << "about_to_change_factory" << qPrintable(factory_uuid) << "\n";
348 _panel_agent->change_factory(factory_uuid.toUtf8().constData());
349 return;
350 }
351 if (key.startsWith(helper_prop_prefix)) {
352 QString helper_uuid = key;
353 helper_uuid.remove(0, helper_prop_prefix.size());
354 SCIM_DEBUG_MAIN(1) << "about_to_start_helper" << qPrintable(helper_uuid) << "\n";
355 _panel_agent->start_helper(helper_uuid.toUtf8().constData());
356 return;
357 }
358 int i = 0;
359 for (i = 0; i < panel_props.size(); ++i) {
360 if (panel_props.at(i).get_key() == String(key.toUtf8().constData())) {
361 break;
362 }
363 }
364 // found one
365 QStringList list_result;
366 list_result.clear();
367 if (i < panel_props.size()) {
368 for (int j = 0; j < panel_props.size(); ++j) {
369 if (panel_props.at(j).is_a_leaf_of(panel_props.at(i))) {
370 list_result << Property2String(panel_props.at(j));
371 }
372 }
373 if (list_result.isEmpty()) {
374 _panel_agent->trigger_property(key.toUtf8().constData());
375 } else {
376 SCIM_DEBUG_MAIN(1) << "ExecMenu" << qPrintable(key) << "\n";
377 QDBusMessage message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ExecMenu");
378 message << list_result;
379 QDBusConnection("scim_panel").send(message);
380 }
381 }
382 }
PanelCreated()383 void PanelCreated()
384 {
385 QDBusMessage message;
386 QStringList list_result;
387
388 list_result.clear();
389 list_result << Property2String(logo_prop);
390 list_result << PropertyList2LeafOnlyStringList(panel_props);
391
392 Q_FOREACH (const QList<Property> &props, helper_props_map) {
393 list_result << PropertyList2LeafOnlyStringList(props);
394 }
395
396 list_result << Property2String(show_help_prop);
397
398 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "RegisterProperties");
399
400 message << list_result;
401 QDBusConnection("scim_panel").send(message);
402 }
Exit()403 void Exit()
404 {
405 SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << "\n";
406 _panel_agent->exit();
407 _panel_agent->stop();
408 exit(1);
409 }
ReloadConfig()410 void ReloadConfig()
411 {
412 SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << "\n";
413 _panel_agent->reload_config();
414 if (!_config.null())
415 _config->reload();
416 }
Configure()417 void Configure()
418 {
419 SCIM_DEBUG_MAIN(1) << Q_FUNC_INFO << "\n";
420 QProcess::startDetached("scim-setup");
421 }
422
423 protected:
event(QEvent * e)424 bool event(QEvent *e) override
425 {
426 QStringList list_result;
427 QList<Property> prop_list;
428 if (e->type() == dbus_event_type) {
429 DBusEvent *ev = (DBusEvent *)e;
430
431 QDBusMessage message;
432
433 switch (ev->scim_event_type()) {
434 case DBusEvent::TURN_ON:
435 /*
436 list_result.clear();
437 list_result << Property2String(logo_prop);
438 list_result << PropertyList2LeafOnlyStringList(panel_props);
439 Q_FOREACH(const QList<Property> &props, helper_props_map.values()) {
440 list_result << PropertyList2LeafOnlyStringList(props);
441 }
442 list_result << Property2String(show_help_prop);
443
444 message = QDBusMessage::createSignal("/kimpanel",
445 "org.kde.kimpanel.inputmethod",
446 "RegisterProperties");
447
448 message << list_result;
449 QDBusConnection("scim_panel").send(message);
450 */
451 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "Enable");
452 message << true;
453 QDBusConnection("scim_panel").send(message);
454 break;
455 case DBusEvent::TURN_OFF:
456 logo_prop.set_icon(String(SCIM_ICON_DIR) + "/trademark.png");
457
458 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateProperty");
459 message << Property2String(logo_prop);
460 QDBusConnection("scim_panel").send(message);
461 /*
462 list_result.clear();
463 list_result << Property2String(logo_prop);
464 Q_FOREACH (const QList<Property> &prop_list, helper_props_map.values()) {
465 list_result << PropertyList2LeafOnlyStringList(prop_list);
466 }
467 list_result << Property2String(show_help_prop);
468
469 message = QDBusMessage::createSignal("/kimpanel",
470 "org.kde.kimpanel.inputmethod",
471 "RegisterProperties");
472
473 message << list_result;
474
475 QDBusConnection("scim_panel").send(message);
476 */
477 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "Enable");
478 message << false;
479 QDBusConnection("scim_panel").send(message);
480 break;
481 case DBusEvent::SHOW_HELP:
482 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ExecDialog");
483 message << Property2String(Property("/Help", "Help", "", ev->data().at(0).toString().toUtf8().constData()));
484 QDBusConnection("scim_panel").send(message);
485 break;
486 case DBusEvent::SHOW_FACTORY_MENU:
487 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ExecMenu");
488 // X _factory_list.clear();
489 list_result.clear();
490 Q_FOREACH (const QVariant &v, ev->data()) {
491 PanelFactoryInfo factory_info = v.value<PanelFactoryInfo>();
492 // X _factory_list << factory_info;
493 list_result << Property2String(Property(String(factory_prop_prefix.toUtf8().constData()) + factory_info.uuid,
494 factory_info.name,
495 factory_info.icon,
496 factory_info.lang));
497 }
498 message << list_result;
499 SCIM_DEBUG_MAIN(1) << qPrintable(list_result.join(";")) << "\n";
500 QDBusConnection("scim_panel").send(message);
501 break;
502 case DBusEvent::SHOW_PREEDIT:
503 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowPreedit");
504 message << true;
505 QDBusConnection("scim_panel").send(message);
506 break;
507 case DBusEvent::SHOW_AUX:
508 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowAux");
509 message << true;
510 QDBusConnection("scim_panel").send(message);
511 break;
512 case DBusEvent::SHOW_LOOKUPTABLE:
513 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowLookupTable");
514 message << true;
515 QDBusConnection("scim_panel").send(message);
516 break;
517 case DBusEvent::HIDE_PREEDIT:
518 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowPreedit");
519 message << false;
520 QDBusConnection("scim_panel").send(message);
521 break;
522 case DBusEvent::HIDE_AUX:
523 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowAux");
524 message << false;
525 QDBusConnection("scim_panel").send(message);
526 break;
527 case DBusEvent::HIDE_LOOKUPTABLE:
528 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ShowLookupTable");
529 message << false;
530 QDBusConnection("scim_panel").send(message);
531 break;
532 case DBusEvent::UP_PROPERTY:
533 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateProperty");
534 message << Property2String(ev->data().at(0).value<Property>());
535 QDBusConnection("scim_panel").send(message);
536 break;
537 case DBusEvent::UP_LOOKUPTABLE:
538 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateLookupTable");
539 message << ev->data().at(0).toStringList();
540 message << ev->data().at(1).toStringList();
541 message << ev->data().at(2).toStringList();
542 message << ev->data().at(3).toBool();
543 message << ev->data().at(4).toBool();
544 QDBusConnection("scim_panel").send(message);
545 break;
546 case DBusEvent::UP_LOOKUPTABLE_CURSOR:
547 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateLookupTableCursor");
548 message << ev->data().at(0).toInt();
549 QDBusConnection("scim_panel").send(message);
550 break;
551 case DBusEvent::UP_PREEDIT_CARET:
552 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdatePreeditCaret");
553 message << ev->data().at(0).toInt();
554 QDBusConnection("scim_panel").send(message);
555 break;
556 case DBusEvent::UP_PREEDIT_STR:
557 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdatePreeditText");
558 message << ev->data().at(0).toString();
559 message << ev->data().at(1).toString();
560 QDBusConnection("scim_panel").send(message);
561 break;
562 case DBusEvent::UP_AUX:
563 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateAux");
564 message << ev->data().at(0).toString();
565 message << ev->data().at(1).toString();
566 QDBusConnection("scim_panel").send(message);
567 break;
568 case DBusEvent::UP_SPOT_LOC:
569 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateSpotLocation");
570 message << ev->data().at(0).toInt();
571 message << ev->data().at(1).toInt();
572 QDBusConnection("scim_panel").send(message);
573 break;
574 case DBusEvent::UP_SCREEN:
575 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateScreen");
576 message << ev->data().at(0).toInt();
577 QDBusConnection("scim_panel").send(message);
578 break;
579 case DBusEvent::UP_FACTORY_INFO:
580 SCIM_DEBUG_MAIN(1) << "update factory info\n";
581
582 logo_prop.set_icon(ev->data().at(0).value<PanelFactoryInfo>().icon);
583 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "UpdateProperty");
584 message << Property2String(logo_prop);
585 QDBusConnection("scim_panel").send(message);
586 break;
587 case DBusEvent::REG_HELPER:
588 break;
589 case DBusEvent::REG_HELPER_PROPERTIES:
590 helper_props_map.clear();
591 prop_list.clear();
592 Q_FOREACH (const QVariant &v, ev->data().at(1).toList()) {
593 Property prop = v.value<Property>();
594 prop_list << prop;
595 }
596 helper_props_map.insert(ev->data().at(0).toInt(), prop_list);
597
598 list_result.clear();
599 list_result << Property2String(logo_prop);
600 list_result << PropertyList2LeafOnlyStringList(panel_props);
601 Q_FOREACH (const QList<Property> &props, helper_props_map) {
602 list_result << PropertyList2LeafOnlyStringList(props);
603 }
604 list_result << Property2String(show_help_prop);
605
606 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "RegisterProperties");
607
608 message << list_result;
609 QDBusConnection("scim_panel").send(message);
610
611 break;
612 case DBusEvent::REG_PROPERTIES:
613 panel_props.clear();
614 Q_FOREACH (const QVariant &v, ev->data()) {
615 Property prop = v.value<Property>();
616 panel_props << prop;
617 SCIM_DEBUG_MAIN(1) << "REG_PROPERTIES" << qPrintable(Property2String(v.value<Property>())) << "\n";
618 }
619
620 list_result.clear();
621 list_result << Property2String(logo_prop);
622 list_result << PropertyList2LeafOnlyStringList(panel_props);
623 SCIM_DEBUG_MAIN(1) << "SIMPLIFY_PROPS " << panel_props.size() << " " << list_result.size() - 1 << "\n";
624 Q_FOREACH (const QList<Property> &props, helper_props_map) {
625 list_result << PropertyList2LeafOnlyStringList(props);
626 }
627 list_result << Property2String(show_help_prop);
628
629 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "RegisterProperties");
630
631 message << list_result;
632 QDBusConnection("scim_panel").send(message);
633
634 break;
635 case DBusEvent::RM_HELPER:
636 helper_props_map.remove(ev->data().at(0).toInt());
637 list_result.clear();
638 list_result << Property2String(logo_prop);
639 list_result << PropertyList2LeafOnlyStringList(panel_props);
640 Q_FOREACH (const QList<Property> &props, helper_props_map) {
641 list_result << PropertyList2LeafOnlyStringList(props);
642 }
643 list_result << Property2String(show_help_prop);
644
645 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "RegisterProperties");
646
647 message << list_result;
648 QDBusConnection("scim_panel").send(message);
649
650 break;
651 case DBusEvent::RM_PROPERTY:
652 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "RemoveProperty");
653 // message << ev->data().at(0).V();
654 QDBusConnection("scim_panel").send(message);
655 break;
656 default:
657 message = QDBusMessage::createSignal("/kimpanel", "org.kde.kimpanel.inputmethod", "ImplementMe");
658 // message << ev->data().at(0).toInt();
659 SCIM_DEBUG_MAIN(1) << "Implement me:" << ev->scim_event_type() << "\n";
660 QDBusConnection("scim_panel").send(message);
661 break;
662 }
663
664 return true;
665 }
666 return QObject::event(e);
667 }
668
669 private:
670 QList<Property> panel_props;
671 QMap<int, QList<Property>> helper_props_map;
672 Property logo_prop;
673 Property show_help_prop;
674 QString factory_prop_prefix;
675 QString helper_prop_prefix;
676 QStringList cached_panel_props;
677 };
678
679 class PanelAgentThread : public QThread
680 {
681 Q_OBJECT
682 public:
PanelAgentThread(QObject * parent=nullptr)683 explicit PanelAgentThread(QObject *parent = nullptr)
684 : QThread(parent)
685 {
686 }
~PanelAgentThread()687 ~PanelAgentThread()
688 {
689 }
run()690 void run() override
691 {
692 if (!_panel_agent->run())
693 std::cerr << "Failed to run Panel.\n";
694 _global_resource_lock.lock();
695 _should_exit = true;
696 _global_resource_lock.unlock();
697 }
698 };
699
700 //////////////////////////////////////////////////////////////////////
701 // Start of PanelAgent Functions
702 //////////////////////////////////////////////////////////////////////
initialize_panel_agent(const String & config,const String & display,bool resident)703 static bool initialize_panel_agent(const String &config, const String &display, bool resident)
704 {
705 _panel_agent = new PanelAgent();
706
707 if (!_panel_agent->initialize(config, display, resident))
708 return false;
709
710 _panel_agent->signal_connect_transaction_start(slot(slot_transaction_start));
711 _panel_agent->signal_connect_transaction_end(slot(slot_transaction_end));
712 _panel_agent->signal_connect_reload_config(slot(slot_reload_config));
713 _panel_agent->signal_connect_turn_on(slot(slot_turn_on));
714 _panel_agent->signal_connect_turn_off(slot(slot_turn_off));
715 _panel_agent->signal_connect_update_screen(slot(slot_update_screen));
716 _panel_agent->signal_connect_update_spot_location(slot(slot_update_spot_location));
717 _panel_agent->signal_connect_update_factory_info(slot(slot_update_factory_info));
718 _panel_agent->signal_connect_show_help(slot(slot_show_help));
719 _panel_agent->signal_connect_show_factory_menu(slot(slot_show_factory_menu));
720 _panel_agent->signal_connect_show_preedit_string(slot(slot_show_preedit_string));
721 _panel_agent->signal_connect_show_aux_string(slot(slot_show_aux_string));
722 _panel_agent->signal_connect_show_lookup_table(slot(slot_show_lookup_table));
723 _panel_agent->signal_connect_hide_preedit_string(slot(slot_hide_preedit_string));
724 _panel_agent->signal_connect_hide_aux_string(slot(slot_hide_aux_string));
725 _panel_agent->signal_connect_hide_lookup_table(slot(slot_hide_lookup_table));
726 _panel_agent->signal_connect_update_preedit_string(slot(slot_update_preedit_string));
727 _panel_agent->signal_connect_update_preedit_caret(slot(slot_update_preedit_caret));
728 _panel_agent->signal_connect_update_aux_string(slot(slot_update_aux_string));
729 _panel_agent->signal_connect_update_lookup_table(slot(slot_update_lookup_table));
730 _panel_agent->signal_connect_register_properties(slot(slot_register_properties));
731 _panel_agent->signal_connect_update_property(slot(slot_update_property));
732 _panel_agent->signal_connect_register_helper_properties(slot(slot_register_helper_properties));
733 _panel_agent->signal_connect_update_helper_property(slot(slot_update_helper_property));
734 _panel_agent->signal_connect_register_helper(slot(slot_register_helper));
735 _panel_agent->signal_connect_remove_helper(slot(slot_remove_helper));
736 _panel_agent->signal_connect_lock(slot(slot_lock));
737 _panel_agent->signal_connect_unlock(slot(slot_unlock));
738
739 _panel_agent->get_helper_list(_helper_list);
740
741 return true;
742 }
743
run_panel_agent(void)744 static bool run_panel_agent(void)
745 {
746 SCIM_DEBUG_MAIN(1) << "run_panel_agent ()\n";
747
748 _panel_agent_thread = NULL;
749
750 if (_panel_agent && _panel_agent->valid()) {
751 _panel_agent_thread = new PanelAgentThread();
752 _panel_agent_thread->start();
753 }
754
755 return (_panel_agent_thread != NULL);
756 }
757
start_auto_start_helpers(void)758 static void start_auto_start_helpers(void)
759 {
760 SCIM_DEBUG_MAIN(1) << "start_auto_start_helpers () begin\n";
761
762 // Add Helper object items.
763 for (size_t i = 0; i < _helper_list.size(); ++i) {
764 SCIM_DEBUG_MAIN(1) << "--" << _helper_list[i].uuid << "--" << _helper_list[i].name << "--\n";
765 if ((_helper_list[i].option & SCIM_HELPER_AUTO_START)) {
766 _panel_agent->start_helper(_helper_list[i].uuid);
767 }
768 }
769 SCIM_DEBUG_MAIN(1) << "start_auto_start_helpers () end\n";
770 }
771
slot_transaction_start(void)772 static void slot_transaction_start(void)
773 {
774 SCIM_DEBUG_MAIN(1) << "slot_transaction_start ()\n";
775 _transaction_lock.lock();
776 }
777
slot_transaction_end(void)778 static void slot_transaction_end(void)
779 {
780 SCIM_DEBUG_MAIN(1) << "slot_transaction_end ()\n";
781 _transaction_lock.unlock();
782 }
783
slot_reload_config(void)784 static void slot_reload_config(void)
785 {
786 SCIM_DEBUG_MAIN(1) << "slot_reload_config ()\n";
787 if (!_config.null())
788 _config->reload();
789 else
790 SCIM_DEBUG_MAIN(1) << "config is null\n";
791 }
792
slot_turn_on(void)793 static void slot_turn_on(void)
794 {
795 SCIM_DEBUG_MAIN(1) << "slot_turn_on ()" << _dbus_handler << "\n";
796 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::TURN_ON));
797 }
798
slot_turn_off(void)799 static void slot_turn_off(void)
800 {
801 SCIM_DEBUG_MAIN(1) << "slot_turn_off ()\n";
802 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::TURN_OFF));
803
804 /*
805 */
806 }
807
slot_update_screen(int num)808 static void slot_update_screen(int num)
809 {
810 SCIM_DEBUG_MAIN(1) << "slot_update_screen ()\n";
811 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_SCREEN, QVariantList() << num));
812 }
813
slot_update_factory_info(const PanelFactoryInfo & info)814 static void slot_update_factory_info(const PanelFactoryInfo &info)
815 {
816 SCIM_DEBUG_MAIN(1) << "slot_update_factory_info ()\n";
817 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_FACTORY_INFO, QVariantList() << QVariant::fromValue(info)));
818 }
819
slot_show_help(const String & help)820 static void slot_show_help(const String &help)
821 {
822 SCIM_DEBUG_MAIN(1) << "slot_show_help ()\n";
823 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::SHOW_HELP, QVariantList() << QString::fromUtf8(help.c_str())));
824 }
825
slot_show_factory_menu(const std::vector<PanelFactoryInfo> & factories)826 static void slot_show_factory_menu(const std::vector<PanelFactoryInfo> &factories)
827 {
828 SCIM_DEBUG_MAIN(1) << "slot_show_factory_menu ()\n";
829 QVariantList list;
830 Q_FOREACH (const PanelFactoryInfo &info, factories) {
831 list << QVariant::fromValue(info);
832 }
833 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::SHOW_FACTORY_MENU, list));
834 }
835
slot_update_spot_location(int x,int y)836 static void slot_update_spot_location(int x, int y)
837 {
838 SCIM_DEBUG_MAIN(1) << "slot_update_spot_location ()\n";
839 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_SPOT_LOC, QVariantList() << x << y));
840 }
841
slot_show_preedit_string(void)842 static void slot_show_preedit_string(void)
843 {
844 SCIM_DEBUG_MAIN(1) << "slot_show_preedit_string ()\n";
845 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::SHOW_PREEDIT));
846 }
847
slot_show_aux_string(void)848 static void slot_show_aux_string(void)
849 {
850 SCIM_DEBUG_MAIN(1) << "slot_show_aux_string ()\n";
851 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::SHOW_AUX));
852 }
853
slot_show_lookup_table(void)854 static void slot_show_lookup_table(void)
855 {
856 SCIM_DEBUG_MAIN(1) << "slot_show_lookup_table ()\n";
857 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::SHOW_LOOKUPTABLE));
858 }
859
slot_hide_preedit_string(void)860 static void slot_hide_preedit_string(void)
861 {
862 SCIM_DEBUG_MAIN(1) << "slot_hide_preedit_string ()\n";
863 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::HIDE_PREEDIT));
864 }
865
slot_hide_aux_string(void)866 static void slot_hide_aux_string(void)
867 {
868 SCIM_DEBUG_MAIN(1) << "slot_hide_aux_string ()\n";
869 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::HIDE_AUX));
870 }
871
slot_hide_lookup_table(void)872 static void slot_hide_lookup_table(void)
873 {
874 SCIM_DEBUG_MAIN(1) << "slot_hide_lookup_table ()\n";
875 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::HIDE_LOOKUPTABLE));
876 }
877
slot_update_preedit_string(const String & str,const AttributeList & attrs)878 static void slot_update_preedit_string(const String &str, const AttributeList &attrs)
879 {
880 SCIM_DEBUG_MAIN(1) << "slot_update_preedit_string ()" << str << "\n";
881 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_PREEDIT_STR, QVariantList() << QString::fromUtf8(str.c_str()) << AttrList2String(attrs)));
882 }
883
slot_update_preedit_caret(int caret)884 static void slot_update_preedit_caret(int caret)
885 {
886 SCIM_DEBUG_MAIN(1) << "slot_update_preedit_caret ()" << caret << "\n";
887 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_PREEDIT_CARET, QVariantList() << caret));
888 }
889
slot_update_aux_string(const String & str,const AttributeList & attrs)890 static void slot_update_aux_string(const String &str, const AttributeList &attrs)
891 {
892 SCIM_DEBUG_MAIN(1) << "slot_update_aux_string ()" << str << "\n";
893 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_AUX, QVariantList() << QString::fromUtf8(str.c_str()) << AttrList2String(attrs)));
894 }
895
slot_update_lookup_table(const LookupTable & table)896 static void slot_update_lookup_table(const LookupTable &table)
897 {
898 SCIM_DEBUG_MAIN(1) << "slot_update_lookup_table ()\n";
899 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_LOOKUPTABLE, LookupTable2VariantList(table)));
900
901 qApp->postEvent(
902 _dbus_handler,
903 new DBusEvent(DBusEvent::UP_LOOKUPTABLE_CURSOR, QVariantList() << (table.is_cursor_visible() ? table.get_cursor_pos_in_current_page() : -1)));
904 }
905
slot_register_properties(const PropertyList & props)906 static void slot_register_properties(const PropertyList &props)
907 {
908 SCIM_DEBUG_MAIN(1) << "slot_register_properties ()\n";
909 QVariantList list;
910 Q_FOREACH (const Property &prop, props) {
911 list << QVariant::fromValue(prop);
912 }
913 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::REG_PROPERTIES, list));
914 }
915
slot_update_property(const Property & prop)916 static void slot_update_property(const Property &prop)
917 {
918 SCIM_DEBUG_MAIN(1) << "slot_update_property ()\n";
919 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_PROPERTY, QVariantList() << QVariant::fromValue(prop)));
920 }
921
slot_register_helper_properties(int id,const PropertyList & props)922 static void slot_register_helper_properties(int id, const PropertyList &props)
923 {
924 SCIM_DEBUG_MAIN(1) << "slot_register_helper_properties ()\n";
925 QVariantList list;
926 Q_FOREACH (const Property &prop, props) {
927 list << QVariant::fromValue(prop);
928 }
929 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::REG_HELPER_PROPERTIES, QVariantList() << id << list));
930 }
931
slot_update_helper_property(int id,const Property & prop)932 static void slot_update_helper_property(int id, const Property &prop)
933 {
934 SCIM_DEBUG_MAIN(1) << "slot_update_helper_property ()\n";
935 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::UP_HELPER_PROPERTY, QVariantList() << id << QVariant::fromValue(prop)));
936 }
937
slot_register_helper(int id,const HelperInfo & helper)938 static void slot_register_helper(int id, const HelperInfo &helper)
939 {
940 SCIM_DEBUG_MAIN(1) << "slot_register_helper ()\n";
941 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::REG_HELPER, QVariantList() << id << QVariant::fromValue(helper)));
942 }
943
slot_remove_helper(int id)944 static void slot_remove_helper(int id)
945 {
946 SCIM_DEBUG_MAIN(1) << "slot_remove_helper ()\n";
947 qApp->postEvent(_dbus_handler, new DBusEvent(DBusEvent::RM_HELPER, QVariantList() << id));
948 }
949
slot_lock(void)950 static void slot_lock(void)
951 {
952 SCIM_DEBUG_MAIN(1) << "slot_lock ()\n";
953 //_panel_agent_lock.lock();
954 }
955
slot_unlock(void)956 static void slot_unlock(void)
957 {
958 SCIM_DEBUG_MAIN(1) << "slot_unlock ()\n";
959 //_panel_agent_lock.unlock();
960 }
961 //////////////////////////////////////////////////////////////////////
962 // End of PanelAgent-Functions
963 //////////////////////////////////////////////////////////////////////
964
signalhandler(int sig)965 static void signalhandler(int sig)
966 {
967 Q_UNUSED(sig)
968 SCIM_DEBUG_MAIN(1) << "In signal handler...\n";
969
970 if (_panel_agent)
971 _panel_agent->stop();
972 }
973
main(int argc,char * argv[])974 int main(int argc, char *argv[])
975 {
976 std::vector<String> config_list;
977
978 int i;
979
980 bool daemon = false;
981
982 int new_argc = 0;
983 char **new_argv = new char *[40];
984
985 String config_name("simple");
986 String display_name;
987 bool should_resident = true;
988
989 // QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
990 // Display version info
991 // std::cerr << "GTK Panel of SCIM " << SCIM_VERSION << "\n\n";
992
993 // get modules list
994 scim_get_config_module_list(config_list);
995
996 // Add a dummy config module, it's not really a module!
997 config_list.push_back("dummy");
998
999 // Use socket Config module as default if available.
1000 if (!config_list.empty()) {
1001 if (std::find(config_list.begin(), config_list.end(), config_name) == config_list.end())
1002 config_name = config_list[0];
1003 }
1004
1005 // DebugOutput::set_output("/home/ora/a.log");
1006 // DebugOutput::enable_debug (SCIM_DEBUG_AllMask);
1007
1008 // parse command options
1009 i = 0;
1010 while (i < argc) {
1011 if (++i >= argc)
1012 break;
1013
1014 if (String("-l") == argv[i] || String("--list") == argv[i]) {
1015 std::vector<String>::iterator it;
1016
1017 std::cout << "\n";
1018 std::cout << "Available Config module:\n";
1019 for (it = config_list.begin(); it != config_list.end(); ++it)
1020 std::cout << " " << *it << "\n";
1021
1022 return 0;
1023 }
1024
1025 if (String("-c") == argv[i] || String("--config") == argv[i]) {
1026 if (++i >= argc) {
1027 std::cerr << "no argument for option " << argv[i - 1] << "\n";
1028 return -1;
1029 }
1030 config_name = argv[i];
1031 continue;
1032 }
1033
1034 if (String("-h") == argv[i] || String("--help") == argv[i]) {
1035 std::cout << "Usage: " << argv[0] << " [option]...\n\n"
1036 << "The options are: \n"
1037 << " --display DISPLAY Run on display DISPLAY.\n"
1038 << " -l, --list List all of available config modules.\n"
1039 << " -c, --config NAME Uses specified Config module.\n"
1040 << " -d, --daemon Run " << argv[0] << " as a daemon.\n"
1041 << " -ns, --no-stay Quit if no connected client.\n"
1042 #if ENABLE_DEBUG
1043 << " -v, --verbose LEVEL Enable debug info, to specific LEVEL.\n"
1044 << " -o, --output FILE Output debug information into FILE.\n"
1045 #endif
1046 << " -h, --help Show this help message.\n";
1047 return 0;
1048 }
1049
1050 if (String("-d") == argv[i] || String("--daemon") == argv[i]) {
1051 daemon = true;
1052 continue;
1053 }
1054
1055 if (String("-ns") == argv[i] || String("--no-stay") == argv[i]) {
1056 should_resident = false;
1057 continue;
1058 }
1059
1060 if (String("-v") == argv[i] || String("--verbose") == argv[i]) {
1061 if (++i >= argc) {
1062 std::cerr << "no argument for option " << argv[i - 1] << "\n";
1063 return -1;
1064 }
1065 DebugOutput::set_verbose_level(atoi(argv[i]));
1066 continue;
1067 }
1068
1069 if (String("-o") == argv[i] || String("--output") == argv[i]) {
1070 if (++i >= argc) {
1071 std::cerr << "No argument for option " << argv[i - 1] << "\n";
1072 return -1;
1073 }
1074 DebugOutput::set_output(argv[i]);
1075 continue;
1076 }
1077
1078 if (String("--display") == argv[i]) {
1079 if (++i >= argc) {
1080 std::cerr << "No argument for option " << argv[i - 1] << "\n";
1081 return -1;
1082 }
1083 display_name = argv[i];
1084 continue;
1085 }
1086
1087 if (String("--") == argv[i])
1088 break;
1089
1090 std::cerr << "Invalid command line option: " << argv[i] << "\n";
1091 return -1;
1092 } // End of command line parsing.
1093
1094 new_argv[new_argc++] = argv[0];
1095
1096 // Store the rest argvs into new_argv.
1097 for (++i; i < argc && new_argc < 40; ++i) {
1098 new_argv[new_argc++] = argv[i];
1099 }
1100
1101 // Make up DISPLAY env.
1102 if (display_name.length()) {
1103 new_argv[new_argc++] = strdup("--display");
1104 new_argv[new_argc++] = const_cast<char *>(display_name.c_str());
1105
1106 setenv("DISPLAY", display_name.c_str(), 1);
1107 }
1108
1109 new_argv[new_argc] = 0;
1110
1111 if (!config_name.length()) {
1112 std::cerr << "No Config module is available!\n";
1113 return -1;
1114 }
1115
1116 if (config_name != "dummy") {
1117 // load config module
1118 _config_module = new ConfigModule(config_name);
1119
1120 if (!_config_module || !_config_module->valid()) {
1121 std::cerr << "Can not load " << config_name << " Config module.\n";
1122 return -1;
1123 }
1124
1125 // create config instance
1126 _config = _config_module->create_config();
1127 } else {
1128 _config = new DummyConfig();
1129 }
1130
1131 if (_config.null()) {
1132 std::cerr << "Failed to create Config instance from " << config_name << " Config module.\n";
1133 return -1;
1134 }
1135
1136 KDE_signal(SIGQUIT, signalhandler);
1137 KDE_signal(SIGTERM, signalhandler);
1138 KDE_signal(SIGINT, signalhandler);
1139 KDE_signal(SIGHUP, signalhandler);
1140
1141 const QByteArray display = qgetenv("DISPLAY");
1142 if (display.constData())
1143 display_name = String(display.constData());
1144
1145 if (!initialize_panel_agent(config_name, display_name, should_resident)) {
1146 std::cerr << "Failed to initialize Panel Agent!\n";
1147 return -1;
1148 }
1149
1150 if (daemon)
1151 scim_daemon();
1152
1153 // connect the configuration reload signal.
1154 _config->signal_connect_reload(slot(ui_config_reload_callback));
1155
1156 qRegisterMetaType<scim::Property>("scim::Property");
1157 qRegisterMetaType<PanelFactoryInfo>("PanelFactoryInfo");
1158 qRegisterMetaType<HelperInfo>("HelperInfo");
1159
1160 QDBusConnection::connectToBus(QDBusConnection::SessionBus, "scim_panel");
1161 _dbus_handler = new DBusHandler();
1162 _dbus_handler->setInitialHelpers(_helper_list);
1163
1164 if (!run_panel_agent()) {
1165 std::cerr << "Failed to run Socket Server!\n";
1166 return -1;
1167 }
1168
1169 start_auto_start_helpers();
1170
1171 QCoreApplication app(argc, argv);
1172 app.exec();
1173
1174 _panel_agent_thread->wait();
1175 _config.reset();
1176
1177 std::cerr << "Successfully exited.\n";
1178
1179 return 0;
1180 }
1181
1182 #include "main.moc"
1183
1184 #undef QT_NO_KEYWORDS
1185
1186 /*
1187 vim:ts=4:nowrap:expandtab
1188 */
1189