~ubuntu-branches/ubuntu/wily/scim/wily-proposed

« back to all changes in this revision

Viewing changes to .pc/23_scim-1.4.7-remove-help-frame.patch/extras/panel/scim_panel_gtk.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Rolf Leggewie
  • Date: 2010-08-11 18:28:44 UTC
  • mfrom: (3.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100811182844-rnn95k63cwehtm75
Tags: 1.4.9-5
* debian/copyright: add my copyright
* debian/control: update to standard 3.9.1, no further changes necessary

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file scim_panel_gtk.cpp
 
2
 */
 
3
 
 
4
/* 
 
5
 * Smart Common Input Method
 
6
 * 
 
7
 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
 
8
 *
 
9
 *
 
10
 * This library is free software; you can redistribute it and/or
 
11
 * modify it under the terms of the GNU Lesser General Public
 
12
 * License as published by the Free Software Foundation; either
 
13
 * version 2 of the License, or (at your option) any later version.
 
14
 *
 
15
 * This library is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 * GNU Lesser General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU Lesser General Public
 
21
 * License along with this program; if not, write to the
 
22
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 
23
 * Boston, MA  02111-1307  USA
 
24
 *
 
25
 * $Id: scim_panel_gtk.cpp,v 1.118.2.15 2007/04/11 11:30:31 suzhe Exp $
 
26
 */
 
27
 
 
28
#include <sys/wait.h>
 
29
#include <sys/types.h>
 
30
#include <sys/time.h>
 
31
#include <signal.h>
 
32
#include <unistd.h>
 
33
#include <errno.h>
 
34
#include <glib.h>
 
35
#include <gdk/gdk.h>
 
36
#ifdef GDK_WINDOWING_X11
 
37
#include <gdk/gdkx.h>
 
38
#endif
 
39
#include <gtk/gtk.h>
 
40
#include <stdlib.h>
 
41
#include <list>
 
42
 
 
43
#define Uses_C_STDIO
 
44
#define Uses_C_STDLIB
 
45
#define Uses_SCIM_LOOKUP_TABLE
 
46
#define Uses_SCIM_SOCKET
 
47
#define Uses_SCIM_TRANSACTION
 
48
#define Uses_SCIM_TRANS_COMMANDS
 
49
#define Uses_SCIM_CONFIG
 
50
#define Uses_SCIM_CONFIG_MODULE
 
51
#define Uses_SCIM_DEBUG
 
52
#define Uses_SCIM_HELPER
 
53
#define Uses_SCIM_HELPER_MODULE
 
54
#define Uses_SCIM_PANEL_AGENT
 
55
 
 
56
#include "scim_private.h"
 
57
#include "scim.h"
 
58
#include "scim_stl_map.h"
 
59
 
 
60
#include "scimstringview.h"
 
61
 
 
62
#if ENABLE_TRAY_ICON
 
63
  #include "scimtrayicon.h"
 
64
#endif
 
65
 
 
66
using namespace scim;
 
67
 
 
68
#include "icons/up.xpm"
 
69
#include "icons/down.xpm"
 
70
#include "icons/left.xpm"
 
71
#include "icons/right.xpm"
 
72
#include "icons/setup.xpm"
 
73
#include "icons/help.xpm"
 
74
#include "icons/trademark.xpm"
 
75
#include "icons/pin-up.xpm"
 
76
#include "icons/pin-down.xpm"
 
77
#include "icons/menu.xpm"
 
78
 
 
79
#define SCIM_CONFIG_PANEL_GTK_FONT                      "/Panel/Gtk/Font"
 
80
#define SCIM_CONFIG_PANEL_GTK_COLOR_NORMAL_BG           "/Panel/Gtk/Color/NormalBackground"
 
81
#define SCIM_CONFIG_PANEL_GTK_COLOR_ACTIVE_BG           "/Panel/Gtk/Color/ActiveBackground"
 
82
#define SCIM_CONFIG_PANEL_GTK_COLOR_NORMAL_TEXT         "/Panel/Gtk/Color/NormalText"
 
83
#define SCIM_CONFIG_PANEL_GTK_COLOR_ACTIVE_TEXT         "/Panel/Gtk/Color/ActiveText"
 
84
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_ALWAYS_SHOW       "/Panel/Gtk/ToolBar/AlwaysShow"
 
85
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_ALWAYS_HIDDEN     "/Panel/Gtk/ToolBar/AlwaysHidden"
 
86
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_AUTO_SNAP         "/Panel/Gtk/ToolBar/AutoSnap"
 
87
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_HIDE_TIMEOUT      "/Panel/Gtk/ToolBar/HideTimeout"
 
88
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_POS_X             "/Panel/Gtk/ToolBar/POS_X"
 
89
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_POS_Y             "/Panel/Gtk/ToolBar/POS_Y"
 
90
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_FACTORY_ICON "/Panel/Gtk/ToolBar/ShowFactoryIcon"
 
91
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_FACTORY_NAME "/Panel/Gtk/ToolBar/ShowFactoryName"
 
92
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_STICK_ICON   "/Panel/Gtk/ToolBar/ShowStickIcon"
 
93
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_HELP_ICON    "/Panel/Gtk/ToolBar/ShowHelpIcon"
 
94
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_MENU_ICON    "/Panel/Gtk/ToolBar/ShowMenuIcon"
 
95
#define SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_PROPERTY_LABEL "/Panel/Gtk/ToolBar/ShowPropertyLabel"
 
96
#define SCIM_CONFIG_PANEL_GTK_LOOKUP_TABLE_EMBEDDED     "/Panel/Gtk/LookupTableEmbedded"
 
97
#define SCIM_CONFIG_PANEL_GTK_LOOKUP_TABLE_VERTICAL     "/Panel/Gtk/LookupTableVertical"
 
98
#define SCIM_CONFIG_PANEL_GTK_DEFAULT_STICKED           "/Panel/Gtk/DefaultSticked"
 
99
#define SCIM_CONFIG_PANEL_GTK_SHOW_TRAY_ICON            "/Panel/Gtk/ShowTrayIcon"
 
100
 
 
101
#define SCIM_KEYBOARD_ICON_FILE     (SCIM_ICONDIR "/keyboard.png")
 
102
#define SCIM_TRADEMARK_ICON_FILE    (SCIM_ICONDIR "/trademark.png")
 
103
#define SCIM_SETUP_ICON_FILE        (SCIM_ICONDIR "/setup.png")
 
104
#define SCIM_HELP_ICON_FILE         (SCIM_ICONDIR "/help.png")
 
105
#define SCIM_MENU_ICON_FILE         (SCIM_ICONDIR "/menu.png")
 
106
#define SCIM_UP_ICON_FILE           (SCIM_ICONDIR "/up.png")
 
107
#define SCIM_DOWN_ICON_FILE         (SCIM_ICONDIR "/down.png")
 
108
#define SCIM_LEFT_ICON_FILE         (SCIM_ICONDIR "/left.png")
 
109
#define SCIM_RIGHT_ICON_FILE        (SCIM_ICONDIR "/right.png")
 
110
#define SCIM_PIN_UP_ICON_FILE       (SCIM_ICONDIR "/pin-up.png")
 
111
#define SCIM_PIN_DOWN_ICON_FILE     (SCIM_ICONDIR "/pin-down.png")
 
112
 
 
113
#define TOOLBAR_ICON_SIZE                     16 
 
114
#define TRAY_ICON_SIZE                        11
 
115
#define LOOKUP_ICON_SIZE                      12
 
116
 
 
117
/////////////////////////////////////////////////////////////////////////////
 
118
// Declaration of internal data types.
 
119
/////////////////////////////////////////////////////////////////////////////
 
120
struct PropertyInfo {
 
121
    Property   property;
 
122
    GtkWidget *widget;
 
123
 
 
124
    PropertyInfo () : widget (0) { }
 
125
};
 
126
 
 
127
typedef std::vector <PropertyInfo>               PropertyRepository;
 
128
 
 
129
struct HelperPropertyInfo {
 
130
    GtkWidget           *holder;
 
131
    PropertyRepository   repository;
 
132
 
 
133
    HelperPropertyInfo () : holder (0) { }
 
134
};
 
135
 
 
136
#if SCIM_USE_STL_EXT_HASH_MAP
 
137
typedef __gnu_cxx::hash_map <int, HelperPropertyInfo, __gnu_cxx::hash <int> > HelperPropertyRepository;
 
138
typedef __gnu_cxx::hash_map <String, std::vector <size_t>, scim_hash_string>  MapStringVectorSizeT;
 
139
#elif SCIM_USE_STL_HASH_MAP
 
140
typedef std::hash_map <int, HelperPropertyInfo, std::hash <int> >             HelperPropertyRepository;
 
141
typedef std::hash_map <String, std::vector <size_t>, scim_hash_string>        MapStringVectorSizeT;
 
142
#else
 
143
typedef std::map <int, HelperPropertyInfo>                                    HelperPropertyRepository;
 
144
typedef std::map <String, std::vector <size_t> >                              MapStringVectorSizeT;
 
145
#endif
 
146
 
 
147
/////////////////////////////////////////////////////////////////////////////
 
148
// Declaration of internal functions.
 
149
/////////////////////////////////////////////////////////////////////////////
 
150
static void       ui_config_reload_callback            (const ConfigPointer &config);
 
151
static void       ui_load_config                       (void);
 
152
static void       ui_initialize                        (void);
 
153
 
 
154
static void       ui_settle_input_window               (bool            relative = false,
 
155
                                                        bool            force    = false);
 
156
static void       ui_settle_lookup_table_window        (bool            force    = false);
 
157
static void       ui_settle_toolbar_window             (bool            force    = false);
 
158
 
 
159
static int        ui_screen_width                      (void);
 
160
static int        ui_screen_height                     (void);
 
161
static void       ui_get_workarea                      (int            &x,
 
162
                                                        int            &y,
 
163
                                                        int            &width,
 
164
                                                        int            &height);
 
165
 
 
166
#if ENABLE_TRAY_ICON
 
167
static gboolean   ui_create_tray_icon_when_idle        (gpointer        data);
 
168
#endif
 
169
 
 
170
#if GDK_MULTIHEAD_SAFE
 
171
static void       ui_switch_screen                     (GdkScreen      *screen);
 
172
#endif
 
173
 
 
174
static GdkPixbuf* ui_scale_pixbuf                      (GdkPixbuf      *pixbuf,
 
175
                                                        int             width,
 
176
                                                        int             height);
 
177
 
 
178
static GtkWidget* ui_create_label                      (const String   &name,
 
179
                                                        const String   &iconfile,
 
180
                                                        const char    **xpm,
 
181
                                                        bool            show_icon_only = false,
 
182
                                                        bool            force_icon = false);
 
183
 
 
184
static GtkWidget* ui_create_icon                       (const String   &iconfile,
 
185
                                                        const char    **xpm = NULL,
 
186
                                                        int             width = -1,
 
187
                                                        int             height = -1,
 
188
                                                        bool            force_create = false);
 
189
 
 
190
static GtkWidget* ui_create_trademark_icon             (void);
 
191
static GtkWidget* ui_create_stick_icon                 (bool            sticked);
 
192
static GtkWidget* ui_create_help_icon                  (void);
 
193
static GtkWidget* ui_create_menu_icon                  (void);
 
194
static GtkWidget* ui_create_up_icon                    (void);
 
195
static GtkWidget* ui_create_down_icon                  (void);
 
196
static GtkWidget* ui_create_left_icon                  (void);
 
197
static GtkWidget* ui_create_right_icon                 (void);
 
198
 
 
199
static GtkWidget* ui_create_factory_menu_entry         (const PanelFactoryInfo &info,
 
200
                                                        int                    id,
 
201
                                                        GtkMenuShell           *menu,
 
202
                                                        bool                   show_lang,
 
203
                                                        bool                   show_name);
 
204
 
 
205
// callback functions
 
206
static void       ui_preedit_area_move_cursor_cb       (ScimStringView *view,
 
207
                                                        guint           position);
 
208
 
 
209
static void       ui_help_button_click_cb              (GtkButton      *button,
 
210
                                                        gpointer        user_data);
 
211
static void       ui_menu_button_click_cb              (GtkButton      *button,
 
212
                                                        gpointer        user_data);
 
213
static gboolean   ui_factory_button_click_cb           (GtkWidget      *button,
 
214
                                                        GdkEvent       *event,
 
215
                                                        gpointer        user_data);
 
216
static void       ui_factory_menu_activate_cb          (GtkMenuItem    *item,
 
217
                                                        gpointer        user_data);
 
218
static void       ui_factory_menu_deactivate_cb        (GtkMenuItem    *item,
 
219
                                                        gpointer        user_data);
 
220
 
 
221
static gboolean   ui_lookup_table_vertical_click_cb    (GtkWidget      *item,
 
222
                                                        GdkEventButton *event,
 
223
                                                        gpointer        user_data);
 
224
 
 
225
static void       ui_lookup_table_horizontal_click_cb  (GtkWidget      *item,
 
226
                                                        guint           position);
 
227
 
 
228
static void       ui_lookup_table_up_button_click_cb   (GtkButton      *button,
 
229
                                                        gpointer        user_data);
 
230
static void       ui_lookup_table_down_button_click_cb (GtkButton      *button,
 
231
                                                        gpointer        user_data);
 
232
 
 
233
static void       ui_window_stick_button_click_cb      (GtkButton      *button,
 
234
                                                        gpointer        user_data);
 
235
 
 
236
static gboolean   ui_input_window_motion_cb            (GtkWidget      *window,
 
237
                                                        GdkEventMotion *event,
 
238
                                                        gpointer        user_data);
 
239
static gboolean   ui_input_window_click_cb             (GtkWidget      *window,
 
240
                                                        GdkEventButton *event,
 
241
                                                        gpointer        user_data);
 
242
static gboolean   ui_toolbar_window_crossing_cb        (GtkWidget      *window,
 
243
                                                        GdkEventCrossing *event,
 
244
                                                        gpointer        user_data);
 
245
static gboolean   ui_toolbar_window_motion_cb          (GtkWidget      *window,
 
246
                                                        GdkEventMotion *event,
 
247
                                                        gpointer        user_data);
 
248
static gboolean   ui_toolbar_window_click_cb           (GtkWidget      *window,
 
249
                                                        GdkEventButton *event,
 
250
                                                        gpointer        user_data);
 
251
static gboolean   ui_lookup_table_window_motion_cb     (GtkWidget      *window,
 
252
                                                        GdkEventMotion *event,
 
253
                                                        gpointer        user_data);
 
254
static gboolean   ui_lookup_table_window_click_cb      (GtkWidget      *window,
 
255
                                                        GdkEventButton *event,
 
256
                                                        gpointer        user_data);
 
257
 
 
258
static gboolean   ui_hide_window_timeout_cb            (gpointer data);
 
259
 
 
260
static void       ui_command_menu_exit_activate_cb     (GtkMenuItem    *item,
 
261
                                                        gpointer        user_data);
 
262
 
 
263
static void       ui_command_menu_reload_activate_cb   (GtkMenuItem    *item,
 
264
                                                        gpointer        user_data);
 
265
static void       ui_command_menu_stick_activate_cb    (GtkMenuItem    *item,
 
266
                                                        gpointer        user_data);
 
267
static void       ui_command_menu_hide_toolbar_toggled_cb (GtkMenuItem    *item,
 
268
                                                           gpointer        user_data);
 
269
static void       ui_command_menu_help_activate_cb     (GtkMenuItem    *item,
 
270
                                                        gpointer        user_data);
 
271
static void       ui_command_menu_helper_activate_cb   (GtkWidget      *item,
 
272
                                                        gpointer        user_data);
 
273
static void       ui_command_menu_deactivate_cb        (GtkWidget      *item,
 
274
                                                        gpointer        user_data);
 
275
 
 
276
#if ENABLE_TRAY_ICON
 
277
static void       ui_tray_icon_destroy_cb              (GtkObject      *object,
 
278
                                                        gpointer        user_data);
 
279
#endif
 
280
 
 
281
// Client Property Callback
 
282
static void       ui_property_activate_cb              (GtkWidget      *widget,
 
283
                                                        gpointer        user_data);
 
284
 
 
285
static void       ui_property_menu_deactivate_cb       (GtkWidget      *item,
 
286
                                                        gpointer        user_data);
 
287
 
 
288
static bool       ui_can_hide_input_window             (void);
 
289
 
 
290
static bool       ui_any_menu_activated                (void);
 
291
 
 
292
static void       ui_show_help                         (const String   &help);
 
293
 
 
294
static PangoAttrList * create_pango_attrlist           (const String    &str,
 
295
                                                        const AttributeList &attrs);
 
296
 
 
297
// Action function
 
298
static void       action_request_help                  (void);
 
299
static void       action_toggle_window_stick           (void);
 
300
static void       action_show_command_menu             (void);
 
301
 
 
302
// PanelAgent related functions
 
303
static bool       initialize_panel_agent               (const String &config, const String &display, bool resident);
 
304
static bool       run_panel_agent                      (void);
 
305
static gpointer   panel_agent_thread_func              (gpointer data);
 
306
static void       start_auto_start_helpers             (void);
 
307
                  
 
308
static void       slot_transaction_start               (void);
 
309
static void       slot_transaction_end                 (void);
 
310
static void       slot_reload_config                   (void);
 
311
static void       slot_turn_on                         (void);
 
312
static void       slot_turn_off                        (void);
 
313
static void       slot_update_screen                   (int screen);
 
314
static void       slot_update_spot_location            (int x, int y);
 
315
static void       slot_update_factory_info             (const PanelFactoryInfo &info);
 
316
static void       slot_show_help                       (const String &help);
 
317
static void       slot_show_factory_menu               (const std::vector <PanelFactoryInfo> &menu);
 
318
                  
 
319
static void       slot_show_preedit_string             (void);
 
320
static void       slot_show_aux_string                 (void);
 
321
static void       slot_show_lookup_table               (void);
 
322
static void       slot_hide_preedit_string             (void);
 
323
static void       slot_hide_aux_string                 (void);
 
324
static void       slot_hide_lookup_table               (void);
 
325
static void       slot_update_preedit_string           (const String &str, const AttributeList &attrs);
 
326
static void       slot_update_preedit_caret            (int caret);
 
327
static void       slot_update_aux_string               (const String &str, const AttributeList &attrs);
 
328
static void       slot_update_lookup_table             (const LookupTable &table);
 
329
static void       slot_register_properties             (const PropertyList &props);
 
330
static void       slot_update_property                 (const Property &prop);
 
331
                  
 
332
static void       slot_register_helper_properties      (int id, const PropertyList &props);
 
333
static void       slot_update_helper_property          (int id, const Property &prop);
 
334
static void       slot_register_helper                 (int id, const HelperInfo &helper);
 
335
static void       slot_remove_helper                   (int id);
 
336
static void       slot_lock                            (void);
 
337
static void       slot_unlock                          (void);
 
338
 
 
339
 
 
340
static void       create_properties                    (GtkWidget            *container,
 
341
                                                        PropertyRepository &repository,
 
342
                                                        const PropertyList   &properties,
 
343
                                                        int                   client,
 
344
                                                        int                   level);
 
345
 
 
346
static GtkWidget* create_properties_node               (PropertyRepository         &repository,
 
347
                                                        PropertyList::const_iterator  begin,
 
348
                                                        PropertyList::const_iterator  end,
 
349
                                                        int                           client,
 
350
                                                        int                           level);
 
351
 
 
352
static void       register_frontend_properties         (const PropertyList &properties);
 
353
static void       update_frontend_property             (const Property     &property);
 
354
static void       register_helper_properties           (int                 client,
 
355
                                                        const PropertyList &properties);
 
356
static void       update_helper_property               (int                 client,
 
357
                                                        const Property     &property);
 
358
 
 
359
static void       update_property                      (PropertyRepository &repository,
 
360
                                                        const Property       &property);
 
361
 
 
362
static void       restore_properties                   (void);
 
363
 
 
364
static gboolean   check_exit_timeout_cb                (gpointer data);
 
365
 
 
366
 
 
367
/////////////////////////////////////////////////////////////////////////////
 
368
// Declaration of internal variables.
 
369
/////////////////////////////////////////////////////////////////////////////
 
370
#if GDK_MULTIHEAD_SAFE
 
371
static GdkScreen         *_current_screen              = 0;
 
372
#endif
 
373
 
 
374
static GtkWidget         *_input_window                = 0;
 
375
static GtkWidget         *_preedit_area                = 0;
 
376
static GtkWidget         *_aux_area                    = 0;
 
377
 
 
378
static GtkWidget         *_lookup_table_window         = 0;
 
379
static GtkWidget         *_lookup_table_up_button      = 0;
 
380
static GtkWidget         *_lookup_table_down_button    = 0;
 
381
static GtkWidget         *_lookup_table_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
 
382
 
 
383
static GtkWidget         *_toolbar_window              = 0;
 
384
static GtkWidget         *_window_stick_button         = 0;
 
385
static GtkWidget         *_factory_button              = 0;
 
386
static GtkWidget         *_factory_menu                = 0;
 
387
static GtkWidget         *_help_button                 = 0;
 
388
static GtkWidget         *_menu_button                 = 0;
 
389
static GtkWidget         *_client_properties_area      = 0;
 
390
static GtkWidget         *_frontend_properties_area    = 0;
 
391
 
 
392
static GtkWidget         *_help_dialog                 = 0;
 
393
static GtkWidget         *_help_scroll                 = 0;
 
394
static GtkWidget         *_help_area                   = 0;
 
395
static GtkWidget         *_command_menu                = 0;
 
396
 
 
397
static GtkTooltips       *_tooltips                    = 0;
 
398
 
 
399
static PangoFontDescription *_default_font_desc        = 0;
 
400
 
 
401
#if ENABLE_TRAY_ICON
 
402
static ScimTrayIcon      *_tray_icon                   = 0;
 
403
static GtkWidget         *_tray_icon_factory_button    = 0;
 
404
static gulong             _tray_icon_destroy_signal_id = 0;
 
405
#endif
 
406
 
 
407
static gboolean           _input_window_draging        = FALSE;
 
408
static gint               _input_window_drag_x         = 0;
 
409
static gint               _input_window_drag_y         = 0;
 
410
 
 
411
static gint               _input_window_x              = 0;
 
412
static gint               _input_window_y              = 0;
 
413
 
 
414
static gboolean           _toolbar_window_draging      = FALSE;
 
415
static gint               _toolbar_window_drag_x       = 0;
 
416
static gint               _toolbar_window_drag_y       = 0;
 
417
 
 
418
static gboolean           _lookup_table_window_draging = FALSE;
 
419
static gint               _lookup_table_window_drag_x  = 0;
 
420
static gint               _lookup_table_window_drag_y  = 0;
 
421
static gint               _lookup_table_window_x       = 0;
 
422
static gint               _lookup_table_window_y       = 0;
 
423
 
 
424
static bool               _lookup_table_embedded       = true;
 
425
static bool               _lookup_table_vertical       = false;
 
426
static bool               _window_sticked              = false;
 
427
 
 
428
#if ENABLE_TRAY_ICON
 
429
static bool               _show_tray_icon              = true;
 
430
#endif
 
431
 
 
432
static bool               _toolbar_always_show         = false;
 
433
static bool               _toolbar_always_hidden       = false;
 
434
static bool               _toolbar_auto_snap           = true;
 
435
static bool               _toolbar_show_factory_icon   = true;
 
436
static bool               _toolbar_show_factory_name   = false;
 
437
static bool               _toolbar_show_stick_icon     = false;
 
438
static bool               _toolbar_show_help_icon      = false;
 
439
static bool               _toolbar_show_menu_icon      = false;
 
440
static bool               _toolbar_show_property_label = false;
 
441
 
 
442
static bool               _toolbar_should_hide         = false;
 
443
static bool               _toolbar_hidden              = false;
 
444
static bool               _factory_menu_activated      = false;
 
445
static bool               _command_menu_activated      = false;
 
446
static bool               _property_menu_activated     = false;
 
447
 
 
448
static int                _spot_location_x             = -1;
 
449
static int                _spot_location_y             = -1;
 
450
 
 
451
static int                _toolbar_window_x            = -1;
 
452
static int                _toolbar_window_y            = -1;
 
453
static int                _toolbar_hide_timeout_max    = 0;
 
454
static int                _toolbar_hide_timeout_count  = 0;
 
455
static guint              _toolbar_hide_timeout        = 0;
 
456
 
 
457
static bool               _ui_initialized              = false;
 
458
 
 
459
static int                _lookup_table_index [SCIM_LOOKUP_TABLE_MAX_PAGESIZE+1];
 
460
 
 
461
static GdkColor           _normal_bg;
 
462
static GdkColor           _normal_text;
 
463
static GdkColor           _active_bg;
 
464
static GdkColor           _active_text;
 
465
 
 
466
static ConfigModule      *_config_module               = 0;
 
467
static ConfigPointer      _config;
 
468
 
 
469
static guint              _check_exit_timeout          = 0;
 
470
 
 
471
static bool               _should_exit                 = false;
 
472
 
 
473
static bool               _panel_is_on                 = false;
 
474
 
 
475
static GThread           *_panel_agent_thread          = 0;
 
476
 
 
477
static PanelAgent        *_panel_agent                 = 0;
 
478
 
 
479
static std::vector<String> _factory_menu_uuids;
 
480
 
 
481
static std::list<String>  _recent_factory_uuids;
 
482
 
 
483
static struct timeval     _last_menu_deactivate_time = {0, 0};
 
484
 
 
485
// client repository
 
486
static PropertyRepository            _frontend_property_repository;
 
487
static HelperPropertyRepository      _helper_property_repository;
 
488
static std::vector<HelperInfo>       _helper_list;
 
489
 
 
490
G_LOCK_DEFINE_STATIC     (_global_resource_lock);
 
491
G_LOCK_DEFINE_STATIC     (_panel_agent_lock);
 
492
 
 
493
 
 
494
/////////////////////////////////////////////////////////////////////////////
 
495
// Implementation of internal functions.
 
496
/////////////////////////////////////////////////////////////////////////////
 
497
static void
 
498
ui_config_reload_callback (const ConfigPointer &config)
 
499
{
 
500
    _config = config;
 
501
    ui_initialize ();
 
502
    restore_properties ();
 
503
}
 
504
 
 
505
static void
 
506
ui_load_config (void)
 
507
{
 
508
    String str;
 
509
 
 
510
    // Read configurations.
 
511
    gdk_color_parse ("gray92",     &_normal_bg);
 
512
    gdk_color_parse ("black",      &_normal_text);
 
513
    gdk_color_parse ("light blue", &_active_bg);
 
514
    gdk_color_parse ("black",      &_active_text);
 
515
 
 
516
    if (_default_font_desc) {
 
517
        pango_font_description_free (_default_font_desc);
 
518
        _default_font_desc = 0;
 
519
    }
 
520
 
 
521
    if (!_config.null ()) {
 
522
        str = _config->read (String (SCIM_CONFIG_PANEL_GTK_FONT),
 
523
                              String ("default"));
 
524
 
 
525
        if (str != String ("default"))
 
526
            _default_font_desc = pango_font_description_from_string (str.c_str ());
 
527
 
 
528
        str = _config->read (String (SCIM_CONFIG_PANEL_GTK_COLOR_NORMAL_BG),
 
529
                             String ("gray92"));
 
530
        gdk_color_parse (str.c_str (), &_normal_bg);
 
531
 
 
532
        str = _config->read (String (SCIM_CONFIG_PANEL_GTK_COLOR_NORMAL_TEXT),
 
533
                             String ("black"));
 
534
        gdk_color_parse (str.c_str (), &_normal_text);
 
535
 
 
536
        str = _config->read (String (SCIM_CONFIG_PANEL_GTK_COLOR_ACTIVE_BG),
 
537
                             String ("light blue"));
 
538
        gdk_color_parse (str.c_str (), &_active_bg);
 
539
 
 
540
        str = _config->read (String (SCIM_CONFIG_PANEL_GTK_COLOR_ACTIVE_TEXT),
 
541
                             String ("black"));
 
542
        gdk_color_parse (str.c_str (), &_active_text);
 
543
 
 
544
        _toolbar_window_x = _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_POS_X),
 
545
                                           _toolbar_window_x);
 
546
 
 
547
        _toolbar_window_y = _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_POS_Y),
 
