Habilitando teclas de atalho 'Alt' para botões no Gnome?

6

Quero dizer: sempre que uma letra no texto de um botão é sublinhada, pressionar Alt mais essa letra clica no botão. Já passei pelos applets Keyboard e Tweak Tool sem sucesso.

Pressionar Alt sublinha as letras, mas eu prefiro que elas sejam sublinhadas de antemão.

    
por Elena 26.06.2015 / 21:00

1 resposta

6

Para o GTK 2, adicione a seguinte linha a ~/.gtkrc-2.0 :

gtk-auto-mnemonic = 0

Para o GTK 3 até o GTK 3.9:

do_dconf /org/gnome/desktop/interface/automatic-mnemonics false

No GTK 3.10, a opção foi removida (em este commit , cuja mensagem de log apenas informa que o recurso foi removido). Olhando para a fonte, não há como ativá-la. O comportamento maluco de mostrar os mnemônicos somente depois que Alt foi pressionado por pelo menos 300ms (o tempo limite é codificado como uma constante de tempo de compilação) é o único possível.

Eu me propus a substituir esse comportamento pelo pré-carregamento de um wrapper de biblioteca que força os mnemônicos a Seja visível. Não foi fácil, porque a maioria das chamadas é interna. Eu finalmente encontrei uma maneira de fazer a consulta que informa ao exibidor de rótulos se o widget deseja exibir mnemônicos sempre retornar true. Na maioria das vezes funciona, eu posso ver os mnemônicos o tempo todo nas caixas de diálogo do GEdit e do Evince, mas não completamente: alguns aceleradores de menu estão faltando, não sei por quê.

O código:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <glib.h>
#include <gtk/gtk.h>

#define PROP_MNEMONICS_VISIBLE 31

#ifdef DEBUG
#define DBG(args...) printf(args)
#else
#define DBG(args...)
#endif

static void (*original_gtk_window_get_property)(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
static void wrap_gtk_window_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
    original_gtk_window_get_property(object, prop_id, value, pspec);
    if (prop_id == PROP_MNEMONICS_VISIBLE) {
        DBG("%s(%p, %u, &%u, %p)\n", __FUNCTION__, object, prop_id, *(unsigned*)value, pspec);
        g_value_set_boolean(value, TRUE);
    }
}

inline void override_gtk_window_get_property(GType object_type, GObject *obj)
{
    static int first_window_creation = 1;
    if (object_type == GTK_TYPE_WINDOW && first_window_creation) {
        first_window_creation = 0;
        GtkWidgetClass *gtk_widget_class = GTK_WIDGET_GET_CLASS(obj);
        GObjectClass *gobject_class = G_OBJECT_CLASS(gtk_widget_class);
        original_gtk_window_get_property = gobject_class->get_property;
        gobject_class->get_property = wrap_gtk_window_get_property;
    }
}

GObject* g_object_new_valist(GType object_type, const gchar *first_property_name, va_list var_args)
{
    static GObject* (*original_g_object_new_valist)(GType object_type, const gchar *first_property_name, va_list var_args) = NULL;
    if (original_g_object_new_valist == NULL) {
        original_g_object_new_valist = dlsym(RTLD_NEXT, "g_object_new_valist");
    }
    GObject* obj = original_g_object_new_valist(object_type, first_property_name, var_args);
    override_gtk_window_get_property(object_type, obj);
    return obj;
}
gpointer g_object_new(GType object_type, const gchar *first_property_name, ...)
{
    va_list var_args;
    va_start(var_args, first_property_name);
    gpointer obj = g_object_new_valist(object_type, first_property_name, var_args);
    va_end(var_args);
    return obj;
}
gpointer g_object_newv(GType object_type, guint n_parameters, GParameter *parameters)
{
    static gpointer (*original_g_object_newv)(GType object_type, guint n_parameters, GParameter *parameters);
    if (original_g_object_newv == NULL) {
        original_g_object_newv = dlsym(RTLD_NEXT, "g_object_newv");
    }
    GObject* obj = original_g_object_newv(object_type, n_parameters, parameters);
    override_gtk_window_get_property(object_type, obj);
    return obj;
}

Como usar: escreva isso em um arquivo chamado gtk_window_get_mnemonics_visible.c . Instale o GCC e o pacote de desenvolvimento do GTK3 (por exemplo, sudo apt-get install gcc libgtk-3-dev no Debian / Ubuntu). Compile com

gcc -Wall -fPIC -shared 'pkg-config --cflags gtk+-3.0' 'pkg-config --libs gtk+-3.0' -o gtk_window_get_mnemonics_visible.so gtk_window_get_mnemonics_visible.c

Execute aplicativos Gnome como este:

LD_PRELOAD=/path/to/gtk_window_get_mnemonics_visible.so gedit

ou coloque isso no seu .profile :

export LD_PRELOAD=/path/to/gtk_window_get_mnemonics_visible.so

Observe que LD_PRELOAD é um hack, pode causar um comportamento estranho às vezes. Eu só dei a este um teste superficial. Bug conhecido:

  • Se GTK_IM_MODULE estiver definido como xim , usar LD_PRELOAD para qualquer coisa (até mesmo um arquivo C vazio!) fará com que o GEdit seja interrompido quando eu pressionar Alt (observado no Debian jessie) . Eu não tenho ideia do porquê.
por 27.06.2015 / 12:14