static void
popup_menu_set_group (gint group_number, gboolean only_menu)
{

	XklEngine *engine = gkbd_status_get_xkl_engine ();

	XklState *st = xkl_engine_get_current_state(engine);
	Window cur;
	st->group = group_number;
	xkl_engine_allow_one_switch_to_secondary_group (engine);
	cur = xkl_engine_get_current_window (engine);
	if (cur != (Window) NULL) {
		xkl_debug (150, "Enforcing the state %d for window %lx\n",
			   st->group, cur);

		xkl_engine_save_state (engine,
				       xkl_engine_get_current_window
				       (engine), st);
/*    XSetInputFocus( GDK_DISPLAY(), cur, RevertToNone, CurrentTime );*/
	} else {
		xkl_debug (150,
			   "??? Enforcing the state %d for unknown window\n",
			   st->group);
		/* strange situation - bad things can happen */
	}
        if (!only_menu)
        	xkl_engine_lock_group (engine, st->group);
}
static void
popup_menu_set_group (GtkMenuItem * item, gpointer param)
{
	gint group_number = GPOINTER_TO_INT (param);
	XklEngine *engine = gkbd_status_get_xkl_engine ();
	XklState st;
	Window cur;

	st.group = group_number;
	xkl_engine_allow_one_switch_to_secondary_group (engine);
	cur = xkl_engine_get_current_window (engine);
	if (cur != (Window) NULL) {
		xkl_debug (150, "Enforcing the state %d for window %lx\n",
			   st.group, cur);
		xkl_engine_save_state (engine,
				       xkl_engine_get_current_window
				       (engine), &st);
/*    XSetInputFocus( GDK_DISPLAY(), cur, RevertToNone, CurrentTime );*/
	} else {
		xkl_debug (150,
			   "??? Enforcing the state %d for unknown window\n",
			   st.group);
		/* strange situation - bad things can happen */
	}
	xkl_engine_lock_group (engine, st.group);
}
예제 #3
0
/*
 * Gets the state from the window property
 */
gboolean
xkl_engine_get_toplevel_window_state(XklEngine * engine,
				     Window toplevel_win,
				     XklState * state_out)
{
	Atom type_ret;
	int format_ret;
	unsigned long nitems, rest;
	CARD32 *prop = NULL;
	gboolean ret = FALSE;

	gint grp = -1;
	guint inds = 0;

	if ((XGetWindowProperty
	     (xkl_engine_get_display(engine), toplevel_win,
	      xkl_engine_priv(engine, atoms)[XKLAVIER_STATE], 0L,
	      XKLAVIER_STATE_PROP_LENGTH, False, XA_INTEGER, &type_ret,
	      &format_ret, &nitems, &rest,
	      (unsigned char **) (void *) &prop) == Success)
	    && (type_ret == XA_INTEGER) && (format_ret == 32)) {
		grp = prop[0];
		if (grp >= xkl_engine_get_num_groups(engine) || grp < 0)
			grp = 0;

		inds = prop[1];

		if (state_out != NULL) {
			state_out->group = grp;
			state_out->indicators = inds;
		}
		if (prop != NULL)
			XFree(prop);

		ret = TRUE;
	}

	if (ret)
		xkl_debug(150,
			  "Appwin " WINID_FORMAT
			  ", '%s' has the group %d, indicators %X\n",
			  toplevel_win,
			  xkl_get_debug_window_title(engine, toplevel_win),
			  grp, inds);
	else
		xkl_debug(150,
			  "Appwin " WINID_FORMAT
			  ", '%s' does not have state\n", toplevel_win,
			  xkl_get_debug_window_title(engine,
						     toplevel_win));

	return ret;
}
static gboolean
filter_xkb_config (void)
{
	XklConfigItem *item;
	gchar *lname;
	gchar *vname;
	gchar **lv;
	gboolean any_change = FALSE;

	xkl_debug (100, "Filtering configuration against the registry\n");
	if (!ensure_xkl_registry ())
		return FALSE;

	lv = current_kbd_config.layouts_variants;
	item = xkl_config_item_new ();
	while (*lv) {
		xkl_debug (100, "Checking [%s]\n", *lv);
		if (gkbd_keyboard_config_split_items (*lv, &lname, &vname)) {
			gboolean should_be_dropped = FALSE;
			g_snprintf (item->name, sizeof (item->name), "%s",
				    lname);
			if (!xkl_config_registry_find_layout
			    (xkl_registry, item)) {
				xkl_debug (100, "Bad layout [%s]\n",
					   lname);
				should_be_dropped = TRUE;
			} else if (vname) {
				g_snprintf (item->name,
					    sizeof (item->name), "%s",
					    vname);
				if (!xkl_config_registry_find_variant
				    (xkl_registry, lname, item)) {
					xkl_debug (100,
						   "Bad variant [%s(%s)]\n",
						   lname, vname);
					should_be_dropped = TRUE;
				}
			}
			if (should_be_dropped) {
				gkbd_strv_behead (lv);
				any_change = TRUE;
				continue;
			}
		}
		lv++;
	}
	g_object_unref (item);
	return any_change;
}
/**
 * static applet config functions
 */