548
                                           _toolbar_window_y);
 
549
 
 
550
        _window_sticked  =
 
551
            _config->read (String (SCIM_CONFIG_PANEL_GTK_DEFAULT_STICKED),
 
552
                           _window_sticked);
 
553
 
 
554
        _lookup_table_vertical =
 
555
            _config->read (String (SCIM_CONFIG_PANEL_GTK_LOOKUP_TABLE_VERTICAL),
 
556
                           _lookup_table_vertical);
 
557
 
 
558
        _lookup_table_embedded =
 
559
            _config->read (String (SCIM_CONFIG_PANEL_GTK_LOOKUP_TABLE_EMBEDDED),
 
560
                           _lookup_table_embedded);
 
561
 
 
562
        _toolbar_always_show =
 
563
            _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_ALWAYS_SHOW),
 
564
                           _toolbar_always_show);
 
565
 
 
566
        _toolbar_always_hidden =
 
567
            _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_ALWAYS_HIDDEN),
 
568
                           _toolbar_always_hidden);
 
569
 
 
570
        // Impossible
 
571
        if (_toolbar_always_show && _toolbar_always_hidden)
 
572
            _toolbar_always_hidden = false;
 
573
 
 
574
        _toolbar_auto_snap =
 
575
            _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_AUTO_SNAP),
 
576
                           _toolbar_auto_snap);
 
577
 
 
578
        _toolbar_show_factory_icon =
 
579
            _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_FACTORY_ICON),
 
580
                           _toolbar_show_factory_icon);
 
581
 
 
582
        _toolbar_show_factory_name =
 
583
            _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_FACTORY_NAME),
 
584
                           _toolbar_show_factory_name);
 
585
 
 
586
        _toolbar_show_stick_icon =
 
587
            _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_STICK_ICON),
 
588
                           _toolbar_show_stick_icon);
 
589
 
 
590
        _toolbar_show_help_icon =
 
591
            _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_HELP_ICON),
 
592
                           _toolbar_show_help_icon);
 
593
 
 
594
        _toolbar_show_menu_icon =
 
595
            _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_MENU_ICON),
 
596
                           _toolbar_show_menu_icon);
 
597
 
 
598
        _toolbar_show_property_label =
 
599
            _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_SHOW_PROPERTY_LABEL),
 
600
                           _toolbar_show_property_label);
 
601
 
 
602
        _toolbar_hide_timeout_max =
 
603
            _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_HIDE_TIMEOUT),
 
604
                           _toolbar_hide_timeout_max);
 
605
 
 
606
#if ENABLE_TRAY_ICON
 
607
        _show_tray_icon =
 
608
            _config->read (String (SCIM_CONFIG_PANEL_GTK_SHOW_TRAY_ICON),
 
609
                           _show_tray_icon);
 
610
#endif
 
611
    }
 
612
}
 
613
 
 
614
#ifdef GDK_WINDOWING_X11
 
615
static GdkFilterReturn
 
