~ubuntu-branches/ubuntu/raring/sunpinyin/raring

« back to all changes in this revision

Viewing changes to wrapper/xim/ic.c

  • Committer: Package Import Robot
  • Author(s): YunQiang Su
  • Date: 2012-03-30 15:31:55 UTC
  • mfrom: (1.1.3) (1.2.7 sid)
  • Revision ID: package-import@ubuntu.com-20120330153155-qgls77sogzgtg9zp
Tags: 2.0.3+git20120222-1
* Team upload: git snapshot 20120222.
   - fix breaks if LDFLAGS in environment contains
       multiple words (Closese #646001).
   - rm patches merged to upstream:
       append-os-environ-toenv.patch
       fix-ftbfs-on-sh.patch
       remove-10-candidate-words-limitation.patch
   - refresh disable-lm-dict-compile.patch.
* Bump stardard version to 3.9.3: no modify needed.
* add libsunpinyin3-dbg and python-sunpinyin packages.
* debian/compat to 9, multiarch it.
* rewrite debian/rules with dh 7 format.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2010 Mike Qin <mikeandmore@gmail.com>
 
3
 *
 
4
 * The contents of this file are subject to the terms of either the GNU Lesser
 
5
 * General Public License Version 2.1 only ("LGPL") or the Common Development and
 
6
 * Distribution License ("CDDL")(collectively, the "License"). You may not use this
 
7
 * file except in compliance with the License. You can obtain a copy of the CDDL at
 
8
 * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
 
9
 * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
 
10
 * specific language governing permissions and limitations under the License. When
 
11
 * distributing the software, include this License Header Notice in each file and
 
12
 * include the full text of the License in the License file as well as the
 
13
 * following notice:
 
14
 *
 
15
 * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
 
16
 * (CDDL)
 
17
 * For Covered Software in this distribution, this License shall be governed by the
 
18
 * laws of the State of California (excluding conflict-of-law provisions).
 
19
 * Any litigation relating to this License shall be subject to the jurisdiction of
 
20
 * the Federal Courts of the Northern District of California and the state courts
 
21
 * of the State of California, with venue lying in Santa Clara County, California.
 
22
 *
 
23
 * Contributor(s):
 
24
 *
 
25
 * If you wish your version of this file to be governed by only the CDDL or only
 
26
 * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
 
27
 * include this software in this distribution under the [CDDL or LGPL Version 2.1]
 
28
 * license." If you don't indicate a single choice of license, a recipient has the
 
29
 * option to distribute your version of this file under either the CDDL or the LGPL
 
30
 * Version 2.1, or to extend the choice of license to its licensees as provided
 
31
 * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
 
32
 * Version 2 license, then the option applies only if the new code is made subject
 
33
 * to such option by the copyright holder.
 
34
 */
 
35
 
 
36
#include <sys/types.h>
 
37
#include <sys/stat.h>
 
38
#include <unistd.h>
 
39
 
 
40
#include <X11/Xlib.h>
 
41
#include <X11/Xos.h>
 
42
#include <X11/Xfuncs.h>
 
43
#include <X11/Xutil.h>
 
44
#include <X11/Xatom.h>
 
45
 
 
46
#include "common.h"
 
47
#include "settings.h"
 
48
#include "ic.h"
 
49
#include "xmisc.h"
 
50
#include "xim.h"
 
51
 
 
52
static IC* icmaps[MAX_IC_NUM];
 
53
static IC ics[MAX_IC_NUM];
 
54
 
 
55
static size_t free_stack_sz = 0;
 
56
static IC* free_stack[MAX_IC_NUM];
 
57
 
 
58
static IC* current_ic;
 
59
 
 
60
// check if this ic is available
 
61
static int
 
62
__find_application_pid(Window w)
 
63
{
 
64
    if (w == DefaultRootWindow(dpy))
 
65
        return 0;
 
66
 
 
67
    Atom actual_type;
 
68
    int actual_format;
 
69
    unsigned long nitems;
 
70
    unsigned long bytes;
 
71
    unsigned char* prop;
 
72
    int status = XGetWindowProperty(
 
73
        dpy, w, XInternAtom(dpy, "_NET_WM_PID", True), 0,
 
74
        1024L, False, AnyPropertyType, &actual_type, &actual_format, &nitems,
 
75
        &bytes, (unsigned char**) &prop);
 
76
    if (status != 0) {
 
77
        if (status == BadRequest)
 
78
            return 0;
 
79
        return -1;
 
80
    }
 
81
    if (!prop) {
 
82
        Window parent;
 
83
        Window root;
 
84
        Window* children = NULL;
 
85
        unsigned int sz = 0;
 
86
        status = XQueryTree(dpy, w, &root, &parent, &children, &sz);
 
87
        if (status != 0) {
 
88
            if (status == BadRequest)
 
89
                return 0;
 
90
            return -1;
 
91
        }
 
92
        if (children)
 
93
            XFree(children);
 
94
        return __find_application_pid(parent);
 
95
    } else {
 
96
        // TODO: is this portable?
 
97
        return prop[1] * 256 + prop[0];
 
98
    }
 
99
}
 
100
 
 
101
static bool
 
102
__ic_available(IC* ic)
 
103
{
 
104
    int pid = __find_application_pid(ic->client_window);
 
105
    if (pid == -1)
 
106
        return false;
 
107
    if (pid == 0)
 
108
        return true;
 
109
    // verify if a process is running
 
110
    char path[256];
 
111
    snprintf(path, 255, "/proc/%d", pid);
 
112
    struct stat buf;
 
113
    if (stat(path, &buf) != 0) {
 
114
        LOG("GC can't catch the process %d", pid);
 
115
        return false;
 
116
    }
 
117
    if (!S_ISDIR(buf.st_mode)) {
 
118
        LOG("GC can't catch the process %d", pid);
 
119
        return false;
 
120
    }
 
121
    return true;
 
122
}
 
123
 
 
124
static void
 
125
__scan_all_ic()
 
126
{
 
127
    int i = 0;
 
128
    for (i = 0; i < MAX_IC_NUM; i++) {
 
129
        IC* ic = icmaps[i];
 
130
        if (ic == NULL)
 
131
            continue;
 
132
 
 
133
        if (__ic_available(ic) == false) {
 
134
            LOG("GC detected garbage %d", ic->icid);
 
135
            icmgr_destroy_ic(i);
 
136
        }
 
137
    }
 
138
}
 
139
 
 
140
static void
 
141
__reset_ic(IC* ic)
 
142
{
 
143
    int id = ic->icid;
 
144
    memset(ic, 0, sizeof(IC));
 
145
    ic->icid = id;
 
146
    ic->is_chn_punc = true;
 
147
}
 
148
 
 
149
void
 
150
icmgr_init(void)
 
151
{
 
152
    memset(ics, 0, sizeof(IC) * MAX_IC_NUM);
 
153
    int i;
 
154
    for (i = 0; i < MAX_IC_NUM; i++) {
 
155
        ics[i].icid = i;
 
156
        __reset_ic(&ics[i]);
 
157
 
 
158
        free_stack[free_stack_sz] = &ics[i];
 
159
        free_stack_sz++;
 
160
    }
 
161
    current_ic = NULL;
 
162
 
 
163
    icmgr_ui_init();
 
164
}
 
165
 
 
166
void
 
167
icmgr_finalize(void)
 
168
{
 
169
    memset(icmaps, 0, sizeof(IC*) * MAX_IC_NUM);
 
170
    current_ic = NULL;
 
171
}
 
172
 
 
173
 
 
174
IC*
 
175
icmgr_create_ic(int connect_id)
 
176
{
 
177
    static int created_cnt = 0;
 
178
 
 
179
    created_cnt++;
 
180
    if (created_cnt == GC_THRESHOLD || free_stack_sz < MAX_IC_NUM / 3) {
 
181
        __scan_all_ic();
 
182
        created_cnt = 0;
 
183
    }
 
184
 
 
185
    if (free_stack_sz == 0) {
 
186
        LOG("Error free stack empty!!");
 
187
        return NULL;
 
188
    }
 
189
 
 
190
    free_stack_sz--;
 
191
    IC* ic = free_stack[free_stack_sz];
 
192
 
 
193
    icmaps[ic->icid] = ic;
 
194
    __reset_ic(ic);
 
195
 
 
196
    /* icmgr_set_current(ic->icid); */
 
197
 
 
198
    ic->connect_id = connect_id;
 
199
 
 
200
    /* current_ic = ic; */
 
201
    return ic;
 
202
}
 
203
 
 
204
void
 
205
icmgr_destroy_ic(int icid)
 
206
{
 
207
    IC* ic = icmaps[icid];
 
208
    if (ic == NULL)
 
209
        return;
 
210
 
 
211
    memset(ic, 0, sizeof(IC));
 
212
    ic->icid = icid;
 
213
 
 
214
    icmaps[icid] = NULL;
 
215
 
 
216
    // return to free stack
 
217
    free_stack[free_stack_sz] = ic;
 
218
    free_stack_sz++;
 
219
 
 
220
    current_ic = NULL;
 
221
}
 
222
 
 
223
bool
 
224
icmgr_set_current(int icid)
 
225
{
 
226
    IC* ic = icmaps[icid];
 
227
    if (ic == NULL)
 
228
        return false;
 
229
    current_ic = ic;
 
230
    return true;
 
231
}
 
232
 
 
233
IC*
 
234
icmgr_get_current(void)
 
235
{
 
236
    return current_ic;
 
237
}
 
238
 
 
239
void
 
240
icmgr_toggle_english(void)
 
241
{
 
242
    if (current_ic) {
 
243
        current_ic->is_english = !current_ic->is_english;
 
244
    }
 
245
}
 
246
 
 
247
void
 
248
icmgr_toggle_full(void)
 
249
{
 
250
    if (current_ic) {
 
251
        current_ic->is_full = !current_ic->is_full;
 
252
    }
 
253
}
 
254
 
 
255
void
 
256
icmgr_toggle_punc(void)
 
257
{
 
258
    if (current_ic) {
 
259
        current_ic->is_chn_punc = !current_ic->is_chn_punc;
 
260
    }
 
261
}
 
262
 
 
263
IC*
 
264
icmgr_get(int icid)
 
265
{
 
266
    return icmaps[icid];
 
267
}
 
268
 
 
269
void
 
270
icmgr_clear_current(void)
 
271
{
 
272
    current_ic = NULL;
 
273
}
 
274
 
 
275
void
 
276
icmgr_refresh(void)
 
277
{
 
278
    if (current_ic == NULL) {
 
279
        icmgr_ui_refresh();
 
280
        return;
 
281
    }
 
282
 
 
283
    /* refresh preedit */
 
284
    if (current_ic->is_enabled) {
 
285
        if (current_ic->is_english && preedit_status())
 
286
            preedit_pause();
 
287
        else if (!current_ic->is_english && !preedit_status())
 
288
            preedit_go_on();
 
289
 
 
290
        preedit_set_full(current_ic->is_full);
 
291
        preedit_set_chinese_punc(current_ic->is_chn_punc);
 
292
    } else {
 
293
        preedit_pause();
 
294
    }
 
295
    icmgr_ui_refresh();
 
296
}
 
297
 
 
298
extern IC_UI icmgr_gtk;
 
299
extern IC_UI icmgr_skin;
 
300
 
 
301
static IC_UI* current_icmgr_ui = NULL;
 
302
 
 
303
static void
 
304
init_front_end()
 
305
{
 
306
    varchar skin_name;
 
307
    settings_get(SKIN_NAME, skin_name);
 
308
    if (strcmp(skin_name, "classic") == 0) {
 
309
        current_icmgr_ui = &icmgr_gtk;
 
310
    } else {
 
311
        current_icmgr_ui = &icmgr_skin;
 
312
    }
 
313
 
 
314
    if (!current_icmgr_ui->init(skin_name)) {
 
315
        fprintf(stderr, "Error init front end!\n");
 
316
        exit(-1);
 
317
    }
 
318
}
 
319
 
 
320
void
 
321
icmgr_ui_init(void)
 
322
{
 
323
    ui_tray_init();
 
324
    init_front_end();
 
325
}
 
326
 
 
327
void
 
328
icmgr_ui_refresh(void)
 
329
{
 
330
    ui_tray_refresh();
 
331
    if (current_icmgr_ui != NULL) {
 
332
        varchar skin_name;
 
333
        settings_get(SKIN_NAME, skin_name);
 
334
        if (strcmp(skin_name, current_icmgr_ui->get_name()) != 0) {
 
335
            current_icmgr_ui->dispose();
 
336
            init_front_end();
 
337
        }
 
338
        current_icmgr_ui->refresh();
 
339
    } else {
 
340
        init_front_end();
 
341
    }
 
342
}
 
343