static void
matekbd_indicator_config_load_font (MatekbdIndicatorConfig * ind_config)
{
    ind_config->font_family =
        g_settings_get_string (ind_config->settings,
                               MATEKBD_INDICATOR_CONFIG_KEY_FONT_FAMILY);

    if (ind_config->font_family == NULL ||
            ind_config->font_family[0] == '\0') {
        PangoFontDescription *fd = NULL;
        GtkStyle *style =
            gtk_rc_get_style_by_paths (gtk_settings_get_default (),
                                       GTK_STYLE_PATH,
                                       GTK_STYLE_PATH,
                                       GTK_TYPE_LABEL);
        if (style != NULL)
            fd = style->font_desc;
        if (fd != NULL) {
            ind_config->font_family =
                g_strdup (pango_font_description_to_string(fd));
        }
    }
    xkl_debug (150, "font: [%s]\n", ind_config->font_family);

}
예제 #6
0
void
xkl_engine_set_toplevel_window_transparent(XklEngine * engine,
					   Window toplevel_win,
					   gboolean transparent)
{
	gboolean oldval;

	oldval =
	    xkl_engine_is_toplevel_window_transparent(engine,
						      toplevel_win);
	xkl_debug(150, "toplevel_win " WINID_FORMAT " was %stransparent\n",
		  toplevel_win, oldval ? "" : "not ");
	if (transparent && !oldval) {
		CARD32 prop = 1;
		XChangeProperty(xkl_engine_get_display(engine),
				toplevel_win,
				xkl_engine_priv(engine, atoms)
				[XKLAVIER_TRANSPARENT], XA_INTEGER, 32,
				PropModeReplace,
				(const unsigned char *) &prop, 1);
	} else if (!transparent && oldval) {
		XDeleteProperty(xkl_engine_get_display(engine),
				toplevel_win,
				xkl_engine_priv(engine, atoms)
				[XKLAVIER_TRANSPARENT]);
	}
}
static void
show_hide_icon ()
{
	if (g_slist_length (current_kbd_config.layouts_variants) > 1) {
		if (icon == NULL) {
			xkl_debug (150, "Creating new icon\n");
			icon = gkbd_status_new ();
			g_signal_connect (icon, "popup-menu",
					  G_CALLBACK
					  (status_icon_popup_menu_cb),
					  NULL);

		}
	} else {
		if (icon != NULL) {
			xkl_debug (150, "Destroying icon\n");
			g_object_unref (icon);
			icon = NULL;
		}
	}
}
static void
matekbd_indicator_config_load_font (MatekbdIndicatorConfig * ind_config)
{
	GError *gerror = NULL;

	ind_config->font_family =
	    mateconf_client_get_string (ind_config->conf_client,
				     MATEKBD_INDICATOR_CONFIG_KEY_FONT_FAMILY,
				     &gerror);
	if (gerror != NULL) {
		g_warning ("Error reading configuration:%s\n",
			   gerror->message);
		ind_config->font_family = g_strdup ("Helvetica");
		g_error_free (gerror);
		gerror = NULL;
	}

	ind_config->font_size =
	    mateconf_client_get_int (ind_config->conf_client,
				  MATEKBD_INDICATOR_CONFIG_KEY_FONT_SIZE,
				  &gerror);
	if (gerror != NULL) {
		g_warning ("Error reading configuration:%s\n",
			   gerror->message);
		ind_config->font_size = 10;
		g_error_free (gerror);
		gerror = NULL;
	}

	if (ind_config->font_family == NULL ||
	    ind_config->font_family[0] == '\0') {
		PangoFontDescription *fd = NULL;
		GtkStyle *style =
		    gtk_rc_get_style_by_paths (gtk_settings_get_default (),
					       GTK_STYLE_PATH,
					       GTK_STYLE_PATH,
					       GTK_TYPE_LABEL);
		if (style != NULL)
			fd = style->font_desc;
		if (fd != NULL) {
			ind_config->font_family =
			    g_strdup (pango_font_description_get_family
				      (fd));
			ind_config->font_size =
			    pango_font_description_get_size (fd) /
			    PANGO_SCALE;
		}
	}
	xkl_debug (150, "font: [%s], size %d\n", ind_config->font_family,
		   ind_config->font_size);

}
예제 #9
0
static void
gkbd_indicator_config_load_font (GkbdIndicatorConfig * ind_config)
{
	ind_config->font_family =
	    g_settings_get_string (ind_config->settings,
				   GKBD_INDICATOR_CONFIG_KEY_FONT_FAMILY);

	ind_config->font_size =
	    g_settings_get_int (ind_config->settings,
				GKBD_INDICATOR_CONFIG_KEY_FONT_SIZE);

	xkl_debug (150, "font: [%s], size %d\n",
		   ind_config->font_family ? ind_config->
		   font_family : "(null)", ind_config->font_size);

}
예제 #10
0
/*
 * Saves the state into the window properties
 */