616
ui_event_filter (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
 
617
{
 
618
    g_return_val_if_fail (gdk_xevent, GDK_FILTER_CONTINUE);
 
619
 
 
620
    XEvent *xev = (XEvent*)gdk_xevent;
 
621
 
 
622
    if (xev->type == PropertyNotify) {
 
623
        if (xev->xproperty.atom == gdk_x11_get_xatom_by_name ("_NET_WORKAREA") ||
 
624
            xev->xproperty.atom == gdk_x11_get_xatom_by_name ("_NET_CURRENT_DESKTOP")) {
 
625
            ui_settle_toolbar_window ();
 
626
        }
 
627
    }
 
628
 
 
629
    return GDK_FILTER_CONTINUE;
 
630
}
 
631
#endif
 
632
 
 
633
static void
 
634
ui_initialize (void)
 
635
{
 
636
    SCIM_DEBUG_MAIN (1) << "Initialize UI...\n";
 
637
 
 
638
    GtkWidget *input_window_vbox;
 
639
 
 
640
    ui_load_config ();
 
641
 
 
642
    if (_lookup_table_window) gtk_widget_destroy (_lookup_table_window);
 
643
    if (_input_window) gtk_widget_destroy (_input_window);
 
644
    if (_toolbar_window) gtk_widget_destroy (_toolbar_window);
 
645
    if (_help_dialog) gtk_widget_destroy (_help_dialog);
 
646
    if (_tooltips) gtk_object_destroy (GTK_OBJECT (_tooltips));
 
647
 
 
648
#if ENABLE_TRAY_ICON
 
649
    if (_tray_icon) {
 
650
        g_signal_handler_disconnect (G_OBJECT (_tray_icon),
 
651
                                     _tray_icon_destroy_signal_id);
 
652
        gtk_widget_destroy (GTK_WIDGET (_tray_icon));
 
653
    }
 
654
    _tray_icon = 0;
 
655
#endif
 
656
 
 
657
    _lookup_table_window = 0;
 
658
    _input_window = 0;
 
659
    _toolbar_window = 0;
 
660
    _help_dialog = 0;
 
661
    _tooltips = 0;
 
662
 
 
663
#if GDK_MULTIHEAD_SAFE
 
664
    // Initialize the Display and Screen.
 
665
    _current_screen  = gdk_screen_get_default ();
 
666
#endif
 
667
 
 
668
    // Create input window
 
669
    {
 
670
        GtkWidget *vbox;
 
671
        GtkWidget *hbox;
 
672
        GtkWidget *frame;
 
673
 
 
674
        _input_window = gtk_window_new (GTK_WINDOW_POPUP);
 
675
        gtk_widget_modify_bg (_input_window, GTK_STATE_NORMAL, &_normal_bg);
 
676
        gtk_window_set_policy (GTK_WINDOW (_input_window), TRUE, TRUE, FALSE);
 
677
        gtk_window_set_resizable (GTK_WINDOW (_input_window), FALSE);
 
678
        gtk_widget_add_events (_input_window,GDK_BUTTON_PRESS_MASK);
 
679
        gtk_widget_add_events (_input_window,GDK_BUTTON_RELEASE_MASK);
 
680
        gtk_widget_add_events (_input_window,GDK_POINTER_MOTION_MASK);
 
681
        g_signal_connect (G_OBJECT (_input_window), "button-press-event",
 
682
                          G_CALLBACK (ui_input_window_click_cb),
 
683
                          GINT_TO_POINTER (0));
 
684
        g_signal_connect (G_OBJECT (_input_window), "button-release-event",
 
685
                          G_CALLBACK (ui_input_window_click_cb),
 
686
                          GINT_TO_POINTER (1));
 
687
 
 
688
        frame = gtk_frame_new (0);
 
689
        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
 
690
        gtk_container_add (GTK_CONTAINER (_input_window), frame);
 
691
 
 
692
        hbox = gtk_hbox_new (FALSE, 0);
 
693
        gtk_container_add (GTK_CONTAINER (frame), hbox);
 
694
 
 
695
        vbox = gtk_vbox_new (FALSE, 0);
 
696
        gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
 
697
        input_window_vbox = vbox;
 
698
 
 
699
        //Create preedit area
 
700
        _preedit_area = scim_string_view_new ();
 
701
        if (_default_font_desc)
 
702
            gtk_widget_modify_font (_preedit_area, _default_font_desc);
 
703
        gtk_widget_modify_base (_preedit_area, GTK_STATE_NORMAL, &_normal_bg);
 
704
        gtk_widget_modify_base (_preedit_area, GTK_STATE_ACTIVE, &_active_bg);
 
705
        gtk_widget_modify_text (_preedit_area, GTK_STATE_NORMAL, &_normal_text);
 
706
        gtk_widget_modify_text (_preedit_area, GTK_STATE_ACTIVE, &_active_text);
 
707
        scim_string_view_set_width_chars (SCIM_STRING_VIEW (_preedit_area), 24);
 
708
        scim_string_view_set_forward_event (SCIM_STRING_VIEW (_preedit_area), TRUE);
 
709
        scim_string_view_set_auto_resize (SCIM_STRING_VIEW (_preedit_area), TRUE);
 
710
        scim_string_view_set_has_frame (SCIM_STRING_VIEW (_preedit_area), FALSE);
 
711
        g_signal_connect (G_OBJECT (_preedit_area), "move_cursor",
 
712
                          G_CALLBACK (ui_preedit_area_move_cursor_cb),
 
713
                          0);
 
714
        gtk_box_pack_start (GTK_BOX (vbox), _preedit_area, TRUE, TRUE, 0);
 
715
 
 
716
        //Create aux area
 
717
        _aux_area = scim_string_view_new ();
 
718
        if (_default_font_desc)
 
719
            gtk_widget_modify_font (_aux_area, _default_font_desc);
 
720
        gtk_widget_modify_base (_aux_area, GTK_STATE_NORMAL, &_normal_bg);
 
721
        gtk_widget_modify_base (_aux_area, GTK_STATE_ACTIVE, &_active_bg);
 
722
        gtk_widget_modify_text (_aux_area, GTK_STATE_NORMAL, &_normal_text);
 
723
        gtk_widget_modify_text (_aux_area, GTK_STATE_ACTIVE, &_active_text);
 
724
        scim_string_view_set_width_chars (SCIM_STRING_VIEW (_aux_area), 24);
 
725
        scim_string_view_set_draw_cursor (SCIM_STRING_VIEW (_aux_area), FALSE);
 
726
        scim_string_view_set_forward_event (SCIM_STRING_VIEW (_aux_area), TRUE);
 
727
        scim_string_view_set_auto_resize (SCIM_STRING_VIEW (_aux_area), TRUE);
 
728
        scim_string_view_set_has_frame (SCIM_STRING_VIEW (_aux_area), FALSE);
 
729
        gtk_box_pack_start (GTK_BOX (vbox), _aux_area, TRUE, TRUE, 0);
 
730
 
 
731
        gtk_window_move (GTK_WINDOW (_input_window), ui_screen_width (), ui_screen_height ());
 
732
 
 
733
        gtk_widget_show_all (_input_window);
 
734
        gtk_widget_hide (_input_window);
 
735
    }
 
736
 
 
737
    //Create lookup table window
 
738
    {
 
739
        GtkWidget *vbox;
 
740
        GtkWidget *hbox;
 
741
        GtkWidget *frame;
 
742
        GtkWidget *lookup_table_parent;
 
743
        GtkWidget *image;
 
744
        GtkWidget *separator;
 
745
 
 
746
        if (_lookup_table_embedded) {
 
747
            _lookup_table_window = gtk_vbox_new (FALSE, 0);
 
748
            gtk_box_pack_start (GTK_BOX (input_window_vbox), _lookup_table_window, TRUE, TRUE, 0);
 
749
            lookup_table_parent = _lookup_table_window;
 
750
            separator = gtk_hseparator_new ();
 
751
            gtk_box_pack_start (GTK_BOX (lookup_table_parent), separator, FALSE, FALSE, 0);
 
752
        } else {
 
753
            _lookup_table_window = gtk_window_new (GTK_WINDOW_POPUP);
 
754
            gtk_widget_modify_bg (_lookup_table_window, GTK_STATE_NORMAL, &_normal_bg);
 
755
            gtk_window_set_policy (GTK_WINDOW (_lookup_table_window), TRUE, TRUE, FALSE);
 
756
            gtk_window_set_resizable (GTK_WINDOW (_lookup_table_window), FALSE);
 
757
            gtk_widget_add_events (_lookup_table_window,GDK_BUTTON_PRESS_MASK);
 
758
            gtk_widget_add_events (_lookup_table_window,GDK_BUTTON_RELEASE_MASK);
 
759
            gtk_widget_add_events (_lookup_table_window,GDK_POINTER_MOTION_MASK);
 
760
            g_signal_connect (G_OBJECT (_lookup_table_window), "button-press-event",
 
761
                              G_CALLBACK (ui_lookup_table_window_click_cb),
 
762
                              GINT_TO_POINTER (0));
 
763
            g_signal_connect (G_OBJECT (_lookup_table_window), "button-release-event",
 
764
                              G_CALLBACK (ui_lookup_table_window_click_cb),
 
765
                              GINT_TO_POINTER (1));
 
766
            gtk_container_set_border_width (GTK_CONTAINER (_lookup_table_window), 0);
 
767
 
 
768
            frame = gtk_frame_new (0);
 
769
            gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
 
770
            gtk_container_add (GTK_CONTAINER (_lookup_table_window), frame);
 
771
            lookup_table_parent = frame;
 
772
        }
 
773
 
 
774
        //Vertical lookup table
 
775
        if (_lookup_table_vertical) {
 
776
            vbox = gtk_vbox_new (FALSE, 0);
 
777
            gtk_container_add (GTK_CONTAINER (lookup_table_parent), vbox);
 
778
 
 
779
            //New table items
 
780
            for (int i=0; i<SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
 
781
                _lookup_table_items [i] = scim_string_view_new ();
 
782
                if (_default_font_desc)
 
783
                    gtk_widget_modify_font (_lookup_table_items [i], _default_font_desc);
 
784
                gtk_widget_modify_base (_lookup_table_items [i], GTK_STATE_NORMAL, &_normal_bg);
 
785
                gtk_widget_modify_base (_lookup_table_items [i], GTK_STATE_ACTIVE, &_active_bg);
 
786
                gtk_widget_modify_text (_lookup_table_items [i], GTK_STATE_NORMAL, &_normal_text);
 
787
                gtk_widget_modify_text (_lookup_table_items [i], GTK_STATE_ACTIVE, &_active_text);
 
788
                scim_string_view_set_width_chars (SCIM_STRING_VIEW (_lookup_table_items [i]), 80);
 
789
                scim_string_view_set_has_frame (SCIM_STRING_VIEW (_lookup_table_items [i]), FALSE);
 
790
                scim_string_view_set_forward_event (SCIM_STRING_VIEW (_lookup_table_items [i]), TRUE);
 
791
                scim_string_view_set_auto_resize (SCIM_STRING_VIEW (_lookup_table_items [i]), TRUE);
 
792
                scim_string_view_set_draw_cursor (SCIM_STRING_VIEW (_lookup_table_items [i]), FALSE);
 
793
                scim_string_view_set_auto_move_cursor (SCIM_STRING_VIEW (_lookup_table_items [i]), FALSE);
 
794
                g_signal_connect (G_OBJECT (_lookup_table_items [i]), "button-press-event",
 
795
                                  G_CALLBACK (ui_lookup_table_vertical_click_cb),
 
796
                                  GINT_TO_POINTER (i));
 
797
                gtk_box_pack_start (GTK_BOX (vbox), _lookup_table_items [i], TRUE, TRUE, 0);
 
798
            }
 
799
 
 
800
            separator = gtk_hseparator_new ();
 
801
            gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
 
802
 
 
803
            hbox = gtk_hbox_new (FALSE, 0);
 
804
            gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
 
805
 
 
806
            //New down button
 
807
            image = ui_create_down_icon ();
 
808
            _lookup_table_down_button = gtk_button_new ();
 
809
            gtk_container_add (GTK_CONTAINER (_lookup_table_down_button), image);
 
810
            gtk_box_pack_end (GTK_BOX (hbox), _lookup_table_down_button, FALSE, FALSE, 0);
 
811
            g_signal_connect (G_OBJECT (_lookup_table_down_button), "clicked",
 
812
                                G_CALLBACK (ui_lookup_table_down_button_click_cb),
 
813
                                image);
 
814
 
 
815
            //New up button
 
816
            image = ui_create_up_icon ();
 
817
            _lookup_table_up_button = gtk_button_new ();
 
818
            gtk_container_add (GTK_CONTAINER (_lookup_table_up_button), image);
 
819
            gtk_box_pack_end (GTK_BOX (hbox), _lookup_table_up_button, FALSE, FALSE, 0);
 
820
            g_signal_connect (G_OBJECT (_lookup_table_up_button), "clicked",
 
821
                                G_CALLBACK (ui_lookup_table_up_button_click_cb),
 
822
                                image);
 
823
 
 
824
        } else {
 
825
            hbox = gtk_hbox_new (FALSE, 0);
 
826
            gtk_container_add (GTK_CONTAINER (lookup_table_parent), hbox);
 
827
 
 
828
            _lookup_table_items [0] = scim_string_view_new ();
 
829
            if (_default_font_desc)
 
830
                gtk_widget_modify_font (_lookup_table_items [0], _default_font_desc);
 
831
            gtk_widget_modify_base (_lookup_table_items [0], GTK_STATE_NORMAL, &_normal_bg);
 
832
            gtk_widget_modify_base (_lookup_table_items [0], GTK_STATE_ACTIVE, &_active_bg);
 
833
            gtk_widget_modify_text (_lookup_table_items [0], GTK_STATE_NORMAL, &_normal_text);
 
834
            gtk_widget_modify_text (_lookup_table_items [0], GTK_STATE_ACTIVE, &_active_text);
 
835
            scim_string_view_set_forward_event (SCIM_STRING_VIEW (_lookup_table_items [0]), TRUE);
 
836
            scim_string_view_set_auto_resize (SCIM_STRING_VIEW (_lookup_table_items [0]), TRUE);
 
837
            scim_string_view_set_has_frame (SCIM_STRING_VIEW (_lookup_table_items [0]), FALSE);
 
838
            scim_string_view_set_draw_cursor (SCIM_STRING_VIEW (_lookup_table_items [0]), FALSE);
 
839
            scim_string_view_set_auto_move_cursor (SCIM_STRING_VIEW (_lookup_table_items [0]), FALSE);
 
840
            g_signal_connect (G_OBJECT (_lookup_table_items [0]), "move_cursor",
 
841
                            G_CALLBACK (ui_lookup_table_horizontal_click_cb),
 
842
                            0);
 
843
            gtk_box_pack_start (GTK_BOX (hbox), _lookup_table_items [0], TRUE, TRUE, 0);
 
844
 
 
845
            separator = gtk_vseparator_new ();
 
846
            gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, FALSE, 0);
 
847
 
 
848
            //New left button
 
849
            image = ui_create_left_icon ();
 
850
            _lookup_table_up_button = gtk_button_new ();
 
851
            gtk_container_add (GTK_CONTAINER (_lookup_table_up_button), image);
 
852
 
 
853
            gtk_box_pack_start (GTK_BOX (hbox), _lookup_table_up_button, FALSE, FALSE, 0);
 
854
            g_signal_connect (G_OBJECT (_lookup_table_up_button), "clicked",
 
855
                                G_CALLBACK (ui_lookup_table_up_button_click_cb),
 
856
                                image);
 
857
 
 
858
            //New right button
 
859
            image = ui_create_right_icon ();
 
860
            _lookup_table_down_button = gtk_button_new ();
 
861
            gtk_container_add (GTK_CONTAINER (_lookup_table_down_button), image);
 
862
 
 
863
            gtk_box_pack_start (GTK_BOX (hbox), _lookup_table_down_button, FALSE, FALSE, 0);
 
864
 
 
865
            g_signal_connect (G_OBJECT (_lookup_table_down_button), "clicked",
 
866
                                G_CALLBACK (ui_lookup_table_down_button_click_cb),
 
867
                                image);
 
868
        }
 
869
 
 
870
        gtk_button_set_relief (GTK_BUTTON (_lookup_table_up_button), GTK_RELIEF_NONE);
 
871
        gtk_widget_modify_bg (_lookup_table_up_button, GTK_STATE_ACTIVE, &_normal_bg);
 
872
        gtk_widget_modify_bg (_lookup_table_up_button, GTK_STATE_INSENSITIVE, &_normal_bg);
 
873
        gtk_widget_modify_bg (_lookup_table_up_button, GTK_STATE_PRELIGHT, &_normal_bg);
 
874
 
 
875
        gtk_button_set_relief (GTK_BUTTON (_lookup_table_down_button), GTK_RELIEF_NONE);
 
876
        gtk_widget_modify_bg (_lookup_table_down_button, GTK_STATE_ACTIVE, &_normal_bg);
 
877
        gtk_widget_modify_bg (_lookup_table_down_button, GTK_STATE_INSENSITIVE, &_normal_bg);
 
878
        gtk_widget_modify_bg (_lookup_table_down_button, GTK_STATE_PRELIGHT, &_normal_bg);
 
879
 
 
880
        if (!_lookup_table_embedded)
 
881
            gtk_window_move (GTK_WINDOW (_lookup_table_window), ui_screen_width (), ui_screen_height ());
 
882
 
 
883
        gtk_widget_show_all (_lookup_table_window);
 
884
        gtk_widget_hide (_lookup_table_window);
 
885
    }
 
886
 
 
887
    //Create toolbar window
 
888
    {
 
889
        GtkWidget *hbox;
 
890
        GtkWidget *frame;
 
891
        GtkWidget *image;
 
892
 
 
893
        _toolbar_window = gtk_window_new (GTK_WINDOW_POPUP);
 
894
        gtk_window_set_policy (GTK_WINDOW (_toolbar_window), TRUE, TRUE, FALSE);
 
895
        gtk_window_set_resizable (GTK_WINDOW (_toolbar_window), FALSE);
 
896
        gtk_widget_add_events (_toolbar_window,GDK_BUTTON_PRESS_MASK);
 
897
        gtk_widget_add_events (_toolbar_window,GDK_BUTTON_RELEASE_MASK);
 
898
        gtk_widget_add_events (_toolbar_window,GDK_POINTER_MOTION_MASK);
 
899
        g_signal_connect (G_OBJECT (_toolbar_window), "button-press-event",
 
900
                          G_CALLBACK (ui_toolbar_window_click_cb),
 
901
                          GINT_TO_POINTER (0));
 
902
        g_signal_connect (G_OBJECT (_toolbar_window), "button-release-event",
 
903
                          G_CALLBACK (ui_toolbar_window_click_cb),
 
904
                          GINT_TO_POINTER (1));
 
905
 
 
906
        frame = gtk_frame_new (0);
 
907
        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
 
908
        gtk_container_add (GTK_CONTAINER (_toolbar_window), frame);
 
909
 
 
910
        hbox = gtk_hbox_new (FALSE, 0);
 
911
        gtk_container_add (GTK_CONTAINER (frame), hbox);
 
912
 
 
913
        //New trademark pixmap
 
914
        image = ui_create_trademark_icon ();
 
915
        gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
 
916
 
 
917
        //New stick button
 
918
        if (_toolbar_show_stick_icon) {
 
919
            image = ui_create_stick_icon (_window_sticked);
 
920
            _window_stick_button = gtk_button_new ();
 
921
            gtk_button_set_relief (GTK_BUTTON (_window_stick_button), GTK_RELIEF_NONE);
 
922
            gtk_container_add (GTK_CONTAINER (_window_stick_button), image);
 
923
            gtk_box_pack_start (GTK_BOX (hbox), _window_stick_button, TRUE, TRUE, 0);
 
924
            g_signal_connect (G_OBJECT (_window_stick_button), "clicked",
 
925
                              G_CALLBACK (ui_window_stick_button_click_cb),
 
926
                              0);
 
927
        }
 
928
 
 
929
        //New factory button
 
930
        if (_toolbar_show_factory_icon || _toolbar_show_factory_name) {
 
931
            _factory_button = gtk_button_new ();
 
932
            gtk_button_set_relief (GTK_BUTTON (_factory_button), GTK_RELIEF_NONE);
 
933
            gtk_box_pack_start (GTK_BOX (hbox), _factory_button, TRUE, TRUE, 0);
 
934
            g_signal_connect (G_OBJECT (_factory_button), "button-release-event",
 
935
                              G_CALLBACK (ui_factory_button_click_cb),
 
936
                              0);
 
937
        }
 
938
 
 
939
        // Put all properties here
 
940
        _client_properties_area = gtk_hbox_new (FALSE, 0);
 
941
        gtk_box_pack_start (GTK_BOX (hbox), _client_properties_area, TRUE, TRUE, 0);
 
942
        gtk_widget_show (_client_properties_area);
 
943
 
 
944
        //New menu button
 
945
        if (_toolbar_show_menu_icon) {
 
946
            image = ui_create_menu_icon ();
 
947
            _menu_button = gtk_button_new ();
 
948
            gtk_button_set_relief (GTK_BUTTON (_menu_button), GTK_RELIEF_NONE);
 
949
            gtk_container_add (GTK_CONTAINER (_menu_button), image);
 
950
            gtk_box_pack_start (GTK_BOX (hbox), _menu_button, TRUE, TRUE, 0);
 
951
            g_signal_connect (G_OBJECT (_menu_button), "clicked",
 
952
                              G_CALLBACK (ui_menu_button_click_cb),
 
953
                              image);
 
954
        }
 
955
 
 
956
        //New help button
 
957
        if (_toolbar_show_help_icon) {
 
958
            image = ui_create_help_icon ();
 
959
            _help_button = gtk_button_new ();
 
960
            gtk_button_set_relief (GTK_BUTTON (_help_button), GTK_RELIEF_NONE);
 
961
            gtk_container_add (GTK_CONTAINER (_help_button), image);
 
962
            gtk_box_pack_start (GTK_BOX (hbox), _help_button, TRUE, TRUE, 0);
 
963
            g_signal_connect (G_OBJECT (_help_button), "clicked",
 
964
                              G_CALLBACK (ui_help_button_click_cb),
 
965
                              image);
 
966
        }
 
967
 
 
968
        gtk_window_move (GTK_WINDOW (_toolbar_window), ui_screen_width (), ui_screen_height ());
 
969
 
 
970
        gtk_widget_show_all (_toolbar_window);
 
971
        gtk_widget_hide (_toolbar_window);
 
972
 
 
973
        ui_settle_toolbar_window ();
 
974
    }
 
975
 
 
976
    // Create help window
 
977
    {
 
978
        GtkWidget *frame;
 
979
        GtkWidget *vbox;
 
980
 
 
981
        _help_dialog = gtk_dialog_new_with_buttons (_("SCIM Help"),
 
982
                                NULL,
 
983
                                GtkDialogFlags (0),
 
984
                                GTK_STOCK_OK,
 
985
                                GTK_RESPONSE_OK,
 
986
                                NULL);
 
987
 
 
988
        g_signal_connect_swapped (GTK_OBJECT (_help_dialog), 
 
989
                                  "response", 
 
990
                                  G_CALLBACK (gtk_widget_hide),
 
991
                                  GTK_OBJECT (_help_dialog));
 
992
 
 
993
        g_signal_connect_swapped (GTK_OBJECT (_help_dialog), 
 
994
                                  "delete_event", 
 
995
                                  G_CALLBACK (gtk_widget_hide_on_delete),
 
996
                                  GTK_OBJECT (_help_dialog));
 
997
 
 
998
        frame = gtk_frame_new (_("Smart Common Input Method"));
 
999
 
 
1000
        gtk_box_pack_start (GTK_BOX (GTK_DIALOG (_help_dialog)->vbox), frame, TRUE, TRUE, 0);
 
1001
        gtk_widget_show (frame);
 
1002
 
 
1003
        vbox = gtk_vbox_new (FALSE, 8);
 
1004
        gtk_container_add (GTK_CONTAINER (frame), vbox);
 
1005
        gtk_widget_show (vbox);
 
1006
 
 
1007
        _help_scroll = gtk_scrolled_window_new (NULL, NULL);
 
1008
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (_help_scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
 
1009
        gtk_box_pack_start (GTK_BOX (vbox), _help_scroll, TRUE, TRUE, 0);
 
1010
        gtk_widget_show (_help_scroll);
 
1011
 
 
1012
        _help_area = gtk_label_new ("");
 
1013
        gtk_label_set_justify (GTK_LABEL (_help_area), GTK_JUSTIFY_LEFT);
 
1014
        gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (_help_scroll), _help_area);
 
1015
        gtk_widget_show (_help_area);
 
1016
    }
 
1017
 
 
1018
#if ENABLE_TRAY_ICON
 
1019
    // Create Tray Icon
 
1020
    {
 
1021
        if (_show_tray_icon)
 
1022
            ui_create_tray_icon_when_idle (0);
 
1023
    }
 
1024
#endif
 
1025
 
 
1026
    //Settle input/lookup windows to default position
 
1027
    {
 
1028
        uint32 spot_x, spot_y;
 
1029
 
 
1030
        spot_x = ui_screen_width () / 2 - 64;
 
1031
        spot_y = ui_screen_height () * 3 / 4;
 
1032
        gtk_window_move (GTK_WINDOW (_input_window), spot_x, spot_y);
 
1033
 
 
1034
        if (!_lookup_table_embedded)
 
1035
            gtk_window_move (GTK_WINDOW (_lookup_table_window), spot_x, spot_y + 32);
 
1036
    }
 
1037
 
 
1038
    //Init timeout callback
 
1039
    if (_toolbar_always_show && _toolbar_hide_timeout_max > 0) {
 
1040
        _toolbar_hide_timeout = gtk_timeout_add (1000, ui_hide_window_timeout_cb, NULL);
 
1041
        g_signal_connect (G_OBJECT (_toolbar_window), "enter-notify-event",
 
1042
                          G_CALLBACK (ui_toolbar_window_crossing_cb),
 
1043
                          GINT_TO_POINTER (0));
 
1044
        g_signal_connect (G_OBJECT (_toolbar_window), "leave-notify-event",
 
1045
                          G_CALLBACK (ui_toolbar_window_crossing_cb),
 
1046
                          GINT_TO_POINTER (1));
 
1047
    }
 
1048
 
 
1049
    // Init the tooltips
 
1050
    {
 
1051
        _tooltips = gtk_tooltips_new ();
 
1052
 
 
1053
        gtk_tooltips_set_delay (_tooltips, 1000);
 
1054
 
 
1055
        if (_window_stick_button)
 
1056
            gtk_tooltips_set_tip (_tooltips, _window_stick_button,
 
1057
                                  _("Stick/unstick the input window and the toolbar."),
 
1058
                                  NULL);
 
1059
 
 
1060
        if (_help_button)
 
1061
            gtk_tooltips_set_tip (_tooltips, _help_button,
 
1062
                                  _("Show a brief help about SCIM and the current input method."),
 
1063
                                  NULL);
 
1064
 
 
1065
        if (_menu_button)
 
1066
            gtk_tooltips_set_tip (_tooltips, _menu_button,
 
1067
                                  _("Show command menu."),
 
1068
                                  NULL);
 
1069
    }
 
1070
 
 
1071
#ifdef GDK_WINDOWING_X11
 
1072
    // Add an event filter function to observe X root window's properties.
 
1073
    GdkWindow *root_window = gdk_get_default_root_window ();
 
1074
#if GDK_MULTIHEAD_SAFE
 
1075
    if (_current_screen)
 
1076
        root_window = gdk_screen_get_root_window (_current_screen);
 
1077
#endif
 
1078
    gdk_window_set_events (root_window, (GdkEventMask)GDK_PROPERTY_NOTIFY);
 
1079
    gdk_window_add_filter (root_window, ui_event_filter, NULL);
 
1080
#endif
 
1081
 
 
1082
    _ui_initialized = true;
 
1083
}
 
1084
 
 
1085
static void
 
1086
ui_settle_input_window (bool relative, bool force)
 
1087
{
 
1088
    SCIM_DEBUG_MAIN (2) << " Settle input window...\n";
 
1089
 
 
1090
    if (_window_sticked) {
 
1091
        if (force)
 
1092
            gtk_window_move (GTK_WINDOW (_input_window), _input_window_x, _input_window_y);
 
1093
        return;
 
1094
    }
 
1095
 
 
1096
    GtkRequisition ws;
 
1097
    gint spot_x, spot_y;
 
1098
 
 
1099
    gtk_widget_size_request (_input_window, &ws);
 
1100
 
 
1101
    if (!relative) {
 
1102
        spot_x = _spot_location_x; 
 
1103
        spot_y = _spot_location_y; 
 
1104
    } else {
 
1105
        spot_x = _input_window_x; 
 
1106
        spot_y = _input_window_y;
 
1107
    }
 
1108
 
 
1109
    if (spot_x < 0) spot_x = 0;
 
1110
    if (spot_y < 0) spot_y = 0;
 
1111
 
 
1112
    if (spot_x + ws.width > ui_screen_width () - 4)
 
1113
        spot_x = ui_screen_width () - ws.width - 4;
 
1114
    if (spot_y + ws.height + 8 > ui_screen_height () - 4)
 
1115
        spot_y = ui_screen_height () - ws.height - 4;
 
1116
 
 
1117
    if (spot_x != _input_window_x || spot_y != _input_window_y || force) {
 
1118
        gtk_window_move (GTK_WINDOW (_input_window), spot_x, spot_y);
 
1119
        _input_window_x = spot_x;
 
1120
        _input_window_y = spot_y;
 
1121
    }
 
1122
}
 
1123
 
 
1124
static void
 
1125
ui_settle_lookup_table_window(bool force)
 
1126
{
 
1127
    SCIM_DEBUG_MAIN (2) << " Settle lookup table window...\n";
 
1128
 
 
1129
    if (_lookup_table_embedded)
 
1130
        return;
 
1131
 
 
1132
    if (_window_sticked) {
 
1133
        if (force)
 
1134
            gtk_window_move (GTK_WINDOW (_lookup_table_window), _lookup_table_window_x, _lookup_table_window_y);
 
1135
        return;
 
1136
    }
 
1137
 
 
1138
    gint pos_x, pos_y;
 
1139
 
 
1140
    GtkRequisition iws;
 
1141
    GtkRequisition ws;
 
1142
 
 
1143
    gtk_widget_size_request (_input_window, &iws);
 
1144
    gtk_widget_size_request (_lookup_table_window, &ws);
 
1145
 
 
1146
    pos_x = _input_window_x;
 
1147
    pos_y = _input_window_y + iws.height + 8;
 
1148
 
 
1149
    if (pos_x + ws.width > ui_screen_width () - 8) {
 
1150
        pos_x = ui_screen_width () - ws.width - 8;
 
1151
    }
 
1152
 
 
1153
    if (pos_y + ws.height > ui_screen_height () - 8) {
 
1154
        pos_y = ui_screen_height () - ws.height - 40;
 
1155
    }
 
1156
 
 
1157
    // input window and lookup table window are overlapped.
 
1158
    if (pos_y < _input_window_y + iws.height && pos_y + ws.height > _input_window_y) {
 
1159
        pos_y = _input_window_y - ws.height - 8;
 
1160
    }
 
1161
 
 
1162
    if (_lookup_table_window_x != pos_x || _lookup_table_window_y != pos_y || force) {
 
1163
        gtk_window_move (GTK_WINDOW (_lookup_table_window), pos_x, pos_y);
 
1164
        _lookup_table_window_x = pos_x;
 
1165
        _lookup_table_window_y = pos_y;
 
1166
    }
 
1167
}
 
1168
 
 
1169
static void
 
1170
ui_settle_toolbar_window (bool force)
 
1171
{
 
1172
    SCIM_DEBUG_MAIN (2) << " Settle toolbar window...\n";
 
1173
 
 
1174
    if (_window_sticked) {
 
1175
        if (force)
 
1176
            gtk_window_move (GTK_WINDOW (_toolbar_window), _toolbar_window_x, _toolbar_window_y);
 
1177
        return;
 
1178
    }
 
1179
 
 
1180
    gint workarea_x, workarea_y, workarea_width, workarea_height;
 
1181
    ui_get_workarea (workarea_x, workarea_y, workarea_width, workarea_height);
 
1182
 
 
1183
    GtkRequisition ws;
 
1184
    gint pos_x, pos_y;
 
1185
 
 
1186
    gtk_widget_size_request (_toolbar_window, &ws);
 
1187
 
 
1188
    pos_x = _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_POS_X),
 
1189
                           workarea_x + workarea_width - ws.width);
 
1190
    pos_y = _config->read (String (SCIM_CONFIG_PANEL_GTK_TOOLBAR_POS_Y),
 
1191
                           workarea_y + workarea_height - ws.height);
 
1192
    if (pos_x == -1 && pos_y == -1) {
 
1193
        pos_x = workarea_x + workarea_width  - ws.width;
 
1194
        pos_y = workarea_y + workarea_height - ws.height;
 
1195
    }
 
1196
 
 
1197
    if (_toolbar_auto_snap) {
 
1198
        if ((ui_screen_width () - (pos_x + ws.width)) < pos_x)
 
1199
            pos_x = ui_screen_width () - ws.width;
 
1200
        else
 
1201
            pos_x = 0;
 
1202
    } else if (pos_x + ws.width > ui_screen_width ()) {
 
1203
        pos_x = ui_screen_width () - ws.width;
 
1204
    } else if (pos_x < 0) {
 
1205
        pos_x = 0;
 
1206
    }
 
1207
 
 
1208
    if (pos_y + ws.height > ui_screen_height ())
 
1209
        pos_y = ui_screen_height () - ws.height;
 
1210
    else if (pos_y < 0)
 
1211
        pos_y = 0;
 
1212
 
 
1213
    if (_toolbar_window_x != pos_x || _toolbar_window_y != pos_y || force) {
 
1214
        gtk_window_move (GTK_WINDOW (_toolbar_window), pos_x, pos_y);
 
1215
        _toolbar_window_x = pos_x;
 
1216
        _toolbar_window_y = pos_y;
 
1217
    }
 
1218
}
 
1219
 
 
1220
static int
 
1221
ui_screen_width (void)
 
1222
{
 
1223
#if GDK_MULTIHEAD_SAFE
 
1224
    if (_current_screen)
 
1225
        return gdk_screen_get_width (_current_screen);
 
1226
#endif
 
1227
    return gdk_screen_width ();
 
1228
}
 
