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

« back to all changes in this revision

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