Blame libxklavier/xklavier_xmm.c

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