1229
 
 
1230
static int
 
1231
ui_screen_height (void)
 
1232
{
 
1233
#if GDK_MULTIHEAD_SAFE
 
1234
    if (_current_screen)
 
1235
        return gdk_screen_get_height (_current_screen);
 
1236
#endif
 
1237
    return gdk_screen_height ();
 
1238
}
 
1239
 
 
1240
static void
 
1241
ui_get_workarea (int &x, int &y, int &width, int &height)
 
1242
{
 
1243
    static GdkAtom net_current_desktop_atom = gdk_atom_intern ("_NET_CURRENT_DESKTOP", TRUE);;
 
1244
    static GdkAtom net_workarea_atom = gdk_atom_intern ("_NET_WORKAREA", TRUE);
 
1245
    GdkWindow *root_window = gdk_get_default_root_window ();
 
1246
    GdkAtom atom_ret;
 
1247
    gint format, length, current_desktop = 0;
 
1248
    guchar *data;
 
1249
 
 
1250
#if GDK_MULTIHEAD_SAFE
 
1251
    if (_current_screen)
 
1252
        root_window = gdk_screen_get_root_window (_current_screen);
 
1253
#endif
 
1254
 
 
1255
    x = 0;
 
1256
    y = 0;
 
1257
    width = ui_screen_width ();
 
1258
    height = ui_screen_height ();
 
1259
 
 
1260
    if (net_current_desktop_atom != GDK_NONE) {
 
1261
        gboolean found = gdk_property_get (root_window,
 
1262
                                           net_current_desktop_atom, GDK_NONE, 0, G_MAXLONG, FALSE,
 
1263
                                           &atom_ret, &format, &length, &data);
 
1264
        if (found && format == 32 && length / sizeof(glong) > 0)
 
1265
            current_desktop = ((glong*)data)[0];
 
1266
        if (found)
 
1267
            g_free (data);
 
1268
    }
 
1269
 
 
1270
    if (net_workarea_atom != GDK_NONE) {
 
1271
        gboolean found = gdk_property_get (root_window,
 
1272
                                           net_workarea_atom, GDK_NONE, 0, G_MAXLONG, FALSE,
 
1273
                                           &atom_ret, &format, &length, &data);
 
1274
        if (found && format == 32 && length / sizeof(glong) >= (current_desktop + 1) * 4) {
 
1275
            x      = ((glong*)data)[current_desktop * 4];
 
1276
            y      = ((glong*)data)[current_desktop * 4 + 1];
 
1277
            width  = ((glong*)data)[current_desktop * 4 + 2];
 
1278
            height = ((glong*)data)[current_desktop * 4 + 3];
 
1279
        }
 
1280
        if (found)
 
1281
            g_free (data);
 
1282
    }
 
1283
}
 
1284
 
 
1285
#if GDK_MULTIHEAD_SAFE
 
1286
static void
 
1287
ui_switch_screen (GdkScreen *screen)
 
1288
{
 
1289
    if (screen) {
 
1290
        if (_input_window) {
 
1291
            gtk_window_set_screen (GTK_WINDOW (_input_window), screen);
 
1292
 
 
1293
            _input_window_x = ui_screen_width ();
 
1294
            _input_window_y = ui_screen_height ();
 
1295
 
 
1296
            gtk_window_move (GTK_WINDOW (_input_window), _input_window_x, _input_window_y);
 
1297
        }
 
1298
 
 
1299
        if (_toolbar_window) {
 
1300
            gtk_window_set_screen (GTK_WINDOW (_toolbar_window), screen);
 
1301
            ui_settle_toolbar_window ();
 
1302
        }
 
1303
 
 
1304
        if (!_lookup_table_embedded && _lookup_table_window) {
 
1305
            gtk_window_set_screen (GTK_WINDOW (_lookup_table_window), screen);
 
1306
 
 
1307
            _lookup_table_window_x = ui_screen_width ();
 
1308
            _lookup_table_window_y = ui_screen_height ();
 
1309
 
 
1310
            gtk_window_move (GTK_WINDOW (_lookup_table_window), _lookup_table_window_x, _lookup_table_window_y);
 
1311
        }
 
1312
 
 
1313
#if ENABLE_TRAY_ICON
 
1314
        if (_tray_icon) {
 
1315
            gtk_window_set_screen (GTK_WINDOW (_tray_icon), screen);
 
1316
        }
 
1317
#endif
 
1318
 
 
1319
        if (_help_dialog) {
 
1320
            gtk_window_set_screen (GTK_WINDOW (_help_dialog), screen);
 
1321
        }
 
1322
 
 
1323
#ifdef GDK_WINDOWING_X11
 
1324
        GdkWindow *root_window = gdk_get_default_root_window ();
 
1325
        if (_current_screen)
 
1326
            root_window = gdk_screen_get_root_window (_current_screen);
 
1327
        gdk_window_set_events (root_window, (GdkEventMask)GDK_PROPERTY_NOTIFY);
 
1328
        gdk_window_add_filter (root_window, ui_event_filter, NULL);
 
1329
#endif
 
1330
 
 
1331
        ui_settle_input_window ();
 
1332
        ui_settle_lookup_table_window ();
 
1333
        ui_settle_toolbar_window ();
 
1334
    }
 
1335
}
 
1336
#endif
 
1337
 
 
1338
#if ENABLE_TRAY_ICON
 
1339
static gboolean
 
1340
ui_tray_icon_expose_event_cb (GtkWidget *widget, GdkEventExpose *event)
 
1341
{
 
1342
    gdk_window_clear_area (widget->window, event->area.x, event->area.y,
 
1343
                           event->area.width, event->area.height);
 
1344
    return FALSE;
 
1345
}
 
1346
 
 
1347
static void
 
1348
ui_tray_icon_style_set_cb (GtkWidget *widget, GtkStyle *previous_style)
 
1349
{
 
1350
    gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
 
1351
}
 
1352
 
 
1353
static void
 
1354
ui_tray_icon_realize_cb (GtkWidget *widget)
 
1355
{
 
1356
    if (GTK_WIDGET_NO_WINDOW (widget) || GTK_WIDGET_APP_PAINTABLE (widget))
 
1357
        return;
 
1358
 
 
1359
    gtk_widget_set_app_paintable (widget, TRUE);
 
1360
    gtk_widget_set_double_buffered (widget, FALSE);
 
1361
    gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
 
1362
    g_signal_connect (widget, "expose_event",
 
1363
                      G_CALLBACK (ui_tray_icon_expose_event_cb), NULL);
 
1364
    g_signal_connect_after (widget, "style_set",
 
1365
                            G_CALLBACK (ui_tray_icon_style_set_cb), NULL);
 
1366
}
 
1367
 
 
1368
static gboolean
 
1369
ui_create_tray_icon_when_idle (gpointer data)
 
1370
{
 
1371
    GtkWidget *image;
 
1372
 
 
1373
    _tray_icon = scim_tray_icon_new ("SCIM Tray Icon");
 
1374
    g_signal_connect (G_OBJECT (_tray_icon), "realize",
 
1375
                      G_CALLBACK (ui_tray_icon_realize_cb), NULL);
 
1376
 
 
1377
    _tray_icon_destroy_signal_id = 
 
1378
    g_signal_connect (G_OBJECT (_tray_icon), "destroy",
 
1379
                      G_CALLBACK (ui_tray_icon_destroy_cb),
 
1380
                      0);
 
1381
 
 
1382
    image = ui_create_icon (SCIM_KEYBOARD_ICON_FILE,
 
1383
                            NULL,
 
1384
                            TRAY_ICON_SIZE,
 
1385
                            TRAY_ICON_SIZE,
 
1386
                            true);
 
1387
 
 
1388
    _tray_icon_factory_button = gtk_event_box_new ();
 
1389
    g_signal_connect (G_OBJECT (_tray_icon_factory_button), "realize",
 
1390
                      G_CALLBACK (ui_tray_icon_realize_cb), NULL);
 
1391
    gtk_container_add (GTK_CONTAINER (_tray_icon_factory_button), image);
 
1392
    gtk_container_add (GTK_CONTAINER (_tray_icon), _tray_icon_factory_button);
 
1393
    g_signal_connect (G_OBJECT (_tray_icon_factory_button), "button-release-event",
 
1394
                      G_CALLBACK (ui_factory_button_click_cb),
 
1395
                      0);
 
1396
 
 
1397
    gtk_widget_show_all (GTK_WIDGET (_tray_icon));
 
1398
 
 
1399
    return FALSE;
 
1400
}
 
1401
#endif
 
1402
 
 
1403
static GdkPixbuf *
 
1404
ui_scale_pixbuf (GdkPixbuf *pixbuf,
 
1405
                 int        width,
 
1406
                 int        height)
 
1407
{
 
1408
    if (pixbuf) {
 
1409
        if (gdk_pixbuf_get_width (pixbuf) != width ||
 
1410
            gdk_pixbuf_get_height (pixbuf) != height) {
 
1411
            GdkPixbuf *dest = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR);
 
1412
            g_object_unref (pixbuf);
 
1413
            pixbuf = dest;
 
1414
        }
 
1415
    }
 
1416
    return pixbuf;
 
1417
}
 
1418
 
 
1419
static GtkWidget *
 
1420
ui_create_label (const String   &name,
 
1421
                 const String   &iconfile,
 
1422
                 const char    **xpm,
 
1423
                 bool            show_icon_only,
 
1424
                 bool            force_icon)
 
1425
{
 
1426
    GtkWidget * hbox = gtk_hbox_new (FALSE, 0);
 
1427
    GtkWidget * label = gtk_label_new (name.c_str ());
 
1428
 
 
1429
    gint width, height;
 
1430
 
 
1431
    if (_default_font_desc)
 
1432
        gtk_widget_modify_font (label, _default_font_desc);
 
1433
 
 
1434
    gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
 
1435
 
 
1436
    GtkWidget *icon = ui_create_icon (iconfile,
 
1437
                                      xpm,
 
1438
                                      width,
 
1439
                                      height,
 
1440
                                      force_icon);
 
1441
 
 
1442
    if (icon) {
 
1443
        gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
 
1444
        if (!show_icon_only)
 
1445
            gtk_box_set_spacing (GTK_BOX (hbox), 4);
 
1446
    }
 
1447
 
 
1448
    if (!show_icon_only || !icon)
 
1449
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
1450
    else
 
1451
        gtk_widget_destroy (label);
 
1452
 
 
1453
    gtk_widget_show_all (hbox);
 
1454
 
 
1455
    return hbox;
 
1456
}
 
1457
 
 
1458
static GtkWidget *
 
1459
ui_create_icon (const String  &iconfile,
 
1460
                const char   **xpm,
 
1461
                int            width,
 
1462
                int            height,
 
1463
                bool           force_create)
 
1464
{
 
1465
    String path = iconfile;
 
1466
    GdkPixbuf *pixbuf = 0;
 
1467
 
 
1468
    if (path.length ()) {
 
1469
        // Not a absolute path, prepend SCIM_ICONDIR
 
1470
        if (path [0] != SCIM_PATH_DELIM)
 
1471
            path = String (SCIM_ICONDIR) + String (SCIM_PATH_DELIM_STRING) + path;
 
1472
 
 
1473
        pixbuf = gdk_pixbuf_new_from_file (path.c_str (), 0);
 
1474
    }
 
1475
 
 
1476
    if (!pixbuf && xpm) {
 
1477
        pixbuf = gdk_pixbuf_new_from_xpm_data (xpm);
 
1478
    }
 
1479
 
 
1480
    if (!pixbuf && force_create) {
 
1481
        if (width <= 0 || height <= 0)
 
1482
            return 0;
 
1483
 
 
1484
        pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, true, 8, width, height);
 
1485
 
 
1486
        if (!pixbuf)
 
1487
            return 0;
 
1488
 
 
1489
        gdk_pixbuf_fill (pixbuf, 0);
 
1490
    }
 
1491
 
 
1492
    if (pixbuf) {
 
1493
        if (width <= 0) width = gdk_pixbuf_get_width (pixbuf);
 
1494
        if (height <= 0) height = gdk_pixbuf_get_height (pixbuf);
 
1495
 
 
1496
        pixbuf = ui_scale_pixbuf (pixbuf, width, height);
 
1497
 
 
1498
        GtkWidget *icon = gtk_image_new_from_pixbuf (pixbuf);
 
1499
        gtk_widget_show (icon);
 
1500
 
 
1501
        gdk_pixbuf_unref (pixbuf);
 
1502
 
 
1503
        return icon;
 
1504
    }
 
1505
    return 0;
 
1506
}
 
1507
 
 
1508
static GtkWidget *
 
1509
ui_create_trademark_icon (void)
 
1510
{
 
1511
    return ui_create_icon (SCIM_TRADEMARK_ICON_FILE,
 
1512
                           (const char **) trademark_xpm,
 
1513
                           TOOLBAR_ICON_SIZE + 4,
 
1514
                           TOOLBAR_ICON_SIZE + 4);
 
1515
}
 
1516
 
 
1517
static GtkWidget *
 
1518
ui_create_stick_icon (bool sticked)
 
1519
{
 
1520
    return ui_create_icon ((sticked ? SCIM_PIN_DOWN_ICON_FILE : SCIM_PIN_UP_ICON_FILE),
 
1521
                           (const char **) (sticked ? pin_down_xpm : pin_up_xpm),
 
1522
                           TOOLBAR_ICON_SIZE,
 
1523
                           TOOLBAR_ICON_SIZE);
 
1524
}
 
1525
 
 
1526
static GtkWidget *
 
1527
ui_create_help_icon (void)
 
1528
{
 
1529
    return ui_create_icon (SCIM_HELP_ICON_FILE,
 
1530
                           (const char **) help_xpm,
 
1531
                           TOOLBAR_ICON_SIZE,
 
1532
                           TOOLBAR_ICON_SIZE);
 
1533
}
 
1534
 
 
1535
static GtkWidget *
 
1536
ui_create_menu_icon (void)
 
1537
{
 
1538
    return ui_create_icon (SCIM_MENU_ICON_FILE,
 
1539
                           (const char **) menu_xpm,
 
1540
                           TOOLBAR_ICON_SIZE,
 
1541
                           TOOLBAR_ICON_SIZE);
 
1542
}
 
1543
 
 
1544
static GtkWidget *
 
1545
ui_create_up_icon (void)
 
1546
{
 
1547
    return ui_create_icon (SCIM_UP_ICON_FILE,
 
1548
                           (const char **) up_xpm,
 
1549
                           LOOKUP_ICON_SIZE,
 
1550
                           LOOKUP_ICON_SIZE);
 
1551
}
 
1552
 
 
1553
static GtkWidget *
 
1554
ui_create_left_icon (void)
 
1555
{
 
1556
    return ui_create_icon (SCIM_LEFT_ICON_FILE,
 
1557
                           (const char **) left_xpm,
 
1558
                           LOOKUP_ICON_SIZE,
 
1559
                           LOOKUP_ICON_SIZE);
 
1560
}
 
1561
 
 
1562
static GtkWidget *
 
1563
ui_create_right_icon (void)
 
1564
{
 
1565
    return ui_create_icon (SCIM_RIGHT_ICON_FILE,
 
1566
                           (const char **) right_xpm,
 
1567
                           LOOKUP_ICON_SIZE,
 
1568
                           LOOKUP_ICON_SIZE);
 
1569
}
 
1570
 
 
1571
static GtkWidget *
 
1572
ui_create_down_icon (void)
 
1573
{
 
1574
    return ui_create_icon (SCIM_DOWN_ICON_FILE,
 
1575
                           (const char **) down_xpm,
 
1576
                           LOOKUP_ICON_SIZE,
 
1577
                           LOOKUP_ICON_SIZE);
 
1578
}
 
1579
 
 
1580
static GtkWidget*
 
1581
ui_create_factory_menu_entry (const PanelFactoryInfo &info,
 
1582
                              gint                   id,
 
1583
                              GtkMenuShell           *menu,
 
1584
                              bool                   show_lang,
 
1585
                              bool                   show_name)
 
1586
{
 
1587
    gint width, height;
 
1588
    GtkWidget *menu_item;
 
1589
    GtkWidget *icon_image;
 
1590
    String text, tooltip;
 
1591
 
 
1592
    if ((!show_lang && show_name) || (show_lang && !show_name && (info.lang == "C" || info.lang == "~other"))) {
 
1593
        text = info.name;
 
1594
        tooltip = "";
 
1595
    } else if (show_lang && !show_name) {
 
1596
        text = scim_get_language_name (info.lang);
 
1597
        tooltip = info.name;
 
1598
    } else {
 
1599
        text = scim_get_language_name (info.lang) + " - " + info.name;
 
1600
        tooltip = "";
 
1601
    }
 
1602
 
 
1603
    menu_item = gtk_image_menu_item_new_with_label (text.c_str ());
 
1604
    gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
 
1605
    icon_image = ui_create_icon (info.icon, NULL, width, height, false);
 
1606
    if (icon_image)
 
1607
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), icon_image);
 
1608
 
 
1609
    g_signal_connect (G_OBJECT (menu_item), "activate",
 
1610
                      G_CALLBACK (ui_factory_menu_activate_cb),
 
1611
                      GINT_TO_POINTER ((gint)id));
 
1612
    gtk_widget_show (menu_item);
 
1613
 
 
1614
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
 
1615
 
 
1616
    if (tooltip != "")
 
1617
        gtk_tooltips_set_tip (_tooltips, menu_item, tooltip.c_str (), NULL);
 
1618
 
 
1619
    return menu_item;
 
1620
}
 
1621
 
 
1622
/* Implementation of callback functions */
 
1623
static void
 
1624
ui_preedit_area_move_cursor_cb (ScimStringView *view,
 
1625
                                guint           position)
 
1626
{
 
1627
    SCIM_DEBUG_MAIN (3) << "  ui_preedit_area_move_cursor_cb...\n";
 
1628
 
 
1629
    _panel_agent->move_preedit_caret (position);
 
1630
}
 
1631
 
 
1632
static void
 
1633
ui_help_button_click_cb (GtkButton *button,
 
1634
                         gpointer   user_data)
 
1635
{
 
1636
    SCIM_DEBUG_MAIN (3) << "  ui_help_button_click_cb...\n";
 
1637
 
 
1638
    if (GTK_WIDGET_VISIBLE (_help_dialog)) {
 
1639
        gtk_widget_hide (_help_dialog);
 
1640
    } else {
 
1641
        action_request_help ();
 
1642
    }
 
1643
}
 
1644
 
 
1645
static void
 
1646
ui_menu_button_click_cb (GtkButton *button,
 
1647
                         gpointer   user_data)
 
1648
{
 
1649
    SCIM_DEBUG_MAIN (3) << "  ui_menu_button_click_cb...\n";
 
1650
 
 
1651
    struct timeval cur_time;
 
1652
    gettimeofday (&cur_time, 0);
 
1653
 
 
1654
    if (cur_time.tv_sec < _last_menu_deactivate_time.tv_sec ||
 
1655
        (cur_time.tv_sec == _last_menu_deactivate_time.tv_sec &&
 
1656
         cur_time.tv_usec < _last_menu_deactivate_time.tv_usec + 200000))
 
1657
        return;
 
1658
 
 
1659
    action_show_command_menu ();
 
1660
}
 
1661
 
 
1662
static gboolean
 
1663
ui_factory_button_click_cb (GtkWidget *button,
 
1664
                            GdkEvent  *event,
 
1665
                            gpointer   user_data)
 
1666
{
 
1667
    SCIM_DEBUG_MAIN (3) << "  ui_factory_button_click_cb...\n";
 
1668
 
 
1669
    GdkEventButton *bevent = (GdkEventButton *) event;
 
1670
 
 
1671
    struct timeval cur_time;
 
1672
    gettimeofday (&cur_time, 0);
 
1673
 
 
1674
    if (cur_time.tv_sec < _last_menu_deactivate_time.tv_sec ||
 
1675
        (cur_time.tv_sec == _last_menu_deactivate_time.tv_sec &&
 
1676
         cur_time.tv_usec < _last_menu_deactivate_time.tv_usec + 200000))
 
1677
        return FALSE;
 
1678
 
 
1679
    if (bevent->button <= 1)
 
1680
        _panel_agent->request_factory_menu ();
 
1681
    else
 
1682
        action_show_command_menu ();
 
1683
 
 
1684
    return FALSE;
 
1685
}
 
1686
 
 
1687
static void
 
1688
ui_factory_menu_activate_cb (GtkMenuItem *item,
 
1689
                             gpointer     user_data)
 
1690
{
 
1691
    int id = GPOINTER_TO_INT (user_data);
 
1692
 
 
1693
    if (id >= 0 && id < (int) _factory_menu_uuids.size ())
 
1694
        _panel_agent->change_factory (_factory_menu_uuids [id]);
 
1695
    else
 
1696
        _panel_agent->change_factory ("");
 
1697
}
 
1698
 
 
1699
static void
 
1700
ui_factory_menu_deactivate_cb (GtkMenuItem *item,
 
1701
                               gpointer     user_data)
 
1702
{
 
1703
    _factory_menu_activated = false;
 
1704
    gettimeofday (&_last_menu_deactivate_time, 0);
 
1705
}
 
1706
 
 
1707
static gboolean
 
1708
ui_lookup_table_vertical_click_cb (GtkWidget      *item,
 
1709
                                   GdkEventButton *event,
 
1710
                                   gpointer        user_data)
 
1711
{
 
1712
    SCIM_DEBUG_MAIN (3) << "  ui_lookup_table_vertical_click_cb...\n";
 
1713
 
 
1714
    _panel_agent->select_candidate ((uint32)GPOINTER_TO_INT (user_data));
 
1715
 
 
1716
    return TRUE;
 
1717
}
 
1718
 
 
1719
static void
 
1720
ui_lookup_table_horizontal_click_cb (GtkWidget *item,
 
1721
                                     guint      position)
 
