1 /*
2  * Copyright (C) 2002-2006 Sergey V. Udaltsov <svu@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 
20 #ifndef __XKLAVIER_PRIVATE_H__
21 #define __XKLAVIER_PRIVATE_H__
22 
23 #include <stdio.h>
24 
25 #include <libxml/xpath.h>
26 
27 #include <libxklavier/xklavier.h>
28 
29 enum { WM_NAME,
30 	WM_STATE,
31 	XKLAVIER_STATE,
32 	XKLAVIER_TRANSPARENT,
33 	XKLAVIER_ALLOW_SECONDARY,
34 	TOTAL_ATOMS
35 };
36 
37 #define XKL_NUMBER_OF_REGISTRY_DOCS 2
38 
39 /* We have 3 values in XklEngineListenModes */
40 enum {
41 	XKLL_MANAGE_WINDOW_STATES_OFFSET = 0,
42 	XKLL_TRACK_KEYBOARD_STATE_OFFSET,
43 	XKLL_MANAGE_LAYOUTS_OFFSET,
44 	XKLL_NUMBER_OF_LISTEN_MODES
45 };
46 
47 
48 struct _XklEnginePrivate {
49 
50 	gboolean group_per_toplevel_window;
51 
52 	gboolean handle_indicators;
53 
54 	gboolean skip_one_restore;
55 
56 	gboolean skip_one_save;
57 
58 	gint default_group;
59 
60 	/*
61 	 * Separate counter for each of XklEngineListenModes!
62 	 */
63 	guchar listener_type_counters[XKLL_NUMBER_OF_LISTEN_MODES];
64 #define xkl_engine_is_listening_for(engine, type) (xkl_engine_priv((engine), listener_type_counters)[type##_OFFSET] > 0)
65 
66 	guint secondary_groups_mask;
67 
68 	Window root_window;
69 
70 	Window prev_toplvl_win;
71 
72 	Window curr_toplvl_win;
73 
74 	XErrorHandler default_error_handler;
75 
76 	Status last_error_code;
77 
78 	XklState curr_state;
79 
80 	gboolean critical_section;
81 
82 	Atom atoms[TOTAL_ATOMS];
83 
84 	Display *display;
85 
86 	/*
87 	 * Backend name
88 	 */
89 	const gchar *backend_id;
90 
91 	/*
92 	 * Functions supported by the backend, combination of XKLF_* constants
93 	 */
94 	guint8 features;
95 
96 	/*
97 	 * Activates the configuration.
98 	 * xkb: create proper the XkbDescRec and send it to the server
99 	 * xmodmap: save the property, init layout #1
100 	 */
101 	 gboolean(*activate_config_rec) (XklEngine * engine,
102 					 const XklConfigRec * data);
103 
104 	/*
105 	 * Background-specific initialization.
106 	 * xkb: XkbInitAtoms - init internal xkb atoms table
107 	 * xmodmap: void.
108 	 */
109 	void (*init_config_registry) (XklConfigRegistry * config);
110 
111 	/*
112 	 * Loads the registry tree into DOM (using whatever path(s))
113 	 * The XklVTConfigFreeRegistry is static - no virtualization necessary.
114 	 * xkb: loads xml from XKB_BASE+"/rules/"+ruleset+".xml"
115 	 * xmodmap: loads xml from XMODMAP_BASE+"/"+ruleset+".xml"
116 	 */
117 	 gboolean(*load_config_registry) (XklConfigRegistry * config,
118 					  gboolean if_extras_needed);
119 
120 	/*
121 	 * Write the configuration into the file (binary/textual)
122 	 * xkb: write xkb or xkm file
123 	 * xmodmap: if text requested, just dump XklConfigRec to the
124 	 * file - not really useful. If binary - fail (not supported)
125 	 */
126 	 gboolean(*write_config_rec_to_file) (XklEngine * engine,
127 					      const gchar * file_name,
128 					      const XklConfigRec * data,
129 					      const gboolean binary);
130 
131 	/*
132 	 * Get the list of the group names
133 	 * xkb: return cached list of the group names
134 	 * xmodmap: return the list of layouts from the internal XklConfigRec
135 	 */
136 	const gchar **(*get_groups_names) (XklEngine * engine);
137 
138 	/*
139 	 * Get the list of the indicators names
140 	 * xkb: return cached list of the indicators names
141 	 * xmodmap: return NULL
142 	 */
143 	const gchar **(*get_indicators_names) (XklEngine * engine);
144 
145 	/*
146 	 * Get the maximum number of loaded groups
147 	 * xkb: returns 1 or XkbNumKbdGroups
148 	 * xmodmap: return 0
149 	 */
150 	 guint(*get_max_num_groups) (XklEngine * engine);
151 
152 	/*
153 	 * Get the number of loaded groups
154 	 * xkb: return from the cached XkbDesc
155 	 * xmodmap: return number of layouts from internal XklConfigRec
156 	 */
157 	 guint(*get_num_groups) (XklEngine * engine);
158 
159 	/*
160 	 * Switches the keyboard to the group N
161 	 * xkb: simple one-liner to call the XKB function
162 	 * xmodmap: changes the root window property
163 	 * (listener invokes xmodmap with appropriate config file).
164 	 */
165 	void (*lock_group) (XklEngine * engine, gint group);
166 
167 	/*
168 	 * Handles X events.
169 	 * xkb: XkbEvent handling
170 	 * xmodmap: keep track on the root window properties. What else can we do?
171 	 */
172 	 gint(*process_x_event) (XklEngine * engine, XEvent * xev);
173 
174 	/*
175 	 * Handles X errors.
176 	 * return 0 if further processing is needed
177 	 *        1 if error was handled
178 	 */
179 	 gint(*process_x_error) (XklEngine * engine, XErrorEvent * xerev);
180 
181 	/*
182 	 * Flushes the cached server config info.
183 	 * xkb: frees XkbDesc
184 	 * xmodmap: frees internal XklConfigRec
185 	 */
186 	void (*free_all_info) (XklEngine * engine);
187 
188 	/*
189 	 * Compares the cached info with the actual one, from the server
190 	 * xkb: Compares some parts of XkbDescPtr
191 	 * xmodmap: returns False
192 	 */
193 	 gboolean(*if_cached_info_equals_actual) (XklEngine * engine);
194 
195 	/*
196 	 * Loads the configuration info from the server
197 	 * xkb: loads XkbDesc, names, indicators
198 	 * xmodmap: loads internal XklConfigRec from server
199 	 */
200 	 gboolean(*load_all_info) (XklEngine * engine);
201 
202 	/*
203 	 * Gets the current state
204 	 * xkb: XkbGetState and XkbGetIndicatorState
205 	 * xmodmap: check the root window property (regarding the group)
206 	 */
207 	void (*get_server_state) (XklEngine * engine,
208 				  XklState * current_state_out);
209 
210 	/*
211 	 * Stop tracking the keyboard-related events
212 	 * xkb: XkbSelectEvents(..., 0)
213 	 * xmodmap: Ungrab the switching shortcut.
214 	 */
215 	 gint(*pause_listen) (XklEngine * engine);
216 
217 	/*
218 	 * Start tracking the keyboard-related events
219 	 * xkb: XkbSelectEvents + XkbSelectEventDetails
220 	 * xmodmap: Grab the switching shortcut.
221 	 */
222 	 gint(*resume_listen) (XklEngine * engine);
223 
224 	/*
225 	 * Set the indicators state from the XklState
226 	 * xkb: XklSetIndicator for all indicators
227 	 * xmodmap: NULL. Not supported
228 	 */
229 	void (*set_indicators) (XklEngine * engine,
230 				const XklState * window_state);
231 
232 	/*
233 	 * Perform the cleanup
234 	 */
235 	void (*finalize) (XklEngine * engine);
236 
237 	/* all data is private - no direct access */
238 	/*
239 	 * The base configuration atom.
240 	 * xkb: _XKB_RF_NAMES_PROP_ATOM
241 	 * xmodmap:  "_XMM_NAMES"
242 	 */
243 	Atom base_config_atom;
244 
245 	/*
246 	 * The configuration backup atom
247 	 * xkb: "_XKB_RULES_NAMES_BACKUP"
248 	 * xmodmap: "_XMM_NAMES_BACKUP"
249 	 */
250 	Atom backup_config_atom;
251 
252 	/*
253 	 * Fallback for missing model
254 	 */
255 	const gchar *default_model;
256 
257 	/*
258 	 * Fallback for missing layout
259 	 */
260 	const gchar *default_layout;
261 
262 	/*
263 	 * Any stuff backend might need to put in here
264 	 */
265 	gpointer backend;
266 };
267 
268 extern XklEngine *xkl_get_the_engine(void);
269 
270 struct _XklConfigRegistryPrivate {
271 	XklEngine *engine;
272 
273 	xmlDocPtr docs[XKL_NUMBER_OF_REGISTRY_DOCS];
274 	xmlXPathContextPtr xpath_contexts[XKL_NUMBER_OF_REGISTRY_DOCS];
275 };
276 
277 extern void xkl_engine_ensure_vtable_inited(XklEngine * engine);
278 
279 extern void xkl_engine_process_focus_in_evt(XklEngine * engine,
280 					    XFocusChangeEvent * fev);
281 extern void xkl_engine_process_focus_out_evt(XklEngine * engine,
282 					     XFocusChangeEvent * fev);
283 extern void xkl_engine_process_property_evt(XklEngine * engine,
284 					    XPropertyEvent * rev);
285 extern void xkl_engine_process_create_window_evt(XklEngine * engine,
286 						 XCreateWindowEvent * cev);
287 
288 extern int xkl_process_error(Display * dpy, XErrorEvent * evt);
289 
290 extern void xkl_engine_process_state_modification(XklEngine * engine,
291 						  XklEngineStateChange
292 						  change_type, gint group,
293 						  unsigned inds,
294 						  gboolean set_indicators);
295 
296 extern Window xkl_engine_get_registered_parent(XklEngine * engine,
297 					       Window win);
298 extern void xkl_engine_reset_all_info(XklEngine * engine, gboolean force,
299 				      const gchar reason[]);
300 extern gboolean xkl_engine_load_window_tree(XklEngine * engine);
301 extern gboolean xkl_engine_load_subtree(XklEngine * engine, Window window,
302 					gint level, XklState * init_state);
303 
304 extern gboolean xkl_engine_if_window_has_wm_state(XklEngine * engine,
305 						  Window win);
306 
307 
308 /**
309  * Toplevel window stuff
310  */
311 extern void xkl_engine_add_toplevel_window(XklEngine * engine, Window win,
312 					   Window parent, gboolean force,
313 					   XklState * init_state);
314 
315 extern gboolean xkl_engine_find_toplevel_window_bottom_to_top(XklEngine *
316 							      engine,
317 							      Window win,
318 							      Window *
319 							      toplevel_win_out);
320 
321 extern gboolean xkl_engine_find_toplevel_window(XklEngine * engine,
322 						Window win,
323 						Window * toplevel_win_out);
324 
325 extern gboolean xkl_engine_is_toplevel_window_transparent(XklEngine *
326 							  engine,
327 							  Window
328 							  toplevel_win);
329 
330 extern void xkl_engine_set_toplevel_window_transparent(XklEngine * engine,
331 						       Window toplevel_win,
332 						       gboolean
333 						       transparent);
334 
335 extern gboolean xkl_engine_get_toplevel_window_state(XklEngine * engine,
336 						     Window toplevel_win,
337 						     XklState * state_out);
338 
339 extern void xkl_engine_remove_toplevel_window_state(XklEngine * engine,
340 						    Window toplevel_win);
341 extern void xkl_engine_save_toplevel_window_state(XklEngine * engine,
342 						  Window toplevel_win,
343 						  XklState * state);
344 /***/
345 
346 extern void xkl_engine_select_input_merging(XklEngine * engine, Window win,
347 					    gulong mask);
348 
349 extern gchar *xkl_get_debug_window_title(XklEngine * engine, Window win);
350 
351 extern Status xkl_engine_query_tree(XklEngine * engine,
352 				    Window w,
353 				    Window * root_out,
354 				    Window * parent_out,
355 				    Window ** children_out,
356 				    guint * nchildren_out);
357 
358 extern void xkl_engine_try_call_state_func(XklEngine * engine,
359 					   XklEngineStateChange
360 					   change_type,
361 					   XklState * old_state);
362 
363 extern gchar *xkl_engine_get_ruleset_name(XklEngine * engine,
364 					  const gchar default_ruleset[]);
365 
366 extern gboolean xkl_config_rec_get_full_from_server(gchar **
367 						    rules_file_out,
368 						    XklConfigRec * data,
369 						    XklEngine * engine);
370 
371 extern gchar *xkl_strings_concat_comma_separated(gchar ** array);
372 
373 extern void xkl_strings_split_comma_separated(gchar *** array,
374 					      const gchar * merged);
375 
376 /**
377  * XConfigRec
378  */
379 extern gchar *xkl_config_rec_merge_layouts(const XklConfigRec * data);
380 
381 extern gchar *xkl_config_rec_merge_variants(const XklConfigRec * data);
382 
383 extern gchar *xkl_config_rec_merge_options(const XklConfigRec * data);
384 
385 extern void xkl_config_rec_split_layouts(XklConfigRec * data,
386 					 const gchar * merged);
387 
388 extern void xkl_config_rec_split_variants(XklConfigRec * data,
389 					  const gchar * merged);
390 
391 extern void xkl_config_rec_split_options(XklConfigRec * data,
392 					 const gchar * merged);
393 /***/
394 
395 extern void xkl_config_rec_dump(FILE * file, XklConfigRec * data);
396 
397 extern const gchar *xkl_event_get_name(gint type);
398 
399 extern void xkl_engine_update_current_state(XklEngine * engine, gint group,
400 					    unsigned indicators,
401 					    const gchar reason[]);
402 
403 extern gint xkl_xkb_init(XklEngine * engine);
404 
405 extern gint xkl_xmm_init(XklEngine * engine);
406 
407 extern gboolean
408 xkl_engine_is_one_switch_to_secondary_group_allowed(XklEngine * engine);
409 
410 extern void xkl_engine_one_switch_to_secondary_group_performed(XklEngine *
411 							       engine);
412 
413 extern gboolean xkl_config_registry_load_from_file(XklConfigRegistry *
414 						   config,
415 						   const gchar * file_name,
416 						   gint docidx);
417 
418 extern void xkl_config_registry_free(XklConfigRegistry * config);
419 
420 extern gchar *xkl_locale_from_utf8(XklConfigRegistry * config,
421 				   const gchar * utf8string);
422 
423 extern gboolean xkl_config_registry_load_helper(XklConfigRegistry * config, const char
424 						default_ruleset[],
425 						const char base_dir[],
426 						gboolean if_extras_needed);
427 
428 #define XKLAVIER_STATE_PROP_LENGTH 2
429 
430 /* taken from XFree86 maprules.c */
431 #define XKB_RF_NAMES_PROP_MAXLEN 1024
432 
433 #define WINID_FORMAT "%lx"
434 
435 #define xkl_engine_priv(engine,member)  (engine)->priv->member
436 #define xkl_engine_backend(engine,type,member)  ((type*)((engine)->priv->backend))->member
437 #define xkl_engine_get_display(engine) (xkl_engine_priv(engine,display))
438 #define xkl_engine_vcall(engine,func)  (*(engine)->priv->func)
439 
440 #define xkl_config_registry_is_initialized(config) \
441   ( xkl_config_registry_priv(config,xpath_contexts[0]) != NULL )
442 
443 #define xkl_config_registry_priv(config,member)  (config)->priv->member
444 #define xkl_config_registry_get_engine(config) ((config)->priv->engine)
445 
446 #define XKBCR_MODEL_PATH "/xkbConfigRegistry/modelList/model"
447 #define XKBCR_LAYOUT_PATH "/xkbConfigRegistry/layoutList/layout"
448 #define XKBCR_VARIANT_PATH XKBCR_LAYOUT_PATH "/variantList/variant"
449 #define XKBCR_GROUP_PATH "/xkbConfigRegistry/optionList/group"
450 #define XKBCR_OPTION_PATH XKBCR_GROUP_PATH "/option"
451 
452 #define XML_TAG_DESCR "description"
453 #define XML_TAG_SHORT_DESCR "shortDescription"
454 #define XML_TAG_VENDOR "vendor"
455 #define XML_TAG_COUNTRY_LIST "countryList"
456 #define XML_TAG_LANGUAGE_LIST "languageList"
457 #define XML_TAG_ISO3166ID "iso3166Id"
458 #define XML_TAG_ISO639ID "iso639Id"
459 
460 extern void
461 
462 
463 
464 
465 
466 xkl_config_registry_foreach_in_xpath_with_param(XklConfigRegistry * config,
467 						const gchar * format,
468 						const gchar * value,
469 						XklConfigItemProcessFunc func,
470 						gpointer data);
471 
472 extern void xkl_config_registry_foreach_in_xpath(XklConfigRegistry *
473 						 config,
474 						 xmlXPathCompExprPtr
475 						 xpath_comp_expr,
476 						 XklConfigItemProcessFunc
477 						 func, gpointer data);
478 
479 extern gboolean xkl_read_config_item(XklConfigRegistry * config,
480 				     gint doc_index, xmlNodePtr iptr,
481 				     XklConfigItem * item);
482 
483 extern gint xkl_debug_level;
484 
485 extern const gchar *xkl_last_error_message;
486 
487 #endif
488