void
xkl_engine_save_toplevel_window_state(XklEngine * engine,
				      Window toplevel_win,
				      XklState * state)
{
	CARD32 prop[XKLAVIER_STATE_PROP_LENGTH];

	prop[0] = state->group;
	prop[1] = state->indicators;

	XChangeProperty(xkl_engine_get_display(engine), toplevel_win,
			xkl_engine_priv(engine, atoms)[XKLAVIER_STATE],
			XA_INTEGER, 32, PropModeReplace,
			(const unsigned char *) prop,
			XKLAVIER_STATE_PROP_LENGTH);

	xkl_debug(160,
		  "Saved the group %d, indicators %X for appwin "
		  WINID_FORMAT "\n", state->group, state->indicators,
		  toplevel_win);
}
/*
 * static applet config functions
 */
static void
matekbd_indicator_config_load_font (MatekbdIndicatorConfig * ind_config)
{
	ind_config->font_family =
	    g_settings_get_string (ind_config->settings,
				   MATEKBD_INDICATOR_CONFIG_KEY_FONT_FAMILY);

	if (ind_config->font_family == NULL ||
	    ind_config->font_family[0] == '\0') {
		PangoFontDescription *fd = NULL;
		GtkWidgetPath *widget_path = gtk_widget_path_new ();
		GtkStyleContext *context = gtk_style_context_new ();

		gtk_widget_path_append_type (widget_path, GTK_TYPE_WINDOW);
		gtk_widget_path_iter_set_name (widget_path, -1 , "PanelWidget");

		gtk_style_context_set_path (context, widget_path);
		gtk_style_context_set_screen (context, gdk_screen_get_default ());
		gtk_style_context_set_state (context, GTK_STATE_FLAG_NORMAL);
		gtk_style_context_add_class (context, GTK_STYLE_CLASS_DEFAULT);
		gtk_style_context_add_class (context, "gnome-panel-menu-bar");
		gtk_style_context_add_class (context, "mate-panel-menu-bar");

		gtk_style_context_get (context, GTK_STATE_FLAG_NORMAL,
		                       GTK_STYLE_PROPERTY_FONT, &fd, NULL);

		if (fd != NULL) {
			ind_config->font_family =
			    g_strdup (pango_font_description_to_string(fd));
		}

		g_object_unref (G_OBJECT (context));
		gtk_widget_path_unref (widget_path);
	}
	xkl_debug (150, "font: [%s]\n", ind_config->font_family);

}
static void
apply_xkb_settings (void)
{
	GkbdKeyboardConfig current_sys_kbd_config;

	if (!inited_ok)
		return;

	gkbd_keyboard_config_init (&current_sys_kbd_config, xkl_engine);

	gkbd_keyboard_config_load (&current_kbd_config,
				   &initial_sys_kbd_config);

	gkbd_keyboard_config_load_from_x_current (&current_sys_kbd_config,
						  NULL);

	if (!try_activating_xkb_config_if_new (&current_sys_kbd_config)) {
		if (filter_xkb_config ()) {
			if (!try_activating_xkb_config_if_new
			    (&current_sys_kbd_config)) {
				g_warning
				    ("Could not activate the filtered XKB configuration");
				activation_error ();
			}
		} else {
			g_warning
			    ("Could not activate the XKB configuration");
			activation_error ();
		}
	} else
		xkl_debug (100,
			   "Actual KBD configuration was not changed: redundant notification\n");

	gkbd_keyboard_config_term (&current_sys_kbd_config);
	show_hide_icon ();
}
static void
apply_xkb_settings (void)
{
	GConfClient *conf_client;
	GkbdKeyboardConfig current_sys_kbd_config;
	int group_to_activate = -1;
	char *gdm_layout;
	char *s;

	if (!inited_ok)
		return;

	conf_client = gconf_client_get_default ();

	/* With GDM the user can already set a layout from the login
	 * screen. Try to keep that setting.
	 * We clear gdm_keyboard_layout early, so we don't risk
	 * recursion from gconf notification.
	 */
	gdm_layout = g_strdup (gdm_keyboard_layout);
	gdm_keyboard_layout = NULL;

	/* gdm's configuration and $GDM_KEYBOARD_LAYOUT separates layout and
	 * variant with a space, but gconf uses tabs; so convert to be robust
	 * with both */
	for (s = gdm_layout; s && *s; ++s) {
		if (*s == ' ') {
			*s = '\t';
		}
	}

	if (gdm_layout != NULL) {
		GSList *layouts;
		GSList *found_node;
		int max_groups;

		max_groups = xkl_engine_get_max_num_groups (xkl_engine);
		layouts = gconf_client_get_list (conf_client,
						 GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS,
						 GCONF_VALUE_STRING, NULL);

		/* Add the layout if it doesn't already exist. XKB limits the
		 * total number of layouts. If we already have the maximum
		 * number of layouts configured, we replace the last one. This
		 * prevents the list from becoming full if the user has a habit
		 * of selecting many different keyboard layouts in GDM. */

		found_node =
		    g_slist_find_custom (layouts, gdm_layout,
					 (GCompareFunc) g_strcmp0);

		if (!found_node) {
			/* Insert at the last valid place, or at the end of
			 * list, whichever comes first */
			layouts =
			    g_slist_insert (layouts, g_strdup (gdm_layout),
					    max_groups - 1);
			if (g_slist_length (layouts) > max_groups) {
				GSList *last;
				GSList *free_layouts;

				last =
				    g_slist_nth (layouts, max_groups - 1);
				free_layouts = last->next;
				last->next = NULL;

				g_slist_foreach (free_layouts,
						 (GFunc) g_free, NULL);
				g_slist_free (free_layouts);
			}

			gconf_client_set_list (conf_client,
					       GKBD_KEYBOARD_CONFIG_KEY_LAYOUTS,
					       GCONF_VALUE_STRING, layouts,
					       NULL);
		}

		g_slist_foreach (layouts, (GFunc) g_free, NULL);
		g_slist_free (layouts);
	}

	gkbd_keyboard_config_init (&current_sys_kbd_config,
				   conf_client, xkl_engine);

	gkbd_keyboard_config_load_from_gconf (&current_kbd_config,
					      &initial_sys_kbd_config);

	gkbd_keyboard_config_load_from_x_current (&current_sys_kbd_config,
						  NULL);

	if (!try_activating_xkb_config_if_new (&current_sys_kbd_config)) {
		if (filter_xkb_config ()) {
			if (!try_activating_xkb_config_if_new
			    (&current_sys_kbd_config)) {
				g_warning
				    ("Could not activate the filtered XKB configuration");
				activation_error ();
			}
		} else {
			g_warning
			    ("Could not activate the XKB configuration");
			activation_error ();
		}
	} else
		xkl_debug (100,
			   "Actual KBD configuration was not changed: redundant notification\n");

	if (gdm_layout != NULL) {
		/* If there are multiple layouts,
		 * try to find the one closest to the gdm layout
		 */
		GSList *l;
		int i;
		size_t len = strlen (gdm_layout);
		for (i = 0, l = current_kbd_config.layouts_variants; l;
		     i++, l = l->next) {
			char *lv = l->data;
			if (strncmp (lv, gdm_layout, len) == 0
			    && (lv[len] == '\0' || lv[len] == '\t')) {
				group_to_activate = i;
				break;
			}
		}
	}

	g_free (gdm_layout);

	if (group_to_activate != -1)
		xkl_engine_lock_group (current_config.engine,
				       group_to_activate);
	gkbd_keyboard_config_term (&current_sys_kbd_config);
}
static gboolean
filter_xkb_config (void)
{
	XklConfigItem *item;
	gchar *lname;
	gchar *vname;
	GSList *lv;
	GSList *filtered;
	gboolean any_change = FALSE;

	xkl_debug (100, "Filtering configuration against the registry\n");
	if (!xkl_registry) {
		xkl_registry =
		    xkl_config_registry_get_instance (xkl_engine);
		/* load all materials, unconditionally! */
		if (!xkl_config_registry_load (xkl_registry, TRUE)) {
			g_object_unref (xkl_registry);
			xkl_registry = NULL;
			return FALSE;
		}
	}
	lv = current_kbd_config.layouts_variants;
	item = xkl_config_item_new ();
	while (lv) {
		xkl_debug (100, "Checking [%s]\n", lv->data);
		if (gkbd_keyboard_config_split_items
		    (lv->data, &lname, &vname)) {
			g_snprintf (item->name, sizeof (item->name), "%s",
				    lname);
			if (!xkl_config_registry_find_layout
			    (xkl_registry, item)) {
				xkl_debug (100, "Bad layout [%s]\n",
					   lname);
				filtered = lv;
				lv = lv->next;
				g_free (filtered->data);
				current_kbd_config.layouts_variants =
				    g_slist_delete_link
				    (current_kbd_config.layouts_variants,
				     filtered);
				any_change = TRUE;
				continue;
			}
			if (vname) {
				g_snprintf (item->name,
					    sizeof (item->name), "%s",
					    vname);
				if (!xkl_config_registry_find_variant
				    (xkl_registry, lname, item)) {
					xkl_debug (100,
						   "Bad variant [%s(%s)]\n",
						   lname, vname);
					filtered = lv;
					lv = lv->next;
					g_free (filtered->data);
					current_kbd_config.layouts_variants
					    =
					    g_slist_delete_link
					    (current_kbd_config.
					     layouts_variants, filtered);
					any_change = TRUE;
					continue;
				}
			}
		}
		lv = lv->next;
	}
	g_object_unref (item);
	return any_change;
}
예제 #15
0
/*
 * "Adds" app window to the set of managed windows.
 * Actually, no data structures involved. The only thing we do is save app state
 * and register ourselves us listeners.
 * Note: User's callback is called
 */