1722
{
 
1723
    SCIM_DEBUG_MAIN (3) << "  ui_lookup_table_horizontal_click_cb...\n";
 
1724
 
 
1725
    int *index = _lookup_table_index;
 
1726
    int pos = (int) position;
 
1727
 
 
1728
    for (int i=0; i<SCIM_LOOKUP_TABLE_MAX_PAGESIZE && index [i] >= 0; ++i) {
 
1729
        if (pos >= index [i] && pos < index [i+1]) {
 
1730
            _panel_agent->select_candidate ((uint32) i);
 
1731
            return;
 
1732
        }
 
1733
    }
 
1734
}
 
1735
 
 
1736
static void
 
1737
ui_lookup_table_up_button_click_cb (GtkButton *button,
 
1738
                                    gpointer user_data)
 
1739
{
 
1740
    SCIM_DEBUG_MAIN (3) << "  ui_lookup_table_up_button_click_cb...\n";
 
1741
 
 
1742
    _panel_agent->lookup_table_page_up ();
 
1743
}
 
1744
 
 
1745
static void
 
1746
ui_lookup_table_down_button_click_cb (GtkButton *button,
 
1747
                                      gpointer user_data)
 
1748
{
 
1749
    SCIM_DEBUG_MAIN (3) << "  ui_lookup_table_down_button_click_cb...\n";
 
1750
 
 
1751
    _panel_agent->lookup_table_page_down ();
 
1752
}
 
1753
 
 
1754
static void
 
1755
ui_window_stick_button_click_cb (GtkButton *button,
 
1756
                                 gpointer user_data)
 
1757
{
 
1758
    action_toggle_window_stick ();
 
1759
}
 
1760
 
 
1761
static gboolean
 
1762
ui_input_window_motion_cb (GtkWidget *window,
 
1763
                           GdkEventMotion *event,
 
1764
                           gpointer user_data)
 
1765
{
 
1766
    gint pos_x, pos_y;
 
1767
 
 
1768
    if ((event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) != 0 &&
 
1769
        _input_window_draging) {
 
1770
        gtk_window_get_position (GTK_WINDOW (window), &pos_x, &pos_y);
 
1771
        gtk_window_move (GTK_WINDOW (window), 
 
1772
            pos_x + ((gint) event->x_root - _input_window_drag_x),
 
1773
            pos_y + ((gint) event->y_root - _input_window_drag_y));
 
1774
 
 
1775
        _input_window_drag_x = (gint) event->x_root;
 
1776
        _input_window_drag_y = (gint) event->y_root;
 
1777
 
 
1778
        return TRUE;
 
1779
    }
 
1780
    return FALSE;
 
1781
}
 
1782
 
 
1783
static gboolean
 
1784
ui_input_window_click_cb (GtkWidget *window,
 
1785
                          GdkEventButton *event,
 
1786
                          gpointer user_data)
 
1787
{
 
1788
    int click_type = GPOINTER_TO_INT (user_data);
 
1789
    static gulong motion_handler;
 
1790
    GdkCursor *cursor;
 
1791
 
 
1792
    if (click_type == 0) {
 
1793
        if (_input_window_draging)
 
1794
            return FALSE;
 
1795
 
 
1796
        // Connection pointer motion handler to this window.
 
1797
        motion_handler = g_signal_connect (G_OBJECT (window), "motion-notify-event",
 
1798
                                           G_CALLBACK (ui_input_window_motion_cb),
 
1799
                                           NULL);
 
1800
 
 
1801
        _input_window_draging = TRUE;
 
1802
        _input_window_drag_x = (gint) event->x_root;
 
1803
        _input_window_drag_y = (gint) event->y_root;
 
1804
 
 
1805
        cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
 
1806
    
 
1807
        // Grab the cursor to prevent losing events.
 
1808
        gdk_pointer_grab (window->window, TRUE,
 
1809
                          (GdkEventMask) (GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK),
 
1810
                          NULL, cursor, event->time);
 
1811
        gdk_cursor_unref (cursor);
 
1812
        return TRUE;
 
1813
    } else if (click_type == 1) {
 
1814
        if (!_input_window_draging)
 
1815
            return FALSE;
 
1816
 
 
1817
        g_signal_handler_disconnect (G_OBJECT (window), motion_handler);
 
1818
        gdk_pointer_ungrab (event->time);
 
1819
        _input_window_draging = FALSE;
 
1820
 
 
1821
        gtk_window_get_position (GTK_WINDOW (window), &_input_window_x, &_input_window_y);
 
1822
 
 
1823
        return TRUE;
 
1824
    }
 
1825
 
 
1826
    return FALSE;
 
1827
}
 
1828
 
 
1829
static gboolean
 
1830
ui_toolbar_window_crossing_cb (GtkWidget        *window,
 
1831
                               GdkEventCrossing *event,
 
1832
                               gpointer          user_data)
 
1833
{
 
1834
    if (!_toolbar_always_show || _panel_is_on || _toolbar_window_draging)
 
1835
        return FALSE;
 
1836
 
 
1837
    int crossing_type = GPOINTER_TO_INT (user_data);
 
1838
 
 
1839
    // 0 == enter, otherwise leave 
 
1840
    if (crossing_type == 0) {
 
1841
        if (_toolbar_hidden) {
 
1842
            if (_window_stick_button)
 
1843
                gtk_widget_show (_window_stick_button);
 
1844
 
 
1845
            if (_factory_button)
 
1846
                gtk_widget_show (_factory_button);
 
1847
 
 
1848
            if (_client_properties_area)
 
1849
                gtk_widget_show (_client_properties_area);
 
1850
 
 
1851
            if (_menu_button)
 
1852
                gtk_widget_show (_menu_button);
 
1853
 
 
1854
            if (_help_button)
 
1855
                gtk_widget_show (_help_button);
 
1856
 
 
1857
            _toolbar_hidden = false;
 
1858
            ui_settle_toolbar_window ();
 
1859
        }
 
1860
        _toolbar_should_hide = false;
 
1861
    } else {
 
1862
        _toolbar_should_hide = true;
 
1863
    }
 
1864
 
 
1865
    return FALSE;
 
1866
}
 
1867
 
 
1868
static gboolean
 
1869
ui_toolbar_window_motion_cb (GtkWidget *window,
 
1870
                             GdkEventMotion *event,
 
1871
                             gpointer user_data)
 
1872
{
 
1873
    gint pos_x, pos_y;
 
1874
    if ((event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) != 0 &&
 
1875
        _toolbar_window_draging) {
 
1876
        gtk_window_get_position (GTK_WINDOW (window), &pos_x, &pos_y);
 
1877
        gtk_window_move (GTK_WINDOW (window), 
 
1878
            pos_x + ((gint) event->x_root - _toolbar_window_drag_x),
 
1879
            pos_y + ((gint) event->y_root - _toolbar_window_drag_y));
 
1880
 
 
1881
        _toolbar_window_drag_x = (gint) event->x_root;
 
1882
        _toolbar_window_drag_y = (gint) event->y_root;
 
1883
 
 
1884
        return TRUE;
 
1885
    }
 
1886
    return FALSE;
 
1887
}
 
1888
 
 
1889
static gboolean
 
1890
ui_toolbar_window_click_cb (GtkWidget *window,
 
1891
                            GdkEventButton *event,
 
1892
                            gpointer user_data)
 
1893
{
 
1894
    int click_type = GPOINTER_TO_INT (user_data);
 
1895
    static gulong motion_handler;
 
1896
    GdkCursor *cursor;
 
1897
 
 
1898
    if (click_type == 0 && event->button <= 1) {
 
1899
        if (_toolbar_window_draging)
 
1900
            return FALSE;
 
1901
 
 
1902
        // Connection pointer motion handler to this window.
 
1903
        motion_handler = g_signal_connect (G_OBJECT (window), "motion-notify-event",
 
1904
                                           G_CALLBACK (ui_toolbar_window_motion_cb),
 
1905
                                           NULL);
 
1906
 
 
1907
        _toolbar_window_draging = TRUE;
 
1908
        _toolbar_window_drag_x = (gint) event->x_root;
 
1909
        _toolbar_window_drag_y = (gint) event->y_root;
 
1910
 
 
1911
        cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
 
1912
 
 
1913
        // Grab the cursor to prevent losing events.
 
1914
        gdk_pointer_grab (window->window, TRUE,
 
1915
                          (GdkEventMask) (GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK),
 
1916
                          NULL, cursor, event->time);
 
1917
        gdk_cursor_unref (cursor);
 
1918
        return TRUE;
 
1919
    } else if (click_type == 1 && event->button <= 1) {
 
1920
        if (!_toolbar_window_draging)
 
1921
            return FALSE;
 
1922
 
 
1923
        g_signal_handler_disconnect (G_OBJECT (window), motion_handler);
 
1924
        gdk_pointer_ungrab (event->time);
 
1925
        _toolbar_window_draging = FALSE;
 
1926
 
 
1927
        gint pos_x, pos_y;
 
1928
 
 
1929
        gtk_window_get_position (GTK_WINDOW (window), &pos_x, &pos_y);
 
1930
 
 
1931
        if (!_config.null () &&
 
1932
            (_toolbar_window_x != pos_x || _toolbar_window_y != pos_y)) {
 
1933
            _config->write (
 
1934
                SCIM_CONFIG_PANEL_GTK_TOOLBAR_POS_X, pos_x);
 
1935
            _config->write (
 
1936
                SCIM_CONFIG_PANEL_GTK_TOOLBAR_POS_Y, pos_y);
 
1937
 
 
1938
        }
 
1939
        _toolbar_window_x = pos_x;
 
1940
        _toolbar_window_y = pos_y;
 
1941
 
 
1942
        return TRUE;
 
1943
    } else if (click_type == 1 && event->button > 1) {
 
1944
        action_show_command_menu ();
 
1945
        return TRUE;
 
1946
    }
 
1947
    return FALSE;
 
1948
}
 
1949
 
 
1950
static gboolean
 
1951
ui_lookup_table_window_motion_cb (GtkWidget      *window,
 
1952
                                  GdkEventMotion *event,
 
1953
                                  gpointer       user_data)
 
1954
{
 
1955
    gint pos_x, pos_y;
 
1956
    if ((event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) != 0 &&
 
1957
        _lookup_table_window_draging) {
 
1958
        gtk_window_get_position (GTK_WINDOW (window), &pos_x, &pos_y);
 
1959
        gtk_window_move (GTK_WINDOW (window), 
 
1960
            pos_x + ((gint) event->x_root - _lookup_table_window_drag_x),
 
1961
            pos_y + ((gint) event->y_root - _lookup_table_window_drag_y));
 
1962
 
 
1963
        _lookup_table_window_drag_x = (gint) event->x_root;
 
1964
        _lookup_table_window_drag_y = (gint) event->y_root;
 
1965
 
 
1966
        return TRUE;
 
1967
    }
 
1968
    return FALSE;
 
1969
}
 
1970
 
 
1971
static gboolean
 
1972
ui_lookup_table_window_click_cb (GtkWidget *window,
 
1973
                                 GdkEventButton *event,
 
1974
                                 gpointer user_data)
 
1975
{
 
1976
    int click_type = GPOINTER_TO_INT (user_data);
 
1977
    static gulong motion_handler;
 
1978
    GdkCursor *cursor;
 
1979
 
 
1980
    if (click_type == 0) {
 
1981
        if (_lookup_table_window_draging)
 
1982
            return FALSE;
 
1983
 
 
1984
        // Connection pointer motion handler to this window.
 
1985
        motion_handler = g_signal_connect (G_OBJECT (window), "motion-notify-event",
 
1986
                                           G_CALLBACK (ui_lookup_table_window_motion_cb),
 
1987
                                           NULL);
 
1988
 
 
1989
        _lookup_table_window_draging = TRUE;
 
1990
        _lookup_table_window_drag_x = (gint) event->x_root;
 
1991
        _lookup_table_window_drag_y = (gint) event->y_root;
 
1992
 
 
1993
        cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW);
 
1994
    
 
1995
        // Grab the cursor to prevent losing events.
 
1996
        gdk_pointer_grab (window->window, TRUE,
 
1997
                          (GdkEventMask) (GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK),
 
1998
                          NULL, cursor, event->time);
 
1999
        gdk_cursor_unref (cursor);
 
2000
        return TRUE;
 
2001
    } else if (click_type == 1) {
 
2002
        if (!_lookup_table_window_draging)
 
2003
            return FALSE;
 
2004
 
 
2005
        g_signal_handler_disconnect (G_OBJECT (window), motion_handler);
 
2006
        gdk_pointer_ungrab (event->time);
 
2007
        _lookup_table_window_draging = FALSE;
 
2008
 
 
2009
        gtk_window_get_position (GTK_WINDOW (window), &_lookup_table_window_x, &_lookup_table_window_y);
 
2010
 
 
2011
        return TRUE;
 
2012
    }
 
2013
 
 
2014
    return FALSE;
 
2015
}
 
2016
 
 
2017
static gboolean
 
2018
ui_hide_window_timeout_cb (gpointer data)
 
2019
{
 
2020
    gdk_threads_enter ();
 
2021
 
 
2022
    if (!_toolbar_always_show) {
 
2023
        gdk_threads_leave ();
 
2024
        return TRUE;
 
2025
    }
 
2026
 
 
2027
    if (!_toolbar_should_hide || _panel_is_on ||
 
2028
        _toolbar_window_draging || _toolbar_hidden ||
 
2029
        ui_any_menu_activated ()) {
 
2030
        _toolbar_hide_timeout_count = 0;
 
2031
        gdk_threads_leave ();
 
2032
        return TRUE;
 
2033
    }
 
2034
 
 
2035
    _toolbar_hide_timeout_count ++;
 
2036
 
 
2037
    if (_toolbar_hide_timeout_count > _toolbar_hide_timeout_max) {
 
2038
        _toolbar_hide_timeout_count = 0;
 
2039
 
 
2040
        if (_help_button)
 
2041
            gtk_widget_hide (_help_button);
 
2042
 
 
2043
        if (_menu_button)
 
2044
            gtk_widget_hide (_menu_button);
 
2045
 
 
2046
        if (_client_properties_area)
 
2047
            gtk_widget_hide (_client_properties_area);
 
2048
 
 
2049
        if (_factory_button)
 
2050
            gtk_widget_hide (_factory_button);
 
2051
 
 
2052
        if (_window_stick_button)
 
2053
            gtk_widget_hide (_window_stick_button);
 
2054
 
 
2055
        _toolbar_hidden = true;
 
2056
        ui_settle_toolbar_window ();
 
2057
    }
 
2058
 
 
2059
    gdk_threads_leave ();
 
2060
    return TRUE;
 
2061
}
 
2062
 
 
2063
static bool
 
2064
ui_can_hide_input_window (void)
 
2065
{
 
2066
    if (!_panel_is_on) return true;
 
2067
 
 
2068
    if (GTK_WIDGET_VISIBLE (_preedit_area) ||
 
2069
        GTK_WIDGET_VISIBLE (_aux_area) ||
 
2070
        (_lookup_table_embedded && GTK_WIDGET_VISIBLE (_lookup_table_window)))
 
2071
        return false;
 
2072
    return true;
 
2073
}
 
2074
 
 
2075
static bool
 
2076
ui_any_menu_activated (void)
 
2077
{
 
2078
    return _factory_menu_activated || _command_menu_activated || _property_menu_activated;
 
2079
}
 
2080
 
 
2081
static void
 
2082
ui_show_help (const String &help)
 
