Blame libxklavier/xklavier_xmm.c

Packit Service 93d855
/*
Packit Service 93d855
 * Copyright (C) 2002-2006 Sergey V. Udaltsov <svu@gnome.org>
Packit Service 93d855
 *
Packit Service 93d855
 * This library is free software; you can redistribute it and/or
Packit Service 93d855
 * modify it under the terms of the GNU Lesser General Public
Packit Service 93d855
 * License as published by the Free Software Foundation; either
Packit Service 93d855
 * version 2 of the License, or (at your option) any later version.
Packit Service 93d855
 *
Packit Service 93d855
 * This library is distributed in the hope that it will be useful,
Packit Service 93d855
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 93d855
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 93d855
 * Lesser General Public License for more details.
Packit Service 93d855
 *
Packit Service 93d855
 * You should have received a copy of the GNU Lesser General Public
Packit Service 93d855
 * License along with this library; if not, write to the
Packit Service 93d855
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit Service 93d855
 * Boston, MA 02111-1307, USA.
Packit Service 93d855
 */
Packit Service 93d855
Packit Service 93d855
#include <time.h>
Packit Service 93d855
#include <stdlib.h>
Packit Service 93d855
#include <string.h>
Packit Service 93d855
Packit Service 93d855
#include <X11/Xmd.h>
Packit Service 93d855
#include <X11/Xatom.h>
Packit Service 93d855
#include <X11/Xlib.h>
Packit Service 93d855
#include <X11/Xutil.h>
Packit Service 93d855
#include <X11/keysym.h>
Packit Service 93d855
Packit Service 93d855
#include "config.h"
Packit Service 93d855
Packit Service 93d855
#include "xklavier_private.h"
Packit Service 93d855
#include "xklavier_private_xmm.h"
Packit Service 93d855
Packit Service 93d855
#define SHORTCUT_OPTION_PREFIX "grp:"
Packit Service 93d855
Packit Service 93d855
const gchar **
Packit Service 93d855
xkl_xmm_get_groups_names(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	return (const gchar **) xkl_engine_backend(engine, XklXmm,
Packit Service 93d855
						   current_config).layouts;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
const gchar **
Packit Service 93d855
xkl_xmm_get_indicators_names(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	return NULL;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xmm_shortcuts_grab(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	const XmmShortcut *shortcut;
Packit Service 93d855
	const XmmSwitchOption *option =
Packit Service 93d855
	    xkl_xmm_shortcut_get_current(engine);
Packit Service 93d855
Packit Service 93d855
	xkl_debug(150, "Found shortcut option: %p\n", option);
Packit Service 93d855
	if (option == NULL)
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	shortcut = option->shortcuts;
Packit Service 93d855
	while (shortcut->keysym != XK_VoidSymbol) {
Packit Service 93d855
		int keycode =
Packit Service 93d855
		    XKeysymToKeycode(xkl_engine_get_display(engine),
Packit Service 93d855
				     shortcut->keysym);
Packit Service 93d855
		xkl_xmm_grab_ignoring_indicators(engine, keycode,
Packit Service 93d855
						 shortcut->modifiers);
Packit Service 93d855
		shortcut++;
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xmm_shortcuts_ungrab(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	const XmmShortcut *shortcut;
Packit Service 93d855
	const XmmSwitchOption *option =
Packit Service 93d855
	    xkl_xmm_shortcut_get_current(engine);
Packit Service 93d855
Packit Service 93d855
	if (option == NULL)
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	shortcut = option->shortcuts;
Packit Service 93d855
	while (shortcut->keysym != XK_VoidSymbol) {
Packit Service 93d855
		int keycode =
Packit Service 93d855
		    XKeysymToKeycode(xkl_engine_get_display(engine),
Packit Service 93d855
				     shortcut->keysym);
Packit Service 93d855
		xkl_xmm_ungrab_ignoring_indicators(engine, keycode,
Packit Service 93d855
						   shortcut->modifiers);
Packit Service 93d855
		shortcut++;
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
XmmSwitchOption *
Packit Service 93d855
xkl_xmm_shortcut_get_current(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	const gchar *option_name =
Packit Service 93d855
	    xkl_xmm_shortcut_get_current_option_name(engine);
Packit Service 93d855
Packit Service 93d855
	xkl_debug(150, "Configured switch option: [%s]\n", option_name);
Packit Service 93d855
Packit Service 93d855
	if (option_name == NULL)
Packit Service 93d855
		return NULL;
Packit Service 93d855
Packit Service 93d855
	return (XmmSwitchOption *)
Packit Service 93d855
	    g_hash_table_lookup(xkl_engine_backend
Packit Service 93d855
				(engine, XklXmm, switch_options),
Packit Service 93d855
				(gconstpointer) option_name);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
const gchar *
Packit Service 93d855
xkl_xmm_shortcut_get_current_option_name(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	gchar **option =
Packit Service 93d855
	    xkl_engine_backend(engine, XklXmm, current_config).options;
Packit Service 93d855
	if (option == NULL)
Packit Service 93d855
		return NULL;
Packit Service 93d855
Packit Service 93d855
	while (*option != NULL) {
Packit Service 93d855
		/* starts with "grp:" */
Packit Service 93d855
		if (strstr(*option, SHORTCUT_OPTION_PREFIX) != NULL) {
Packit Service 93d855
			return *option + sizeof SHORTCUT_OPTION_PREFIX - 1;
Packit Service 93d855
		}
Packit Service 93d855
		option++;
Packit Service 93d855
	}
Packit Service 93d855
	return NULL;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
const XmmSwitchOption *
Packit Service 93d855
xkl_xmm_find_switch_option(XklEngine * engine, gint keycode,
Packit Service 93d855
			   guint state, gint * current_shortcut_rv)
Packit Service 93d855
{
Packit Service 93d855
	const XmmSwitchOption *rv = xkl_xmm_shortcut_get_current(engine);
Packit Service 93d855
Packit Service 93d855
	if (rv != NULL) {
Packit Service 93d855
		const XmmShortcut *sc = rv->shortcuts;
Packit Service 93d855
		while (sc->keysym != XK_VoidSymbol) {
Packit Service 93d855
			if ((XKeysymToKeycode
Packit Service 93d855
			     (xkl_engine_get_display(engine),
Packit Service 93d855
			      sc->keysym) == keycode)
Packit Service 93d855
			    && ((state & sc->modifiers) == sc->modifiers)) {
Packit Service 93d855
				return rv;
Packit Service 93d855
			}
Packit Service 93d855
			sc++;
Packit Service 93d855
		}
Packit Service 93d855
	}
Packit Service 93d855
	return NULL;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gint
Packit Service 93d855
xkl_xmm_resume_listen(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_LAYOUTS))
Packit Service 93d855
		xkl_xmm_shortcuts_grab(engine);
Packit Service 93d855
	return 0;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gint
Packit Service 93d855
xkl_xmm_pause_listen(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	if (xkl_engine_is_listening_for(engine, XKLL_MANAGE_LAYOUTS))
Packit Service 93d855
		xkl_xmm_shortcuts_ungrab(engine);
Packit Service 93d855
	return 0;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
guint
Packit Service 93d855
xkl_xmm_get_max_num_groups(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	return 0;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
guint
Packit Service 93d855
xkl_xmm_get_num_groups(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	gint rv = 0;
Packit Service 93d855
	gchar **p =
Packit Service 93d855
	    xkl_engine_backend(engine, XklXmm, current_config).layouts;
Packit Service 93d855
	if (p != NULL)
Packit Service 93d855
		while (*p++ != NULL)
Packit Service 93d855
			rv++;
Packit Service 93d855
	return rv;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xmm_free_all_info(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	gchar *current_rules =
Packit Service 93d855
	    xkl_engine_backend(engine, XklXmm, current_rules);
Packit Service 93d855
	if (current_rules != NULL) {
Packit Service 93d855
		g_free(current_rules);
Packit Service 93d855
		current_rules = NULL;
Packit Service 93d855
		xkl_engine_backend(engine, XklXmm, current_rules) = NULL;
Packit Service 93d855
	}
Packit Service 93d855
	xkl_config_rec_reset(&xkl_engine_backend
Packit Service 93d855
			     (engine, XklXmm, current_config));
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xmm_if_cached_info_equals_actual(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	return FALSE;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
gboolean
Packit Service 93d855
xkl_xmm_load_all_info(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	return
Packit Service 93d855
	    xkl_config_rec_get_full_from_server(&xkl_engine_backend
Packit Service 93d855
						(engine, XklXmm,
Packit Service 93d855
						 current_rules),
Packit Service 93d855
						&xkl_engine_backend(engine,
Packit Service 93d855
								    XklXmm,
Packit Service 93d855
								    current_config),
Packit Service 93d855
						engine);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xmm_get_server_state(XklEngine * engine, XklState * state)
Packit Service 93d855
{
Packit Service 93d855
	unsigned char *propval = NULL;
Packit Service 93d855
	Atom actual_type;
Packit Service 93d855
	int actual_format;
Packit Service 93d855
	unsigned long bytes_remaining;
Packit Service 93d855
	unsigned long actual_items;
Packit Service 93d855
	int result;
Packit Service 93d855
Packit Service 93d855
	memset(state, 0, sizeof(*state));
Packit Service 93d855
Packit Service 93d855
	result =
Packit Service 93d855
	    XGetWindowProperty(xkl_engine_get_display(engine),
Packit Service 93d855
			       xkl_engine_priv(engine, root_window),
Packit Service 93d855
			       xkl_engine_backend(engine, XklXmm,
Packit Service 93d855
						  state_atom), 0L, 1L,
Packit Service 93d855
			       False, XA_INTEGER, &actual_type,
Packit Service 93d855
			       &actual_format, &actual_items,
Packit Service 93d855
			       &bytes_remaining, &propval);
Packit Service 93d855
Packit Service 93d855
	if (Success == result) {
Packit Service 93d855
		if (actual_format == 32 || actual_items == 1) {
Packit Service 93d855
			state->group = *(CARD32 *) propval;
Packit Service 93d855
		} else {
Packit Service 93d855
			xkl_debug(160,
Packit Service 93d855
				  "Could not get the xmodmap current group\n");
Packit Service 93d855
		}
Packit Service 93d855
		XFree(propval);
Packit Service 93d855
	} else {
Packit Service 93d855
		xkl_debug(160,
Packit Service 93d855
			  "Could not get the xmodmap current group: %d\n",
Packit Service 93d855
			  result);
Packit Service 93d855
	}
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xmm_actualize_group(XklEngine * engine, gint group)
Packit Service 93d855
{
Packit Service 93d855
	char cmd[1024];
Packit Service 93d855
	int res;
Packit Service 93d855
	const gchar *layout_name = NULL;
Packit Service 93d855
Packit Service 93d855
	if (xkl_xmm_get_num_groups(engine) < group)
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	layout_name =
Packit Service 93d855
	    xkl_engine_backend(engine, XklXmm,
Packit Service 93d855
			       current_config).layouts[group];
Packit Service 93d855
Packit Service 93d855
	g_snprintf(cmd, sizeof cmd,
Packit Service 93d855
		   "xmodmap %s/xmodmap.%s", XMODMAP_BASE, layout_name);
Packit Service 93d855
Packit Service 93d855
	res = system(cmd);
Packit Service 93d855
	if (res > 0) {
Packit Service 93d855
		xkl_debug(0, "xmodmap error %d\n", res);
Packit Service 93d855
	} else if (res < 0) {
Packit Service 93d855
		xkl_debug(0, "Could not execute xmodmap: %d\n", res);
Packit Service 93d855
	}
Packit Service 93d855
	XSync(xkl_engine_get_display(engine), False);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xmm_lock_group(XklEngine * engine, gint group)
Packit Service 93d855
{
Packit Service 93d855
	CARD32 propval;
Packit Service 93d855
	Display *display;
Packit Service 93d855
Packit Service 93d855
	if (xkl_xmm_get_num_groups(engine) < group)
Packit Service 93d855
		return;
Packit Service 93d855
Packit Service 93d855
	/* updating the status property */
Packit Service 93d855
	propval = group;
Packit Service 93d855
	display = xkl_engine_get_display(engine);
Packit Service 93d855
	XChangeProperty(display, xkl_engine_priv(engine, root_window),
Packit Service 93d855
			xkl_engine_backend(engine, XklXmm, state_atom),
Packit Service 93d855
			XA_INTEGER, 32, PropModeReplace,
Packit Service 93d855
			(unsigned char *) &propval, 1);
Packit Service 93d855
	XSync(display, False);
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xmm_set_indicators(XklEngine * engine, const XklState * window_state)
Packit Service 93d855
{
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
Packit Service 93d855
gint
Packit Service 93d855
xkl_xmm_init(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	Display *display;
Packit Service 93d855
Packit Service 93d855
	xkl_engine_priv(engine, backend_id) = "xmodmap";
Packit Service 93d855
	xkl_engine_priv(engine, features) =
Packit Service 93d855
	    XKLF_MULTIPLE_LAYOUTS_SUPPORTED |
Packit Service 93d855
	    XKLF_REQUIRES_MANUAL_LAYOUT_MANAGEMENT;
Packit Service 93d855
	xkl_engine_priv(engine, activate_config_rec) =
Packit Service 93d855
	    xkl_xmm_activate_config_rec;
Packit Service 93d855
	xkl_engine_priv(engine, init_config_registry) =
Packit Service 93d855
	    xkl_xmm_init_config_registry;
Packit Service 93d855
	xkl_engine_priv(engine, load_config_registry) =
Packit Service 93d855
	    xkl_xmm_load_config_registry;
Packit Service 93d855
	xkl_engine_priv(engine, write_config_rec_to_file) = NULL;
Packit Service 93d855
Packit Service 93d855
	xkl_engine_priv(engine, get_groups_names) =
Packit Service 93d855
	    xkl_xmm_get_groups_names;
Packit Service 93d855
	xkl_engine_priv(engine, get_indicators_names) =
Packit Service 93d855
	    xkl_xmm_get_indicators_names;
Packit Service 93d855
	xkl_engine_priv(engine, get_max_num_groups) =
Packit Service 93d855
	    xkl_xmm_get_max_num_groups;
Packit Service 93d855
	xkl_engine_priv(engine, get_num_groups) = xkl_xmm_get_num_groups;
Packit Service 93d855
	xkl_engine_priv(engine, lock_group) = xkl_xmm_lock_group;
Packit Service 93d855
Packit Service 93d855
	xkl_engine_priv(engine, process_x_event) = xkl_xmm_process_x_event;
Packit Service 93d855
	xkl_engine_priv(engine, process_x_error) = NULL;
Packit Service 93d855
	xkl_engine_priv(engine, free_all_info) = xkl_xmm_free_all_info;
Packit Service 93d855
	xkl_engine_priv(engine, if_cached_info_equals_actual) =
Packit Service 93d855
	    xkl_xmm_if_cached_info_equals_actual;
Packit Service 93d855
	xkl_engine_priv(engine, load_all_info) = xkl_xmm_load_all_info;
Packit Service 93d855
	xkl_engine_priv(engine, get_server_state) =
Packit Service 93d855
	    xkl_xmm_get_server_state;
Packit Service 93d855
	xkl_engine_priv(engine, pause_listen) = xkl_xmm_pause_listen;
Packit Service 93d855
	xkl_engine_priv(engine, resume_listen) = xkl_xmm_resume_listen;
Packit Service 93d855
	xkl_engine_priv(engine, set_indicators) = xkl_xmm_set_indicators;
Packit Service 93d855
	xkl_engine_priv(engine, finalize) = xkl_xmm_term;
Packit Service 93d855
Packit Service 93d855
	if (getenv("XKL_XMODMAP_DISABLE") != NULL)
Packit Service 93d855
		return -1;
Packit Service 93d855
Packit Service 93d855
	display = xkl_engine_get_display(engine);
Packit Service 93d855
	xkl_engine_priv(engine, base_config_atom) =
Packit Service 93d855
	    XInternAtom(display, "_XMM_NAMES", False);
Packit Service 93d855
	xkl_engine_priv(engine, backup_config_atom) =
Packit Service 93d855
	    XInternAtom(display, "_XMM_NAMES_BACKUP", False);
Packit Service 93d855
Packit Service 93d855
	xkl_engine_priv(engine, backend) = g_new0(XklXmm, 1);
Packit Service 93d855
Packit Service 93d855
	xkl_engine_backend(engine, XklXmm, state_atom) =
Packit Service 93d855
	    XInternAtom(display, "_XMM_STATE", False);
Packit Service 93d855
Packit Service 93d855
	xkl_engine_priv(engine, default_model) = "generic";
Packit Service 93d855
	xkl_engine_priv(engine, default_layout) = "us";
Packit Service 93d855
Packit Service 93d855
	xkl_xmm_init_switch_options((XklXmm *)
Packit Service 93d855
				    xkl_engine_priv(engine, backend));
Packit Service 93d855
Packit Service 93d855
	return 0;
Packit Service 93d855
}
Packit Service 93d855
Packit Service 93d855
void
Packit Service 93d855
xkl_xmm_term(XklEngine * engine)
Packit Service 93d855
{
Packit Service 93d855
	xkl_xmm_term_switch_options((XklXmm *)
Packit Service 93d855
				    xkl_engine_priv(engine, backend));
Packit Service 93d855
}