void
xkl_engine_add_toplevel_window(XklEngine * engine, Window toplevel_win,
			       Window parent,
			       gboolean ignore_existing_state,
			       XklState * init_state)
{
	XklState state = *init_state;
	gint default_group_to_use = -1;
	GValue params[3];
	GValue rv;
	guint signal_id;

	if (toplevel_win == xkl_engine_priv(engine, root_window))
		xkl_debug(150, "??? root app win ???\n");

	xkl_debug(150,
		  "Trying to add window " WINID_FORMAT
		  "/%s with group %d\n", toplevel_win,
		  xkl_get_debug_window_title(engine, toplevel_win),
		  init_state->group);

	if (!ignore_existing_state) {
		gboolean have_state =
		    xkl_engine_get_toplevel_window_state(engine,
							 toplevel_win,
							 &state);

		if (have_state) {
			xkl_debug(150,
				  "The window " WINID_FORMAT
				  " does not require to be added, it already has the xklavier state \n",
				  toplevel_win);
			return;
		}
	}
	memset(params, 0, sizeof(params));
	g_value_init(params, XKL_TYPE_ENGINE);
	g_value_set_object(params, engine);
	g_value_init(params + 1, G_TYPE_LONG);
	g_value_set_long(params + 1, toplevel_win);
	g_value_init(params + 2, G_TYPE_LONG);
	g_value_set_long(params + 2, parent);

	memset(&rv, 0, sizeof(rv));
	g_value_init(&rv, G_TYPE_INT);
	g_value_set_int(&rv, default_group_to_use);

	signal_id =
	    g_signal_lookup("new-toplevel-window", xkl_engine_get_type());
	g_signal_emitv(params, signal_id, 0, &rv);
	default_group_to_use = g_value_get_int(&rv);
        
	if (default_group_to_use == -1) {
		Window transient_for = 0;
		if (XGetTransientForHint(xkl_engine_get_display(engine), toplevel_win, &transient_for)) {
			if (transient_for) {
				XklState trans_state;
				gboolean have_state =
					xkl_engine_get_toplevel_window_state(engine,
							 transient_for,
							 &trans_state);
				if (have_state) {
					default_group_to_use = trans_state.group;
				}
			}
		}
	}

	if (default_group_to_use == -1)
		default_group_to_use =
		    xkl_engine_priv(engine, default_group);

	if (default_group_to_use != -1)
		state.group = default_group_to_use;

	xkl_engine_save_toplevel_window_state(engine, toplevel_win,
					      &state);
	xkl_engine_select_input_merging(engine, toplevel_win,
					FocusChangeMask |
					PropertyChangeMask);

	if (default_group_to_use != -1) {
		if (xkl_engine_priv(engine, curr_toplvl_win) ==
		    toplevel_win) {
			if ((xkl_engine_priv(engine, secondary_groups_mask)
			     & (1 << default_group_to_use)) != 0)
				xkl_engine_allow_one_switch_to_secondary_group
				    (engine);
			xkl_engine_lock_group(engine,
					      default_group_to_use);
		}
	}

	if (parent == (Window) NULL)
		parent =
		    xkl_engine_get_registered_parent(engine, toplevel_win);

	xkl_debug(150, "done\n");
}
예제 #16
0
/*
 * Recursively finds "App window" (window with WM_STATE) for given window.
 * First, checks the window itself
 * Then, for first level of recursion, checks childen,
 * Then, goes to parent.
 * NOTE: root window cannot be "App window" under normal circumstances
 */