2083
{
 
2084
    if (!help.length () || !_help_dialog || !_help_scroll || !_help_area)
 
2085
        return;
 
2086
 
 
2087
    GtkRequisition size;
 
2088
 
 
2089
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (_help_scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
 
2090
 
 
2091
    gtk_label_set_text (GTK_LABEL (_help_area), help.c_str ());
 
2092
 
 
2093
    gtk_widget_size_request (_help_area, &size);
 
2094
 
 
2095
    if (size.width > ui_screen_width ()/2) {
 
2096
        size.width = ui_screen_width ()/2;
 
2097
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (_help_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
2098
    }
 
2099
 
 
2100
    if (size.height > ui_screen_height ()/2)
 
2101
        size.height = ui_screen_height ()/2;
 
2102
 
 
2103
    if (size.height < size.width/2)
 
2104
        size.height = size.width/2;
 
2105
 
 
2106
    gtk_widget_set_size_request (_help_scroll, size.width, size.height);
 
2107
 
 
2108
    gtk_window_set_position (GTK_WINDOW (_help_dialog), GTK_WIN_POS_CENTER_ALWAYS);
 
2109
    gtk_widget_show (_help_dialog);
 
2110
}
 
2111
 
 
2112
static PangoAttrList *
 
2113
create_pango_attrlist (const String        &mbs,
 
2114
                       const AttributeList &attrs)
 
2115
{
 
2116
    PangoAttrList  *attrlist = pango_attr_list_new ();
 
2117
    PangoAttribute *attr;
 
2118
 
 
2119
    guint start_index, end_index;
 
2120
    guint wlen = g_utf8_strlen (mbs.c_str (), mbs.length ());
 
2121
 
 
2122
    for (int i=0; i < (int) attrs.size (); ++i) {
 
2123
        start_index = attrs[i].get_start ();
 
2124
        end_index = attrs[i].get_end ();
 
2125
 
 
2126
        if (end_index <= wlen && start_index < end_index) {
 
2127
            start_index = g_utf8_offset_to_pointer (mbs.c_str (), attrs[i].get_start ()) - mbs.c_str ();
 
2128
            end_index = g_utf8_offset_to_pointer (mbs.c_str (), attrs[i].get_end ()) - mbs.c_str ();
 
2129
 
 
2130
            if (attrs[i].get_type () == SCIM_ATTR_DECORATE) {
 
2131
                if (attrs[i].get_value () == SCIM_ATTR_DECORATE_UNDERLINE) {
 
2132
                    attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
 
2133
                    attr->start_index = start_index;
 
2134
                    attr->end_index = end_index;
 
2135
                    pango_attr_list_insert (attrlist, attr);
 
2136
                } else if (attrs[i].get_value () == SCIM_ATTR_DECORATE_REVERSE) {
 
2137
                    attr = pango_attr_foreground_new (_normal_bg.red, _normal_bg.green, _normal_bg.blue);
 
2138
                    attr->start_index = start_index;
 
2139
                    attr->end_index = end_index;
 
2140
                    pango_attr_list_insert (attrlist, attr);
 
2141
 
 
2142
                    attr = pango_attr_background_new (_normal_text.red, _normal_text.green, _normal_text.blue);
 
2143
                    attr->start_index = start_index;
 
2144
                    attr->end_index = end_index;
 
2145
                    pango_attr_list_insert (attrlist, attr);
 
2146
                } else if (attrs[i].get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
 
2147
                    attr = pango_attr_foreground_new (_active_text.red, _active_text.green, _active_text.blue);
 
2148
                    attr->start_index = start_index;
 
2149
                    attr->end_index = end_index;
 
2150
                    pango_attr_list_insert (attrlist, attr);
 
2151
 
 
2152
                    attr = pango_attr_background_new (_active_bg.red, _active_bg.green, _active_bg.blue);
 
2153
                    attr->start_index = start_index;
 
2154
                    attr->end_index = end_index;
 
2155
                    pango_attr_list_insert (attrlist, attr);
 
2156
                }
 
2157
            } else if (attrs[i].get_type () == SCIM_ATTR_FOREGROUND) {
 
2158
                unsigned int color = attrs[i].get_value ();
 
2159
 
 
2160
                attr = pango_attr_foreground_new (SCIM_RGB_COLOR_RED(color) * 256, SCIM_RGB_COLOR_GREEN(color) * 256, SCIM_RGB_COLOR_BLUE(color) * 256);
 
2161
                attr->start_index = start_index;
 
2162
                attr->end_index = end_index;
 
2163
                pango_attr_list_insert (attrlist, attr);
 
2164
            } else if (attrs[i].get_type () == SCIM_ATTR_BACKGROUND) {
 
2165
                unsigned int color = attrs[i].get_value ();
 
2166
 
 
2167
                attr = pango_attr_background_new (SCIM_RGB_COLOR_RED(color) * 256, SCIM_RGB_COLOR_GREEN(color) * 256, SCIM_RGB_COLOR_BLUE(color) * 256);
 
2168
                attr->start_index = start_index;
 
2169
                attr->end_index = end_index;
 
2170
                pango_attr_list_insert (attrlist, attr);
 
2171
            }
 
2172
        }
 
2173
    }
 
2174
    return attrlist;
 
2175
}
 
2176
 
 
2177
static void
 
2178
ui_command_menu_exit_activate_cb (GtkMenuItem *item,
 
2179
                                  gpointer     user_data)
 
2180
{
 
2181
    _panel_agent->exit ();
 
2182
}
 
2183
 
 
2184
static void
 
2185
ui_command_menu_reload_activate_cb (GtkMenuItem *item,
 
2186
                                    gpointer     user_data)
 
2187
{
 
2188
    _panel_agent->reload_config ();
 
2189
 
 
2190
    if (!_config.null ()) _config->reload ();
 
2191
}
 
2192
 
 
2193
static void
 
2194
ui_command_menu_stick_activate_cb (GtkMenuItem *item,
 
2195
                                   gpointer     user_data)
 
2196
{
 
2197
    action_toggle_window_stick ();
 
2198
}
 
2199
 
 
2200
static void
 
2201
ui_command_menu_hide_toolbar_toggled_cb (GtkMenuItem *item,
 
2202
                                         gpointer     user_data)
 
2203
{
 
2204
    _toolbar_always_hidden = ! _toolbar_always_hidden;
 
2205
 
 
2206
    if (_toolbar_always_hidden && !_toolbar_hidden) {
 
2207
        gtk_widget_hide (_toolbar_window);
 
2208
        _toolbar_hidden = true;
 
2209
    } else if (!_toolbar_always_hidden && _panel_is_on) {
 
2210
        gtk_widget_show (_toolbar_window);
 
2211
        _toolbar_hidden = false;
 
2212
    }
 
2213
}
 
2214
 
 
2215
static void
 
2216
ui_command_menu_help_activate_cb (GtkMenuItem *item,
 
2217
                                  gpointer     user_data)
 
2218
{
 
2219
    if (GTK_WIDGET_VISIBLE (_help_dialog)) {
 
2220
        gtk_widget_hide (_help_dialog);
 
2221
    } else {
 
2222
        action_request_help ();
 
2223
    }
 
2224
}
 
2225
 
 
2226
static void
 
2227
ui_command_menu_helper_activate_cb (GtkWidget *item,
 
2228
                                    gpointer   user_data)
 
2229
{
 
2230
    size_t i = (size_t) GPOINTER_TO_INT (user_data);
 
2231
 
 
2232
    if (i < _helper_list.size ())
 
2233
        _panel_agent->start_helper (_helper_list [i].uuid);
 
2234
}
 
2235
 
 
2236
static void
 
2237
ui_command_menu_deactivate_cb (GtkWidget   *item,
 
2238
                               gpointer     user_data)
 
2239
{
 
2240
    _command_menu_activated = false;
 
2241
    gettimeofday (&_last_menu_deactivate_time, 0);
 
2242
}
 
2243
 
 
2244
#if ENABLE_TRAY_ICON
 
2245
static void
 
2246
ui_tray_icon_destroy_cb (GtkObject      *object,
 
2247
                         gpointer        user_data)
 
2248
{
 
2249
    SCIM_DEBUG_MAIN (1) << "Tray Icon destroyed!\n";
 
2250
 
 
2251
    gtk_widget_destroy (GTK_WIDGET (object));
 
2252
 
 
2253
    _tray_icon = 0;
 
2254
    _tray_icon_factory_button = 0;
 
2255
 
 
2256
    g_idle_add (ui_create_tray_icon_when_idle, NULL);
 
2257
}
 
2258
#endif
 
2259
 
 
2260
static void
 
2261
ui_property_activate_cb (GtkWidget      *widget,
 
2262
                         gpointer        user_data)
 
2263
{
 
2264
    GtkWidget *submenu = (GtkWidget *) g_object_get_data (G_OBJECT (widget), "property_submenu");
 
2265
 
 
2266
    if (submenu) {
 
2267
#if GDK_MULTIHEAD_SAFE
 
2268
        if (_current_screen)
 
2269
            gtk_menu_set_screen (GTK_MENU (submenu), _current_screen);
 
2270
#endif
 
2271
        guint32 activate_time = gtk_get_current_event_time ();
 
2272
        _property_menu_activated = true;
 
2273
        gtk_menu_popup (GTK_MENU (submenu), 0, 0, 0, 0, 1, activate_time);
 
2274
        return;
 
2275
    }
 
2276
 
 
2277
    gchar * key = (gchar *) g_object_get_data (G_OBJECT (widget), "property_key");
 
2278
 
 
2279
    if (key) {
 
2280
        int client = GPOINTER_TO_INT (user_data);
 
2281
 
 
2282
        if (client < 0)
 
2283
            _panel_agent->trigger_property (key);
 
2284
        else
 
2285
            _panel_agent->trigger_helper_property (client, key);
 
2286
    }
 
2287
}
 
2288
 
 
2289
static void
 
2290
ui_property_menu_deactivate_cb (GtkWidget   *item,
 
2291
                                gpointer     user_data)
 
2292
{
 
2293
    _property_menu_activated = false;
 
2294
}
 
2295
 
 
2296
//Implementation of the action functions
 
2297
static void
 
2298
action_request_help (void)
 
2299
{
 
2300
    if (!_panel_agent->request_help ()) {
 
2301
        String help;
 
2302
 
 
2303
        help =  String (_("Smart Common Input Method platform ")) +
 
2304
                String (SCIM_VERSION) +
 
2305
                String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>"));
 
2306
 
 
2307
        ui_show_help (help);
 
2308
    }
 
2309
}
 
2310
 
 
2311
static void
 
2312
action_toggle_window_stick (void)
 
2313
{
 
2314
    GtkWidget *image;
 
2315
 
 
2316
    _window_sticked = ! _window_sticked;
 
2317
 
 
2318
    if (_window_stick_button) {
 
2319
        image = gtk_bin_get_child (GTK_BIN (_window_stick_button));
 
2320
        gtk_container_remove (GTK_CONTAINER (_window_stick_button), image);
 
2321
 
 
2322
        image = ui_create_stick_icon (_window_sticked);
 
2323
        gtk_container_add (GTK_CONTAINER (_window_stick_button), image);
 
2324
    }
 
2325
}
 
2326
 
 
2327
static void
 
2328
action_show_command_menu (void)
 
2329
{
 
2330
    if (_command_menu_activated)
 
2331
        return;
 
2332
 
 
2333
    _command_menu_activated = true;
 
2334
 
 
2335
    guint32 activate_time = gtk_get_current_event_time ();
 
2336
 
 
2337
    if (_command_menu) {
 
2338
        gtk_widget_destroy (_command_menu);
 
2339
        _command_menu = 0;
 
2340
    }
 
2341
 
 
2342
    _command_menu = gtk_menu_new ();
 
2343
 
 
2344
#if GDK_MULTIHEAD_SAFE
 
2345
    if (_current_screen)
 
2346
        gtk_menu_set_screen (GTK_MENU (_command_menu), _current_screen);
 
2347
#endif
 
2348
 
 
2349
    GtkWidget *menu_item;
 
2350
    GtkWidget *icon;
 
2351
 
 
2352
    gint width, height;
 
2353
 
 
2354
    gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
 
2355
 
 
2356
    // Add Helper object items.
 
2357
    for (size_t i = 0; i < _helper_list.size (); ++i) {
 
2358
        if ((_helper_list [i].option & SCIM_HELPER_STAND_ALONE) != 0 &&
 
2359
            (_helper_list [i].option & SCIM_HELPER_AUTO_START) == 0) {
 
2360
            menu_item = gtk_image_menu_item_new_with_label (_helper_list [i].name.c_str ());
 
2361
            gtk_tooltips_set_tip (_tooltips, menu_item, _helper_list [i].description.c_str (), NULL);
 
2362
            icon = ui_create_icon (_helper_list [i].icon, NULL, width, height, false);
 
2363
 
 
2364
            if (icon)
 
2365
                gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), icon);
 
2366
 
 
2367
            gtk_menu_shell_append (GTK_MENU_SHELL (_command_menu), menu_item);
 
2368
 
 
2369
            g_signal_connect (G_OBJECT (menu_item), "activate",
 
2370
                              G_CALLBACK (ui_command_menu_helper_activate_cb),
 
2371
                              GINT_TO_POINTER ((int)i));
 
2372
 
 
2373
            gtk_widget_show (menu_item);
 
2374
        }
 
2375
    }
 
2376
 
 
2377
    if (_helper_list.size ()) {
 
2378
        menu_item = gtk_separator_menu_item_new ();
 
2379
        gtk_menu_shell_append (GTK_MENU_SHELL (_command_menu), menu_item);
 
2380
        gtk_widget_show (menu_item);
 
2381
    }
 
2382
 
 
2383
    //Reload Configuration.
 
2384
    menu_item = gtk_image_menu_item_new_with_label (_("Reload Configuration"));
 
2385
    gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
 
2386
                                   gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU));
 
2387
    gtk_menu_shell_append (GTK_MENU_SHELL (_command_menu), menu_item);
 
2388
    g_signal_connect (G_OBJECT (menu_item), "activate",
 
2389
                      G_CALLBACK (ui_command_menu_reload_activate_cb),
 
2390
                      0);
 
2391
    gtk_widget_show_all (menu_item);
 
2392
 
 
2393
    //Stick
 
2394
    menu_item = gtk_check_menu_item_new_with_label (_("Stick Windows"));
 
2395
    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), _window_sticked);
 
2396
    gtk_menu_shell_append (GTK_MENU_SHELL (_command_menu), menu_item);
 
2397
    g_signal_connect (G_OBJECT (menu_item), "activate",
 
2398
                      G_CALLBACK (ui_command_menu_stick_activate_cb),
 
2399
                      0);
 
2400
    gtk_widget_show_all (menu_item);
 
2401
 
 
2402
    //Toolbar
 
2403
    menu_item = gtk_check_menu_item_new_with_label (_("Hide Toolbar"));
 
2404
    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), _toolbar_always_hidden);
 
2405
    gtk_menu_shell_append (GTK_MENU_SHELL (_command_menu), menu_item);
 
2406
    g_signal_connect (G_OBJECT (menu_item), "toggled",
 
2407
                      G_CALLBACK (ui_command_menu_hide_toolbar_toggled_cb),
 
2408
                      0);
 
2409
    gtk_widget_show_all (menu_item);
 
2410
 
 
2411
    //Help
 
2412
    menu_item = gtk_image_menu_item_new_with_label (_("Help ..."));
 
2413
    gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
 
2414
                                   gtk_image_new_from_stock (GTK_STOCK_HELP, GTK_ICON_SIZE_MENU));
 
2415
    gtk_menu_shell_append (GTK_MENU_SHELL (_command_menu), menu_item);
 
2416
    g_signal_connect (G_OBJECT (menu_item), "activate",
 
2417
                      G_CALLBACK (ui_command_menu_help_activate_cb),
 
2418
                      0);
 
2419
    gtk_widget_show_all (menu_item);
 
2420
 
 
2421
    g_signal_connect (G_OBJECT (_command_menu), "deactivate",
 
2422
                      G_CALLBACK (ui_command_menu_deactivate_cb),
 
2423
                      NULL);
 
2424
 
 
2425
    menu_item = gtk_separator_menu_item_new ();
 
2426
    gtk_menu_shell_append (GTK_MENU_SHELL (_command_menu), menu_item);
 
2427
    gtk_widget_show (menu_item);
 
2428
 
 
2429
    //Clients exit.
 
2430
    menu_item = gtk_image_menu_item_new_with_label (_("Exit"));
 
2431
    gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
 
2432
                                   gtk_image_new_from_stock (GTK_STOCK_QUIT, GTK_ICON_SIZE_MENU));
 
2433
    gtk_menu_shell_append (GTK_MENU_SHELL (_command_menu), menu_item);
 
2434
    g_signal_connect (G_OBJECT (menu_item), "activate",
 
2435
                      G_CALLBACK (ui_command_menu_exit_activate_cb),
 
2436
                      0);
 
2437
    gtk_widget_show_all (menu_item);
 
2438
 
 
2439
    gtk_menu_popup (GTK_MENU (_command_menu), 0, 0, 0, 0, 2, activate_time);
 
2440
}
 
2441
 
 
2442
//////////////////////////////////////////////////////////////////////
 
2443
// Start of PanelAgent Functions
 
2444
//////////////////////////////////////////////////////////////////////
 
2445
static bool
 
2446
initialize_panel_agent (const String &config, const String &display, bool resident)
 
2447
{
 
2448
    _panel_agent = new PanelAgent ();
 
2449
 
 
2450
    if (!_panel_agent->initialize (config, display, resident))
 
2451
        return false;
 
2452
 
 
2453
    _panel_agent->signal_connect_transaction_start          (slot (slot_transaction_start));
 
2454
    _panel_agent->signal_connect_transaction_end            (slot (slot_transaction_end));
 
2455
    _panel_agent->signal_connect_reload_config              (slot (slot_reload_config));
 
2456
    _panel_agent->signal_connect_turn_on                    (slot (slot_turn_on));
 
2457
    _panel_agent->signal_connect_turn_off                   (slot (slot_turn_off));
 
2458
    _panel_agent->signal_connect_update_screen              (slot (slot_update_screen));
 
2459
    _panel_agent->signal_connect_update_spot_location       (slot (slot_update_spot_location));
 
2460
    _panel_agent->signal_connect_update_factory_info        (slot (slot_update_factory_info));
 
2461
    _panel_agent->signal_connect_show_help                  (slot (slot_show_help));
 
2462
    _panel_agent->signal_connect_show_factory_menu          (slot (slot_show_factory_menu));
 
2463
    _panel_agent->signal_connect_show_preedit_string        (slot (slot_show_preedit_string));
 
2464
    _panel_agent->signal_connect_show_aux_string            (slot (slot_show_aux_string));
 
2465
    _panel_agent->signal_connect_show_lookup_table          (slot (slot_show_lookup_table));
 
2466
    _panel_agent->signal_connect_hide_preedit_string        (slot (slot_hide_preedit_string));
 
2467
    _panel_agent->signal_connect_hide_aux_string            (slot (slot_hide_aux_string));
 
2468
    _panel_agent->signal_connect_hide_lookup_table          (slot (slot_hide_lookup_table));
 
2469
    _panel_agent->signal_connect_update_preedit_string      (slot (slot_update_preedit_string));
 
2470
    _panel_agent->signal_connect_update_preedit_caret       (slot (slot_update_preedit_caret));
 
2471
    _panel_agent->signal_connect_update_aux_string          (slot (slot_update_aux_string));
 
2472
    _panel_agent->signal_connect_update_lookup_table        (slot (slot_update_lookup_table));
 
2473
    _panel_agent->signal_connect_register_properties        (slot (slot_register_properties));
 
2474
    _panel_agent->signal_connect_update_property            (slot (slot_update_property));
 
2475
    _panel_agent->signal_connect_register_helper_properties (slot (slot_register_helper_properties));
 
2476
    _panel_agent->signal_connect_update_helper_property     (slot (slot_update_helper_property));
 
2477
    _panel_agent->signal_connect_register_helper            (slot (slot_register_helper));
 
2478
    _panel_agent->signal_connect_remove_helper              (slot (slot_remove_helper));
 
2479
    _panel_agent->signal_connect_lock                       (slot (slot_lock));
 
2480
    _panel_agent->signal_connect_unlock                     (slot (slot_unlock));
 
2481
 
 
2482
    _panel_agent->get_helper_list (_helper_list);
 
2483
 
 
2484
    return true;
 
2485
}
 
2486
 
 
2487
static bool
 
2488
run_panel_agent (void)
 
2489
{
 
2490
    SCIM_DEBUG_MAIN(1) << "run_panel_agent ()\n";
 
2491
 
 
2492
    _panel_agent_thread = NULL;
 
2493
 
 
2494
    if (_panel_agent && _panel_agent->valid ())
 
2495
        _panel_agent_thread = g_thread_create (panel_agent_thread_func, NULL, TRUE, NULL);
 
2496
 
 
2497
    return (_panel_agent_thread != NULL);
 
2498
}
 
2499
 
 
2500
static gpointer
 
2501
panel_agent_thread_func (gpointer data)
 
2502
{
 
2503
    SCIM_DEBUG_MAIN(1) << "panel_agent_thread_func ()\n";
 
2504
 
 
2505
    if (!_panel_agent->run ())
 
2506
        std::cerr << "Failed to run Panel.\n";
 
2507
 
 
2508
    G_LOCK (_global_resource_lock);
 
2509
    _should_exit = true;
 
2510
    G_UNLOCK (_global_resource_lock);
 
2511
 
 
2512
    g_thread_exit (NULL);
 
2513
    return ((gpointer) NULL);
 
2514
}
 
2515
 
 
2516
static void
 
2517
start_auto_start_helpers (void)
 
2518
{
 
2519
    SCIM_DEBUG_MAIN(1) << "start_auto_start_helpers ()\n";
 
2520
 
 
2521
    // Add Helper object items.
 
2522
    for (size_t i = 0; i < _helper_list.size (); ++i) {
 
2523
        if ((_helper_list [i].option & SCIM_HELPER_AUTO_START) != 0) {
 
2524
            _panel_agent->start_helper (_helper_list [i].uuid);
 
2525
        }
 
2526
    }
 
2527
}
 
2528
 
 
2529
static void
 
2530
slot_transaction_start (void)
 
2531
{
 
2532
    gdk_threads_enter ();
 
2533
}
 
2534
 
 
2535
static void
 
2536
slot_transaction_end (void)
 
2537
{
 
2538
    gdk_threads_leave ();
 
2539
}
 
2540
 
 
2541
static void
 
2542
slot_reload_config (void)
 
2543
{
 
2544
    if (!_config.null ()) _config->reload ();
 
2545
}
 
2546
 
 
2547
static void
 
2548
slot_turn_on (void)
 
2549
{
 
2550
    _toolbar_should_hide = false;
 
2551
    _toolbar_hidden = false;
 
2552
    _panel_is_on = true;
 
2553
 
 
2554
    gtk_widget_hide (_lookup_table_window);
 
2555
    gtk_widget_hide (_input_window);
 
2556
    gtk_widget_hide (_preedit_area);
 
2557
    gtk_widget_hide (_aux_area);
 
2558
 
 
2559
    if (_toolbar_always_hidden)
 
2560
        return;
 
2561
 
 
2562
    if (_frontend_properties_area)
 
2563
        gtk_widget_hide (_frontend_properties_area);
 
2564
 
 
2565
    if (_window_stick_button)
 
2566
        gtk_widget_show (_window_stick_button);
 
2567
 
 
2568
    if (_factory_button)
 
2569
        gtk_widget_show (_factory_button);
 
2570
 
 
2571
    if (_client_properties_area)
 
2572
        gtk_widget_show (_client_properties_area);
 
2573
 
 
2574
    if (_menu_button)
 
2575
        gtk_widget_show (_menu_button);
 
2576
 
 
2577
    if (_help_button)
 
2578
        gtk_widget_show (_help_button);
 
2579
 
 
2580
    if (!_toolbar_always_hidden)
 
2581
        gtk_widget_show (_toolbar_window);
 
2582
 
 
2583
    ui_settle_toolbar_window (true);
 
2584
}
 
2585
 
 
2586
static void
 
2587
slot_turn_off (void)
 
2588
{
 
2589
    if (ui_any_menu_activated ()) return;
 
2590
 
 
2591
    _panel_is_on = false;
 
2592
 
 
2593
    gtk_widget_hide (_input_window);
 
2594
    gtk_widget_hide (_lookup_table_window);
 
2595
 
 
2596
    gtk_widget_hide (_preedit_area);
 
2597
    gtk_widget_hide (_aux_area);
 
2598
 
 
2599
    if (_frontend_properties_area)
 
2600
        gtk_widget_hide (_frontend_properties_area);
 
2601
 
 
2602
    if (_toolbar_always_show) {
 
2603
        if (!_toolbar_hidden) {
 
2604
            if (_window_stick_button)
 
2605
                gtk_widget_show (_window_stick_button);
 
2606
 
 
2607
            if (_factory_button)
 
2608
                gtk_widget_show (_factory_button);
 
2609
 
 
2610
            if (_client_properties_area)
 
2611
                gtk_widget_show (_client_properties_area);
 
2612
 
 
2613
            if (_menu_button)
 
2614
                gtk_widget_show (_menu_button);
 
2615
 
 
2616
            if (_help_button)
 
2617
                gtk_widget_show (_help_button);
 
2618
        }
 
2619
        gtk_widget_show (_toolbar_window);
 
2620
        ui_settle_toolbar_window (true);
 
2621
        _toolbar_should_hide = true;
 
2622
    } else {
 
2623
        gtk_widget_hide (_toolbar_window);
 
2624
        _toolbar_hidden = true;
 
2625
    }
 
2626
}
 
2627
 
 
2628
static void
 
2629
slot_update_screen (int num)
 
2630
{
 
2631
#if GDK_MULTIHEAD_SAFE
 
2632
    if (gdk_display_get_n_screens (gdk_display_get_default ()) > num) {
 
2633
 
 
2634
        GdkScreen *screen = gdk_display_get_screen (gdk_display_get_default (), num);
 
2635
 
 
2636
        if (screen) {
 
2637
#ifdef GDK_WINDOWING_X11
 
2638
            GdkWindow *root_window = gdk_get_default_root_window ();
 
2639
            if (_current_screen)
 
2640
                root_window = gdk_screen_get_root_window (_current_screen);
 
2641
            gdk_window_remove_filter (root_window, ui_event_filter, NULL);
 
2642
#endif
 
2643
 
 
2644
            _current_screen = screen;
 
2645
            ui_switch_screen (screen);
 
2646
        }
 
2647
    }
 
2648
#endif
 
2649
}
 
2650
 
 
2651
static void
 
2652
slot_update_factory_info (const PanelFactoryInfo &info)
 
2653
{
 
2654
    if (_factory_button) {
 
2655
        GtkWidget * newlabel = 0;
 
2656
 
 
2657
        if (_toolbar_show_factory_icon) {
 
2658
            newlabel = ui_create_label (info.name,
 
2659
                                        info.icon,
 
2660
                                        0,
 
2661
                                        !_toolbar_show_factory_name,
 
2662
                                        false);
 
2663
        } else {
 
2664
            newlabel = gtk_label_new (info.name.c_str ());
 
2665
            if (_default_font_desc)
 
2666
                gtk_widget_modify_font (newlabel, _default_font_desc);
 
2667
            gtk_widget_show (newlabel);
 
2668
        }
 
2669
 
 
2670
        if (newlabel) {
 
2671
            GtkWidget * old = gtk_bin_get_child (GTK_BIN (_factory_button));
 
2672
            if (old)
 
2673
                gtk_container_remove (GTK_CONTAINER (_factory_button), old);
 
2674
            gtk_container_add (GTK_CONTAINER (_factory_button), newlabel);
 
2675
        }
 
2676
 
 
2677
        if (!GTK_WIDGET_VISIBLE (_factory_button) && !_toolbar_hidden)
 
2678
            gtk_widget_show (_factory_button);
 
2679
 
 
2680
        if (_tooltips)
 
2681
            gtk_tooltips_set_tip (_tooltips, _factory_button, info.name.c_str (), NULL);
 
2682
 
 
2683
        ui_settle_toolbar_window ();
 
2684
    }
 
2685
 
 
2686
#if ENABLE_TRAY_ICON
 
2687
    if (_tray_icon_factory_button) {
 
2688
        GtkWidget *icon = gtk_bin_get_child (GTK_BIN (_tray_icon_factory_button));
 
2689
 
 
2690
        if (icon)
 
2691
            gtk_container_remove (GTK_CONTAINER (_tray_icon_factory_button), icon);
 
2692
 
 
2693
        icon = ui_create_icon (info.icon, NULL, TRAY_ICON_SIZE, TRAY_ICON_SIZE, true);
 
2694
 
 
2695
        gtk_container_add (GTK_CONTAINER (_tray_icon_factory_button), icon);
 
2696
 
 
2697
        if (_tooltips)
 
2698
            gtk_tooltips_set_tip (_tooltips, _tray_icon_factory_button, info.name.c_str (), NULL);
 
2699
    }
 
2700
#endif
 
2701
 
 
2702
    if (info.uuid != "") {
 
2703
        _recent_factory_uuids.remove(info.uuid);
 
2704
        _recent_factory_uuids.push_front(info.uuid);
 
2705
        if (_recent_factory_uuids.size () > 5)
 
2706
            _recent_factory_uuids.pop_back ();
 
2707
    }
 
2708
}
 
