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

« back to all changes in this revision

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