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); }
/* * 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); }
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); }
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); }
/* * 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 (¤t_sys_kbd_config, xkl_engine); gkbd_keyboard_config_load (¤t_kbd_config, &initial_sys_kbd_config); gkbd_keyboard_config_load_from_x_current (¤t_sys_kbd_config, NULL); if (!try_activating_xkb_config_if_new (¤t_sys_kbd_config)) { if (filter_xkb_config ()) { if (!try_activating_xkb_config_if_new (¤t_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 (¤t_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 (¤t_sys_kbd_config, conf_client, xkl_engine); gkbd_keyboard_config_load_from_gconf (¤t_kbd_config, &initial_sys_kbd_config); gkbd_keyboard_config_load_from_x_current (¤t_sys_kbd_config, NULL); if (!try_activating_xkb_config_if_new (¤t_sys_kbd_config)) { if (filter_xkb_config ()) { if (!try_activating_xkb_config_if_new (¤t_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 (¤t_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; }
/* * "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"); }
/* * 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; }