2709
 
 
2710
static void
 
2711
slot_show_help (const String &help)
 
2712
{
 
2713
    ui_show_help (help);
 
2714
}
 
2715
 
 
2716
static void
 
2717
slot_show_factory_menu (const std::vector <PanelFactoryInfo> &factories)
 
2718
{
 
2719
    if (!_factory_menu_activated && factories.size ()) {
 
2720
        size_t i;
 
2721
 
 
2722
        MapStringVectorSizeT groups;
 
2723
        std::map<String,size_t> langs, recents;
 
2724
 
 
2725
        guint32 activate_time = gtk_get_current_event_time ();
 
2726
 
 
2727
        _factory_menu_uuids.clear ();
 
2728
        _factory_menu_activated = true;
 
2729
 
 
2730
        bool use_submenus = false;
 
2731
        bool show_recent = (factories.size () > 5 && _recent_factory_uuids.size ());
 
2732
 
 
2733
        for (i = 0; i < factories.size (); ++i) {
 
2734
            _factory_menu_uuids.push_back (factories [i].uuid);
 
2735
            langs [factories [i].lang]++;
 
2736
 
 
2737
            if (show_recent &&
 
2738
                std::find (_recent_factory_uuids.begin (), _recent_factory_uuids.end (),
 
2739
                           factories [i].uuid) != _recent_factory_uuids.end ()) {
 
2740
                recents [factories [i].uuid] = i;
 
2741
            } else {
 
2742
                groups [factories [i].lang].push_back (i);
 
2743
                if (groups [factories [i].lang].size () > 1)
 
2744
                    use_submenus = true;
 
2745
            }
 
2746
        }
 
2747
 
 
2748
        use_submenus = (use_submenus && factories.size () > 9);
 
2749
 
 
2750
        if (_factory_menu) {
 
2751
            gtk_widget_destroy (_factory_menu);
 
2752
            _factory_menu = 0;
 
2753
        }
 
2754
 
 
2755
        _factory_menu = gtk_menu_new ();
 
2756
 
 
2757
#if GDK_MULTIHEAD_SAFE
 
2758
    if (_current_screen)
 
2759
        gtk_menu_set_screen (GTK_MENU (_factory_menu), _current_screen);
 
2760
#endif
 
2761
 
 
2762
        GtkWidget *submenu;
 
2763
        GtkWidget *menu_item;
 
2764
        guint id;
 
2765
        PanelFactoryInfo info;
 
2766
 
 
2767
        // recently used factories
 
2768
        if (show_recent && recents.size ()) {
 
2769
            for (std::list<String>::iterator it = _recent_factory_uuids.begin (); it != _recent_factory_uuids.end (); ++it) {
 
2770
        
 
2771
                id = recents [*it];
 
2772
                info = factories [id];
 
2773
 
 
2774
                ui_create_factory_menu_entry (info, id, GTK_MENU_SHELL (_factory_menu), true, (langs [info.lang] > 1));
 
2775
 
 
2776
                if (use_submenus) {
 
2777
                    MapStringVectorSizeT::iterator g = groups.find (info.lang);
 
2778
                    if (g != groups.end () && g->second.size () >= 1) {
 
2779
                        g->second.push_back (id);
 
2780
                    }
 
2781
                }
 
2782
            }
 
2783
 
 
2784
            menu_item = gtk_separator_menu_item_new ();
 
2785
            gtk_menu_shell_append (GTK_MENU_SHELL (_factory_menu), menu_item);
 
2786
            gtk_widget_show (menu_item);
 
2787
        }
 
2788
 
 
2789
        for (MapStringVectorSizeT::iterator it = groups.begin (); it != groups.end (); ++ it) {
 
2790
            if (use_submenus && it->second.size () > 1) {
 
2791
                String lang = it->first;
 
2792
                menu_item = gtk_menu_item_new_with_label (scim_get_language_name (lang).c_str ());
 
2793
                submenu = gtk_menu_new ();
 
2794
            } else {
 
2795
                menu_item = 0;
 
2796
                submenu = 0;
 
2797
            }
 
2798
 
 
2799
            for (i = 0; i < it->second.size (); ++i) {
 
2800
                id = it->second [i];
 
2801
                info = factories [id];
 
2802
                ui_create_factory_menu_entry (info, id, GTK_MENU_SHELL (submenu ? submenu : _factory_menu), !submenu, (langs [info.lang] > 1));
 
2803
            }
 
2804
 
 
2805
            if (menu_item && submenu) {
 
2806
                gtk_menu_shell_append (GTK_MENU_SHELL (_factory_menu), menu_item);
 
2807
                gtk_widget_show (menu_item);
 
2808
                gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), submenu);
 
2809
                gtk_widget_show (submenu);
 
2810
            }
 
2811
        }
 
2812
 
 
2813
        //Append an entry for forward mode.
 
2814
        info = PanelFactoryInfo (String (""), String (_("English/Keyboard")), String ("C"), String (SCIM_KEYBOARD_ICON_FILE));
 
2815
        ui_create_factory_menu_entry (info, -1, GTK_MENU_SHELL (_factory_menu), false, true);
 
2816
 
 
2817
        g_signal_connect (G_OBJECT (_factory_menu), "deactivate",
 
2818
                          G_CALLBACK (ui_factory_menu_deactivate_cb),
 
2819
                          NULL);
 
2820
        gtk_menu_popup (GTK_MENU (_factory_menu), 0, 0, 0, 0, 1, activate_time);
 
2821
    }
 
2822
}
 
2823
 
 
2824
static void
 
2825
slot_update_spot_location (int x, int y)
 
2826
{
 
2827
    if (x > 0 && x < ui_screen_width () && y > 0 && y < ui_screen_height ()) {
 
2828
        _spot_location_x = x;
 
2829
        _spot_location_y = y;
 
2830
 
 
2831
        ui_settle_input_window ();
 
2832
        ui_settle_lookup_table_window ();
 
2833
    }
 
2834
}
 
2835
 
 
2836
static void
 
2837
slot_show_preedit_string (void)
 
2838
{
 
2839
    gtk_widget_show (_preedit_area);
 
2840
 
 
2841
    if (_panel_is_on && !GTK_WIDGET_VISIBLE (_input_window))
 
2842
        gtk_widget_show (_input_window);
 
2843
 
 
2844
    ui_settle_input_window (true, true);
 
2845
    ui_settle_lookup_table_window ();
 
2846
}
 
2847
 
 
2848
static void
 
2849
slot_show_aux_string (void)
 
2850
{
 
2851
    gtk_widget_show (_aux_area);
 
2852
 
 
2853
    if (_panel_is_on && !GTK_WIDGET_VISIBLE (_input_window))
 
2854
        gtk_widget_show (_input_window);
 
2855
 
 
2856
    ui_settle_input_window (true, true);
 
2857
    ui_settle_lookup_table_window ();
 
2858
}
 
2859
 
 
2860
static void
 
2861
slot_show_lookup_table (void)
 
2862
{
 
2863
    gtk_widget_show (_lookup_table_window);
 
2864
 
 
2865
    if (_panel_is_on && _lookup_table_embedded && !GTK_WIDGET_VISIBLE (_input_window)) {
 
2866
        gtk_widget_show (_input_window);
 
2867
        ui_settle_input_window (true, true);
 
2868
    }
 
2869
 
 
2870
    ui_settle_lookup_table_window (true);
 
2871
}
 
2872
 
 
2873
static void
 
2874
slot_hide_preedit_string (void)
 
2875
{
 
2876
    gtk_widget_hide (_preedit_area);
 
2877
    scim_string_view_set_text (SCIM_STRING_VIEW (_preedit_area), "");
 
2878
 
 
2879
    if (ui_can_hide_input_window ())
 
2880
        gtk_widget_hide (_input_window);
 
2881
 
 
2882
    ui_settle_lookup_table_window ();
 
2883
}
 
2884
 
 
2885
static void
 
2886
slot_hide_aux_string (void)
 
2887
{
 
2888
    gtk_widget_hide (_aux_area);
 
2889
    scim_string_view_set_text (SCIM_STRING_VIEW (_aux_area), "");
 
2890
 
 
2891
    if (ui_can_hide_input_window ())
 
2892
        gtk_widget_hide (_input_window);
 
2893
 
 
2894
    ui_settle_lookup_table_window ();
 
2895
}
 
2896
 
 
2897
static void
 
2898
slot_hide_lookup_table (void)
 
2899
{
 
2900
    gtk_widget_hide (_lookup_table_window);
 
2901
 
 
2902
    if (_lookup_table_embedded && ui_can_hide_input_window ())
 
2903
        gtk_widget_hide (_input_window);
 
2904
}
 
2905
 
 
2906
static void
 
2907
slot_update_preedit_string (const String &str, const AttributeList &attrs)
 
2908
{
 
2909
    PangoAttrList  *attrlist = create_pango_attrlist (str, attrs);
 
2910
 
 
2911
    scim_string_view_set_attributes (SCIM_STRING_VIEW (_preedit_area), attrlist);
 
2912
    scim_string_view_set_text (SCIM_STRING_VIEW (_preedit_area), str.c_str ());
 
2913
 
 
2914
    pango_attr_list_unref (attrlist);
 
2915
 
 
2916
    ui_settle_input_window (true);
 
2917
 
 
2918
    ui_settle_lookup_table_window ();
 
2919
}
 
2920
 
 
2921
static void
 
2922
slot_update_preedit_caret (int caret)
 
2923
{
 
2924
    scim_string_view_set_position (SCIM_STRING_VIEW (_preedit_area), caret);
 
2925
}
 
2926
 
 
2927
static void
 
2928
slot_update_aux_string (const String &str, const AttributeList &attrs)
 
2929
{
 
2930
    PangoAttrList  *attrlist = create_pango_attrlist (str, attrs);
 
2931
 
 
2932
    scim_string_view_set_attributes (SCIM_STRING_VIEW (_aux_area), attrlist);
 
2933
    scim_string_view_set_text (SCIM_STRING_VIEW (_aux_area), str.c_str ());
 
2934
 
 
2935
    pango_attr_list_unref (attrlist);
 
2936
 
 
2937
    ui_settle_input_window (true);
 
2938
 
 
2939
    ui_settle_lookup_table_window ();
 
2940
}
 
2941
 
 
2942
static void
 
2943
slot_update_lookup_table (const LookupTable &table)
 
2944
{
 
2945
    size_t i;
 
2946
    size_t item_num = table.get_current_page_size ();
 
2947
 
 
2948
    String         mbs;
 
2949
    WideString     wcs;
 
2950
    WideString     label;
 
2951
    GtkRequisition size;
 
2952
    AttributeList  attrs;
 
2953
    PangoAttrList  *attrlist;
 
2954
 
 
2955
    if (_lookup_table_vertical) {
 
2956
        for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++ i) {
 
2957
            if (i < item_num) {
 
2958
                mbs = String ();
 
2959
 
 
2960
                wcs = table.get_candidate_in_current_page (i);
 
2961
 
 
2962
                label = table.get_candidate_label (i);
 
2963
 
 
2964
                if (label.length ()) {
 
2965
                    label += utf8_mbstowcs (". ");
 
2966
                } else {
 
2967
                    label = utf8_mbstowcs (" ");
 
2968
                }
 
2969
 
 
2970
                mbs = utf8_wcstombs (label+wcs);
 
2971
 
 
2972
                scim_string_view_set_text (SCIM_STRING_VIEW (_lookup_table_items [i]),
 
2973
                                           mbs.c_str ());
 
2974
 
 
2975
                // Update attributes;
 
2976
                attrs = table.get_attributes_in_current_page (i);
 
2977
 
 
2978
                if (attrs.size ()) {
 
2979
                    for (AttributeList::iterator ait = attrs.begin (); ait != attrs.end (); ++ait)
 
2980
                        ait->set_start (ait->get_start () + label.length ());
 
2981
 
 
2982
                    attrlist = create_pango_attrlist (mbs, attrs);
 
2983
                    scim_string_view_set_attributes (SCIM_STRING_VIEW (_lookup_table_items [i]), attrlist);
 
2984
                    pango_attr_list_unref (attrlist);
 
2985
                } else {
 
2986
                    scim_string_view_set_attributes (SCIM_STRING_VIEW (_lookup_table_items [i]), 0);
 
2987
                }
 
2988
 
 
2989
                if (i == table.get_cursor_pos_in_current_page () && table.is_cursor_visible ())
 
2990
                    scim_string_view_set_highlight (SCIM_STRING_VIEW (_lookup_table_items [i]),
 
2991
                                                    0, wcs.length () + 3);
 
2992
                else
 
2993
                    scim_string_view_set_highlight (SCIM_STRING_VIEW (_lookup_table_items [i]),
 
2994
                                                    -1, -1);
 
2995
 
 
2996
                gtk_widget_show (_lookup_table_items [i]);
 
2997
            } else {
 
2998
                gtk_widget_hide (_lookup_table_items [i]);
 
2999
            }
 
3000
        }
 
3001
    } else {
 
3002
        _lookup_table_index [0] = 0;
 
3003
        for (i=0; i<SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
 
3004
            if (i<item_num) {
 
3005
                // Update attributes
 
3006
                AttributeList item_attrs = table.get_attributes_in_current_page (i);
 
3007
                size_t attr_start, attr_end;
 
3008
 
 
3009
                label = table.get_candidate_label (i);
 
3010
 
 
3011
                if (label.length ()) {
 
3012
                    label += utf8_mbstowcs (".");
 
3013
                }
 
3014
 
 
3015
                wcs += label;
 
3016
 
 
3017
                attr_start = wcs.length ();
 
3018
 
 
3019
                wcs += table.get_candidate_in_current_page (i);
 
3020
 
 
3021
                attr_end = wcs.length ();
 
3022
 
 
3023
                wcs.push_back (0x20);
 
3024
 
 
3025
                _lookup_table_index [i+1] = wcs.length ();
 
3026
 
 
3027
                mbs = utf8_wcstombs (wcs);
 
3028
 
 
3029
                scim_string_view_set_text (SCIM_STRING_VIEW (_lookup_table_items [0]),
 
3030
                                           mbs.c_str ());
 
3031
 
 
3032
                gtk_widget_size_request (_lookup_table_window, &size);
 
3033
 
 
3034
                if (size.width >= ui_screen_width () / 3 && !table.is_page_size_fixed ()) {
 
3035
                    item_num = i+1;
 
3036
                }
 
3037
 
 
3038
                if (item_attrs.size ()) {
 
3039
                    for (AttributeList::iterator ait = item_attrs.begin (); ait != item_attrs.end (); ++ait) {
 
3040
                        ait->set_start (ait->get_start () + attr_start);
 
3041
                        if (ait->get_end () + attr_start > attr_end)
 
3042
                            ait->set_length (attr_end - ait->get_start ());
 
3043
                    }
 
3044
 
 
3045
                    attrs.insert (attrs.end (), item_attrs.begin (), item_attrs.end ());
 
3046
                }
 
3047
 
 
3048
            } else {
 
3049
                _lookup_table_index [i+1] = -1;
 
3050
            }
 
3051
        }
 
3052
 
 
3053
        if (attrs.size ()) {
 
3054
            attrlist = create_pango_attrlist (mbs, attrs);
 
3055
            scim_string_view_set_attributes (SCIM_STRING_VIEW (_lookup_table_items [0]), attrlist);
 
3056
            pango_attr_list_unref (attrlist);
 
3057
        } else {
 
3058
            scim_string_view_set_attributes (SCIM_STRING_VIEW (_lookup_table_items [0]), 0);
 
3059
        }
 
3060
 
 
3061
        if (table.is_cursor_visible ()) {
 
3062
            int start = _lookup_table_index [table.get_cursor_pos_in_current_page ()];
 
3063
            int end = _lookup_table_index [table.get_cursor_pos_in_current_page ()+1] - 1;
 
3064
            scim_string_view_set_highlight (SCIM_STRING_VIEW (_lookup_table_items [0]), start, end);
 
3065
        } else {
 
3066
            scim_string_view_set_highlight (SCIM_STRING_VIEW (_lookup_table_items [0]), -1, -1);
 
3067
        }
 
3068
    }
 
3069
 
 
3070
    if (table.get_current_page_start ())
 
3071
        gtk_widget_set_sensitive (_lookup_table_up_button, TRUE);
 
3072
    else
 
3073
        gtk_widget_set_sensitive (_lookup_table_up_button, FALSE);
 
3074
 
 
3075
    if (table.get_current_page_start () + item_num < table.number_of_candidates ())
 
3076
        gtk_widget_set_sensitive (_lookup_table_down_button, TRUE);
 
3077
    else
 
3078
        gtk_widget_set_sensitive (_lookup_table_down_button, FALSE);
 
3079
 
 
3080
    if (item_num < table.get_current_page_size ())
 
3081
        _panel_agent->update_lookup_table_page_size (item_num);
 
3082
 
 
3083
    if (_lookup_table_embedded)
 
3084
        ui_settle_input_window (true);
 
3085
    else
 
3086
        ui_settle_lookup_table_window ();
 
3087
}
 
3088
 
 
3089
static void
 
3090
slot_register_properties (const PropertyList &props)
 
3091
{
 
3092
    register_frontend_properties (props);
 
3093
}
 
3094
 
 
3095
static void
 
3096
slot_update_property (const Property &prop)
 
3097
{
 
3098
    update_frontend_property (prop);
 
3099
}
 
3100
 
 
3101
static void
 
3102
slot_register_helper_properties (int id, const PropertyList &props)
 
3103
{
 
3104
    register_helper_properties (id, props);
 
3105
}
 
3106
 
 
3107
static void
 
3108
slot_update_helper_property (int id, const Property &prop)
 
3109
{
 
3110
    update_helper_property (id, prop);
 
3111
}
 
3112
 
 
3113
static void
 
3114
slot_register_helper (int id, const HelperInfo &helper)
 
3115
{
 
3116
}
 
3117
 
 
3118
static void
 
3119
slot_remove_helper (int id)
 
3120
{
 
3121
    HelperPropertyRepository::iterator it = _helper_property_repository.find (id);
 
3122
 
 
3123
    if (it != _helper_property_repository.end () && it->second.holder)
 
3124
        gtk_widget_destroy (it->second.holder);
 
3125
 
 
3126
    _helper_property_repository.erase (id);
 
3127
}
 
3128
 
 
3129
static void
 
3130
slot_lock (void)
 
3131
{
 
3132
    G_LOCK (_panel_agent_lock);
 
3133
}
 
3134
 
 
3135
static void
 
3136
slot_unlock (void)
 
3137
{
 
3138
    G_UNLOCK (_panel_agent_lock);
 
3139
}
 
3140
//////////////////////////////////////////////////////////////////////
 
3141
// End of PanelAgent-Functions
 
3142
//////////////////////////////////////////////////////////////////////
 
3143
 
 
3144
static GtkWidget *
 
3145
create_properties_node (PropertyRepository           &repository,
 
3146
                        PropertyList::const_iterator  begin,
 
3147
                        PropertyList::const_iterator  end,
 
3148
                        int                           client,
 
3149
                        int                           level)
 
3150
{
 
3151
    PropertyList::const_iterator it;
 
3152
    PropertyList::const_iterator next;
 
3153
 
 
3154
    GtkWidget * node;
 
3155
    PropertyInfo info;
 
3156
    bool leaf = true;
 
3157
 
 
3158
    if (begin >= end) return 0;
 
3159
 
 
3160
    // If the level is zero, then create the this node as button, otherwise create as a menu item.
 
3161
    if (!level) {
 
3162
        GtkWidget * label = ui_create_label (begin->get_label (),
 
3163
                                             begin->get_icon (),
 
3164
                                             0,
 
3165
                                             !_toolbar_show_property_label,
 
3166
                                             false);
 
3167
 
 
3168
        node = gtk_button_new ();
 
3169
        gtk_container_add (GTK_CONTAINER (node), label);
 
3170
        gtk_button_set_relief (GTK_BUTTON (node), GTK_RELIEF_NONE);
 
3171
    } else {
 
3172
        gint width, height;
 
3173
        gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
 
3174
        GtkWidget * icon = ui_create_icon (begin->get_icon (), NULL, width, height, false);
 
3175
        node = gtk_image_menu_item_new_with_label (begin->get_label ().c_str ());
 
3176
        if (icon)
 
3177
            gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (node), icon);
 
3178
    }
 
3179
 
 
3180
    if (begin->visible ())
 
3181
        gtk_widget_show (node);
 
3182
    else
 
3183
        gtk_widget_hide (node);
 
3184
 
 
3185
    gtk_widget_set_sensitive (node, begin->active ());
 
3186
 
 
3187
    if (_tooltips && begin->get_tip ().length ())
 
3188
        gtk_tooltips_set_tip (_tooltips, node, begin->get_tip ().c_str (), NULL);
 
3189
 
 
3190
    g_object_set_data_full (G_OBJECT (node), "property_key", g_strdup (begin->get_key ().c_str ()), g_free);
 
3191
 
 
3192
    info.property = *begin;
 