gboolean
xkl_engine_find_toplevel_window(XklEngine * engine, Window win,
				Window * toplevel_win_out)
{
	Window parent = (Window) NULL,
	    rwin = (Window) NULL, *children = NULL, *child;
	guint num = 0;
	gboolean rv;

	if (win == (Window) NULL
	    || win == PointerRoot
	    || win == xkl_engine_priv(engine, root_window)) {
		*toplevel_win_out = (Window) NULL;
		xkl_last_error_message = "The window is either 0 or root";
		xkl_debug(150,
			  "Window " WINID_FORMAT
			  " is either 0 or root so could not get the app window for it\n",
			  win);
		return FALSE;
	}

	if (xkl_engine_if_window_has_wm_state(engine, win)) {
		*toplevel_win_out = win;
		return TRUE;
	}

	xkl_engine_priv(engine, last_error_code) =
	    xkl_engine_query_tree(engine, win, &rwin, &parent, &children,
				  &num);

	if (xkl_engine_priv(engine, last_error_code) != Success) {
		*toplevel_win_out = (Window) NULL;
		xkl_debug(150,
			  "Could not get tree for window " WINID_FORMAT
			  " so could not get the app window for it\n",
			  win);
		return FALSE;
	}

	/*
	 * Here we first check the children (in case win is just above some "App Window")
	 * and then go upstairs
	 */
	child = children;
	while (num) {
		if (xkl_engine_if_window_has_wm_state(engine, *child)) {
			*toplevel_win_out = *child;
			if (children != NULL)
				XFree(children);
			return TRUE;
		}
		child++;
		num--;
	}

	if (children != NULL)
		XFree(children);

	rv = xkl_engine_find_toplevel_window_bottom_to_top(engine, parent,
							   toplevel_win_out);

	if (!rv)
		xkl_debug(200,
			  "Could not get the app window for " WINID_FORMAT
			  "/%s\n", win, xkl_get_debug_window_title(engine,
								   win));

	return rv;
}