3193
    info.widget = node;
 
3194
 
 
3195
    repository.push_back (info);
 
3196
 
 
3197
    it = begin + 1;
 
3198
 
 
3199
    if (it != end) {
 
3200
        GtkWidget * submenu = gtk_menu_new ();
 
3201
        GtkWidget * child;
 
3202
        int menu_item_idx = 0;
 
3203
 
 
3204
        // Create all leafs of the first child.
 
3205
        while (it != end) {
 
3206
            // Find all leafs of the first child.
 
3207
            for (next = it + 1; next != end; ++ next)
 
3208
                if (!next->is_a_leaf_of (*it)) break;
 
3209
 
 
3210
            child = create_properties_node (repository, it, next, client, level + 1);
 
3211
            if (child) {
 
3212
                gtk_menu_shell_append (GTK_MENU_SHELL (submenu), child);
 
3213
                g_object_set_data (G_OBJECT (child), "menu_item_idx", GINT_TO_POINTER (menu_item_idx));
 
3214
                ++ menu_item_idx;
 
3215
            }
 
3216
 
 
3217
            it = next;
 
3218
        }
 
3219
 
 
3220
        // The node is a button, so attach the submenu as its data.
 
3221
        if (!level) {
 
3222
            g_object_set_data_full (G_OBJECT (node), "property_submenu", submenu, (void (*)(void*)) gtk_widget_destroy);
 
3223
 
 
3224
            g_signal_connect (G_OBJECT (submenu), "deactivate",
 
3225
                              G_CALLBACK (ui_property_menu_deactivate_cb),
 
3226
                              NULL);
 
3227
        } else // The node is a menu item, so attach the submenu directly.
 
3228
            gtk_menu_item_set_submenu (GTK_MENU_ITEM (node), submenu);
 
3229
 
 
3230
        leaf = false;
 
3231
    }
 
3232
 
 
3233
    if (leaf || level == 0) {
 
3234
        g_signal_connect (G_OBJECT (node),
 
3235
                          ((level > 0) ? "activate" : "clicked"),
 
3236
                          G_CALLBACK (ui_property_activate_cb),
 
3237
                          GINT_TO_POINTER (client));
 
3238
    }
 
3239
 
 
3240
    return node;
 
3241
}
 
3242
 
 
3243
static void
 
3244
create_properties (GtkWidget *container,
 
3245
                   PropertyRepository &repository,
 
3246
                   const PropertyList &properties,
 
3247
                   int client,
 
3248
                   int level)
 
3249
{
 
3250
 
 
3251
    PropertyList::const_iterator it;
 
3252
    PropertyList::const_iterator next;
 
3253
    PropertyList::const_iterator begin = properties.begin ();
 
3254
    PropertyList::const_iterator end = properties.end ();
 
3255
 
 
3256
    GtkWidget *root;
 
3257
 
 
3258
    int menu_item_idx = 0;
 
3259
 
 
3260
    if (begin == end) return;
 
3261
 
 
3262
    root = gtk_hbox_new (FALSE, 0);
 
3263
 
 
3264
    it = begin;
 
3265
    next = begin + 1;
 
3266
 
 
3267
    while (it != end) {
 
3268
        if (next == end || !next->is_a_leaf_of (*it)) {
 
3269
            GtkWidget * node = create_properties_node (repository, it, next, client, level);
 
3270
 
 
3271
            if (node) {
 
3272
                // The container is a hbox.
 
3273
                if (!level)
 
3274
                    gtk_box_pack_start (GTK_BOX (container), node, TRUE, TRUE, 0);
 
3275
                // The container is a menu.
 
3276
                else {
 
3277
                    gtk_menu_shell_append (GTK_MENU_SHELL (container), node);
 
3278
                    g_object_set_data (G_OBJECT (node), "menu_item_idx", GINT_TO_POINTER (menu_item_idx));
 
3279
                    ++ menu_item_idx;
 
3280
                }
 
3281
            }
 
3282
            it = next;
 
3283
        }
 
3284
        ++ next;
 
3285
    }
 
3286
}
 
3287
 
 
3288
static void
 
3289
register_frontend_properties (const PropertyList &properties)
 
3290
{
 
3291
    bool same = true;
 
3292
 
 
3293
    PropertyList::const_iterator pit = properties.begin ();
 
3294
 
 
3295
    if (properties.size () == 0) {
 
3296
        same = false;
 
3297
    } else if (properties.size () == _frontend_property_repository.size ()) {
 
3298
        // Check if the properties are same as old ones.
 
3299
        PropertyRepository::iterator it = _frontend_property_repository.begin ();
 
3300
 
 
3301
        for (; it != _frontend_property_repository.end (); ++it, ++pit) {
 
3302
            if (it->property != *pit) {
 
3303
                same = false;
 
3304
                break;
 
3305
            }
 
3306
        }
 
3307
    } else {
 
3308
        same = false;
 
3309
    }
 
3310
 
 
3311
    // Only update the properties.
 
3312
    if (same) {
 
3313
        for (pit = properties.begin (); pit != properties.end (); ++pit)
 
3314
            update_frontend_property (*pit);
 
3315
 
 
3316
        gtk_widget_show (_frontend_properties_area);
 
3317
    } else { // Construct all properties.
 
3318
        if (_frontend_properties_area)
 
3319
            gtk_widget_destroy (_frontend_properties_area);
 
3320
 
 
3321
        _frontend_properties_area = 0;
 
3322
 
 
3323
        _frontend_property_repository.clear ();
 
3324
 
 
3325
        if (properties.size ()) {
 
3326
            _frontend_properties_area = gtk_hbox_new (FALSE, 0);
 
3327
 
 
3328
            create_properties (_frontend_properties_area,
 
3329
                               _frontend_property_repository,
 
3330
                               properties,
 
3331
                               -1,
 
3332
                               0);
 
3333
 
 
3334
            gtk_widget_show (_frontend_properties_area);
 
3335
 
 
3336
            gtk_box_pack_start (GTK_BOX (_client_properties_area), _frontend_properties_area, TRUE,TRUE, 0);
 
3337
        }
 
3338
    }
 
3339
 
 
3340
    ui_settle_toolbar_window ();
 
3341
}
 
3342
 
 
3343
static void
 
3344
update_frontend_property (const Property &property)
 
3345
{
 
3346
    update_property (_frontend_property_repository, property);
 
3347
}
 
3348
 
 
3349
static void
 
3350
register_helper_properties (int client, const PropertyList &properties)
 
3351
{
 
3352
    HelperPropertyRepository::iterator it = _helper_property_repository.find (client);
 
3353
 
 
3354
    if (it == _helper_property_repository.end ()) {
 
3355
        _helper_property_repository [client] = HelperPropertyInfo ();
 
3356
        it = _helper_property_repository.find (client);
 
3357
    }
 
3358
 
 
3359
    if (it->second.holder)
 
3360
        gtk_widget_destroy (it->second.holder);
 
3361
 
 
3362
    it->second.holder = 0;
 
3363
 
 
3364
    if (properties.size ()) {
 
3365
        it->second.holder = gtk_hbox_new (FALSE, 0);
 
3366
 
 
3367
        create_properties (it->second.holder,
 
3368
                           it->second.repository,
 
3369
                           properties,
 
3370
                           client,
 
3371
                           0);
 
3372
 
 
3373
        gtk_widget_show (it->second.holder);
 
3374
        gtk_box_pack_end (GTK_BOX (_client_properties_area), it->second.holder, TRUE,TRUE, 0);
 
3375
    }
 
3376
 
 
3377
    ui_settle_toolbar_window ();
 
3378
}
 
3379
 
 
3380
static void
 
3381
update_helper_property (int client, const Property &property)
 
3382
{
 
3383
    update_property (_helper_property_repository [client].repository, property);
 
3384
}
 
3385
 
 
3386
static void
 
3387
update_property (PropertyRepository &repository,
 
3388
                 const Property       &property)
 
3389
{
 
3390
    PropertyRepository::iterator it = repository.begin ();
 
3391
 
 
3392
    for (; it != repository.end (); ++ it) {
 
3393
        if (it->property == property) {
 
3394
 
 
3395
            if (!it->widget) break;
 
3396
 
 
3397
            if (it->property.get_label () != property.get_label () ||
 
3398
                it->property.get_icon () != property.get_icon ()) {
 
3399
                if (GTK_IS_BUTTON (it->widget)) {
 
3400
                    GtkWidget *label = ui_create_label (property.get_label (),
 
3401
                                                        property.get_icon (),
 
3402
                                                        0,
 
3403
                                                        !_toolbar_show_property_label,
 
3404
                                                        false);
 
3405
                    GtkWidget *old = gtk_bin_get_child (GTK_BIN (it->widget));
 
3406
                    gtk_container_remove (GTK_CONTAINER (it->widget), old);
 
3407
                    gtk_container_add (GTK_CONTAINER (it->widget), label);
 
3408
                } else if (GTK_IS_MENU_ITEM (it->widget)) {
 
3409
                    gint width, height;
 
3410
                    gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
 
3411
 
 
3412
                    GtkWidget * menu = gtk_widget_get_parent (it->widget);
 
3413
                    int menu_item_idx = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (it->widget), "menu_item_idx"));
 
3414
 
 
3415
                    GtkWidget * icon = ui_create_icon (property.get_icon (), NULL, width, height, false);
 
3416
                    GtkWidget * new_item = gtk_image_menu_item_new_with_label (property.get_label ().c_str ());
 
3417
 
 
3418
                    gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (new_item), icon);
 
3419
 
 
3420
                    GtkWidget * submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (it->widget));
 
3421
 
 
3422
                    gtk_menu_item_set_submenu (GTK_MENU_ITEM (new_item), submenu);
 
3423
 
 
3424
                    g_object_set_data_full (G_OBJECT (new_item), "property_key", g_strdup (property.get_key ().c_str ()), g_free);
 
3425
                    g_object_set_data (G_OBJECT (new_item), "menu_item_idx", GINT_TO_POINTER (menu_item_idx));
 
3426
 
 
3427
                    gtk_widget_destroy (it->widget);
 
3428
 
 
3429
                    it->widget = new_item;
 
3430
                    gtk_menu_shell_insert (GTK_MENU_SHELL (menu), new_item, menu_item_idx);
 
3431
                }
 
3432
            }
 
3433
 
 
3434
            if (property.visible ())
 
3435
                gtk_widget_show (it->widget);
 
3436
            else
 
3437
                gtk_widget_hide (it->widget);
 
3438
 
 
3439
            gtk_widget_set_sensitive (it->widget, property.active ());
 
3440
 
 
3441
            if (_tooltips && property.get_tip ().length ())
 
3442
                gtk_tooltips_set_tip (_tooltips, it->widget, property.get_tip ().c_str (), NULL);
 
3443
 
 
3444
            it->property = property;
 
3445
            break;
 
3446
        }
 
3447
    }
 
3448
    ui_settle_toolbar_window ();
 
3449
}
 
3450
 
 
3451
static void
 
3452
restore_properties (void)
 
3453
{
 
3454
    PropertyList properties;
 
3455
 
 
3456
    _frontend_properties_area = 0;
 
3457
 
 
3458
    PropertyRepository::iterator it = _frontend_property_repository.begin ();
 
3459
    HelperPropertyRepository::iterator helper_it = _helper_property_repository.begin ();
 
3460
 
 
3461
    for (; it != _frontend_property_repository.end (); ++it)
 
3462
        properties.push_back (it->property);
 
3463
 
 
3464
    if (properties.size ()) {
 
3465
        _frontend_property_repository.clear ();
 
3466
        register_frontend_properties (properties);
 
3467
    }
 
3468
 
 
3469
    for (; helper_it != _helper_property_repository.end (); ++ helper_it) {
 
3470
 
 
3471
        helper_it->second.holder = 0;
 
3472
 
 
3473
        properties.clear ();
 
3474
 
 
3475
        for (it = helper_it->second.repository.begin (); it != helper_it->second.repository.end (); ++it)
 
3476
            properties.push_back (it->property);
 
3477
 
 
3478
        if (properties.size ()) {
 
3479
            helper_it->second.repository.clear ();
 
3480
            register_helper_properties (helper_it->first, properties);
 
3481
        }
 
3482
    }
 
3483
}
 
3484
 
 
3485
static gboolean
 
3486
check_exit_timeout_cb (gpointer data)
 
3487
{
 
3488
    G_LOCK (_global_resource_lock);
 
3489
    if (_should_exit) {
 
3490
        gdk_threads_enter ();
 
3491
        gtk_main_quit ();
 
3492
        gdk_threads_leave ();
 
3493
    }
 
3494
    G_UNLOCK (_global_resource_lock);
 
3495
 
 
3496
    return TRUE;
 
3497
}
 
3498
 
 
3499
static void
 
3500
signalhandler(int sig)
 
3501
{
 
3502
    SCIM_DEBUG_MAIN (1) << "In signal handler...\n";
 
3503
    if (_panel_agent != NULL) {
 
3504
        _panel_agent->stop ();
 
3505
    }
 
3506
}
 
3507
 
 
3508
int main (int argc, char *argv [])
 
3509
{
 
3510
    std::vector<String>  config_list;
 
3511
 
 
3512
    int i;
 
3513
 
 
3514
    bool daemon = false;
 
3515
 
 
3516
    int    new_argc = 0;
 
3517
    char **new_argv = new char * [40];
 
3518
 
 
3519
    String config_name ("simple");
 
3520
    String display_name;
 
3521
    bool should_resident = true;
 
3522
 
 
3523
    //Display version info
 
3524
    std::cerr << "GTK Panel of SCIM " << SCIM_VERSION << "\n\n";
 
3525
 
 
3526
    //get modules list
 
3527
    scim_get_config_module_list (config_list);
 
3528
 
 
3529
    //Add a dummy config module, it's not really a module!
 
3530
    config_list.push_back ("dummy");
 
3531
 
 
3532
    //Use socket Config module as default if available.
 
3533
    if (config_list.size ()) {
 
3534
        if (std::find (config_list.begin (),
 
3535
                       config_list.end (),
 
3536
                       config_name) == config_list.end ())
 
3537
            config_name = config_list [0];
 
3538
    }
 
3539
 
 
3540
    DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
 
3541
    DebugOutput::enable_debug (SCIM_DEBUG_MainMask);
 
3542
 
 
3543
    //parse command options
 
3544
    i = 0;
 
3545
    while (i<argc) {
 
3546
        if (++i >= argc) break;
 
3547
 
 
3548
        if (String ("-l") == argv [i] ||
 
3549
            String ("--list") == argv [i]) {
 
3550
            std::vector<String>::iterator it;
 
3551
 
 
3552
            std::cout << "\n";
 
3553
            std::cout << "Available Config module:\n";
 
3554
            for (it = config_list.begin (); it != config_list.end (); it++)
 
3555
                std::cout << "    " << *it << "\n";
 
3556
 
 
3557
            return 0;
 
3558
        }
 
3559
 
 
3560
        if (String ("-c") == argv [i] ||
 
3561
            String ("--config") == argv [i]) {
 
3562
            if (++i >= argc) {
 
3563
                std::cerr << "no argument for option " << argv [i-1] << "\n";
 
3564
                return -1;
 
3565
            }
 
3566
            config_name = argv [i];
 
3567
            continue;
 
3568
        }
 
3569
 
 
3570
        if (String ("-h") == argv [i] ||
 
3571
            String ("--help") == argv [i]) {
 
3572
            std::cout << "Usage: " << argv [0] << " [option]...\n\n"
 
3573
                 << "The options are: \n"
 
3574
                 << "  --display DISPLAY    Run on display DISPLAY.\n"
 
3575
                 << "  -l, --list           List all of available config modules.\n"
 
3576
                 << "  -c, --config NAME    Uses specified Config module.\n"
 
3577
                 << "  -d, --daemon         Run " << argv [0] << " as a daemon.\n"
 
3578
                 << "  -ns, --no-stay       Quit if no connected client.\n"
 
3579
#if ENABLE_DEBUG
 
3580
                 << "  -v, --verbose LEVEL  Enable debug info, to specific LEVEL.\n"
 
3581
                 << "  -o, --output FILE    Output debug information into FILE.\n"
 
3582
#endif
 
3583
                 << "  -h, --help           Show this help message.\n";
 
3584
            return 0;
 
3585
        }
 
3586
 
 
3587
        if (String ("-d") == argv [i] ||
 
3588
            String ("--daemon") == argv [i]) {
 
3589
            daemon = true;
 
3590
            continue;
 
3591
        }
 
3592
 
 
3593
        if (String ("-ns") == argv [i] ||
 
3594
            String ("--no-stay") == argv [i]) {
 
3595
            should_resident = false;
 
3596
            continue;
 
3597
        }
 
3598
 
 
3599
        if (String ("-v") == argv [i] ||
 
3600
            String ("--verbose") == argv [i]) {
 
3601
            if (++i >= argc) {
 
3602
                std::cerr << "no argument for option " << argv [i-1] << "\n";
 
3603
                return -1;
 
3604
            }
 
3605
            DebugOutput::set_verbose_level (atoi (argv [i]));
 
3606
            continue;
 
3607
        }
 
3608
 
 
3609
        if (String ("-o") == argv [i] ||
 
3610
            String ("--output") == argv [i]) {
 
3611
            if (++i >= argc) {
 
3612
                std::cerr << "No argument for option " << argv [i-1] << "\n";
 
3613
                return -1;
 
3614
            }
 
3615
            DebugOutput::set_output (argv [i]);
 
3616
            continue;
 
3617
        }
 
3618
 
 
3619
        if (String ("--display") == argv [i]) {
 
3620
            if (++i >= argc) {
 
3621
                std::cerr << "No argument for option " << argv [i-1] << "\n";
 
3622
                return -1;
 
3623
            }
 
3624
            display_name = argv [i]; 
 
3625
            continue;
 
3626
        }
 
3627
 
 
3628
        if (String ("--") == argv [i])
 
3629
            break;
 
3630
 
 
3631
        std::cerr << "Invalid command line option: " << argv [i] << "\n";
 
3632
        return -1;
 
3633
    } //End of command line parsing.
 
3634
 
 
3635
    new_argv [new_argc ++] = argv [0];
 
3636
 
 
3637
    // Store the rest argvs into new_argv.
 
3638
    for (++i; i < argc && new_argc < 40; ++i) {
 
3639
        new_argv [new_argc ++] = argv [i];
 
3640
    }
 
3641
 
 
3642
    // Make up DISPLAY env.
 
3643
    if (display_name.length ()) {
 
3644
        new_argv [new_argc ++] = const_cast <char*> ("--display");
 
3645
        new_argv [new_argc ++] = const_cast <char*> (display_name.c_str ());
 
3646
 
 
3647
        setenv ("DISPLAY", display_name.c_str (), 1);
 
3648
    }
 
3649
 
 
3650
    new_argv [new_argc] = 0;
 
3651
 
 
3652
    if (!config_name.length ()) {
 
3653
        std::cerr << "No Config module is available!\n";
 
3654
        return -1;
 
3655
    }
 
3656
 
 
3657
    if (config_name != "dummy") {
 
3658
        //load config module
 
3659
        _config_module = new ConfigModule (config_name);
 
3660
 
 
3661
        if (!_config_module || !_config_module->valid ()) {
 
3662
            std::cerr << "Can not load " << config_name << " Config module.\n";
 
3663
            return -1;
 
3664
        }
 
3665
 
 
3666
        //create config instance
 
3667
        _config = _config_module->create_config ();
 
3668
    } else {
 
3669
        _config = new DummyConfig ();
 
3670
    }
 
3671
 
 
3672
    if (_config.null ()) {
 
3673
        std::cerr << "Failed to create Config instance from "
 
3674
             << config_name << " Config module.\n";
 
3675
        return -1;
 
3676
    }
 
3677
 
 
3678
    /* init threads */
 
3679
    g_thread_init (NULL);
 
3680
    gdk_threads_init ();
 
3681
 
 
3682
    signal(SIGQUIT, signalhandler);
 
3683
    signal(SIGTERM, signalhandler);
 
3684
    signal(SIGINT,  signalhandler);
 
3685
    signal(SIGHUP,  signalhandler);
 
3686
 
 
3687
    gtk_init (&new_argc, &new_argv);
 
3688
 
 
3689
    ui_initialize ();
 
3690
 
 
3691
    // get current display.
 
3692
    {
 
3693
#if GDK_MULTIHEAD_SAFE
 
3694
        const char *p = gdk_display_get_name (gdk_display_get_default ());
 
3695
#else
 
3696
        const char *p = getenv ("DISPLAY");
 
3697
#endif
 
3698
        if (p) display_name = String (p);
 
3699
    }
 
3700
 
 
3701
    if (!initialize_panel_agent (config_name, display_name, should_resident)) {
 
3702
        std::cerr << "Failed to initialize Panel Agent!\n";
 
3703
        return -1;
 
3704
    }
 
3705
 
 
3706
    if (daemon)
 
3707
        scim_daemon ();
 
3708
 
 
3709
    // connect the configuration reload signal.
 
3710
    _config->signal_connect_reload (slot (ui_config_reload_callback));
 
3711
 
 
3712
    if (!run_panel_agent()) {
 
3713
        std::cerr << "Failed to run Socket Server!\n";
 
3714
        return -1;
 
3715
    }
 
3716
 
 
3717
    start_auto_start_helpers ();
 
3718
 
 
3719
    _check_exit_timeout = gtk_timeout_add (500, check_exit_timeout_cb, NULL);
 
3720
 
 
3721
    gdk_threads_enter ();
 
3722
    gtk_main ();
 
3723
    gdk_threads_leave ();
 
3724
 
 
3725
    // Exiting...
 
3726
    g_thread_join (_panel_agent_thread);
 
3727
    _config.reset ();
 
3728
 
 
3729
    std::cerr << "Successfully exited.\n";
 
3730
 
 
3731
    return 0;
 
3732
}
 
3733
 
 
3734
/*
 
3735
vi:ts=4:nowrap:expandtab
 
3736
*/