LINUX.ORG.RU

[c][gtk] Конфликт Bindings vs Accelerators

 ,


0

1

Изучаю потихоньку GTK+ 2.x, и уже второй вечер бьюсь над реализацией горячих клавиш (shortcuts). Делаю как положено, через Accelerator Groups, вешаю группу на окно, потом привязываю акселераторы к действиям (Actions) — всё работает, но есть одно «но»: не активируются акселераторы, назначеные на клавиши, участвующие в Bindings. Т.е. простым пробелом, стрелками, клавишей табуляции или вводом без модификаторов нельзя активировать акселератор. Судя по документации нет механизмов для удаления или отключения дефолтных Bindings, хотел было обойти с помощью key-press-event на окне, но опять же нет никакой возможности вручную активировать акселератор по значениям клавиши и модификаторов. Куда ни сунься, везде засада. Подскажите куда копать, или может проще собственный механизм горячих клавиш свелосипедить?


можно пример того, что ты желаешь сотворить? судя по описанию, подобные случаи вообще через gtkrc разруливаются

ananas ★★★★★
()
Ответ на: комментарий от ananas

Есть окно, в нём есть область вывода изображения, панель с кнопками и контекстное меню. Всё, больше ничего нет, нет никакого смысла в навигации по элементам управления, которых нет. Желаю использовать занятые клавиши (чистый пробел без модификаторов, стрелки и т.п.) в качестве горячих клавиш в этом окне. Через gtkrc можно переназначить клавиши для Bindings (понятия не имею, как это назвать по-русски), но там так же сказано, что удалить стандартные нельзя.

У меня есть приблизительно такой код:

GtkAccelGroup *accel_group = gtk_accel_group_new();
GtkAction *action = gtk_action_new(name, label, tooltip, stock_id);
g_signal_connect(action, "activate", callback, NULL);
gtk_action_set_accel_path(action, accel_path);
gtk_action_set_accel_group(action, accel_group);
gtk_action_connect_accelerator(action);
/* остальные действия создаются таким же макаром */
Потом в другом месте:
gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
gtk_accel_map_add_entry(accel_path, GDK_KEY_space, 0);
/* назначаются остальные клавиши */
Если указать код клавиши GDK_KEY_x или любой другой алфавитно-цифровой, то всё работает, а если GDK_KEY_space, GDK_KEY_Return и некоторые другие, то не работает.

Я попробовал сделать так:

GtkBindingSet *bs = gtk_binding_set_by_class(G_OBJECT_GET_CLASS(window));
GtkBindingEntry *p;
for (p = bs->entries; p != NULL; p = p->set_next) {
	gtk_binding_entry_remove(bs, p->keyval, p->modifiers);
}
Но не помогло. Может если обойти всю иерархию до самого корня и посносить всё, то заработает, но тогда поломаются другие вещи, к примеру, навигация по меню.

Zveroy
() автор топика

Рисовать интерфейс в Glade не пробовали? У меня тоже была такая проблема: если интерфейс нарисован вручную, «горячие клавиши» не работали. А вот интерфейс из Glade работал нормально.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Рисовать интерфейс в Glade не пробовали?

Нет, с детсва не люблю визуальные редакторы, да и такой простой интерфейс несложно руками накодить, тем более используется парочка самопальных объектов.

У меня тоже была такая проблема: если интерфейс нарисован вручную, «горячие клавиши» не работали.

Самое интересное в том, что они отлично работают, только не со всеми клавишами.

Немного поэксперементировал, и у меня возникло подозрение, что подстава кроется в методах gtk_accel_map_add_entry () и gtk_accel_map_change_entry (), сейчас репозиторий GTK+ доклонируется, и я погляжу что там не так.

Zveroy
() автор топика
Ответ на: комментарий от Zveroy

Как я и предполагал, в gtkaccelmap.c, в коде internal_change_entry ():

  /* 4) walk the acceleratables and figure whether they occupy accel_key&accel_mods */
  if (accel_key)
    for (slist = win_list; slist; slist = slist->next)
      if (GTK_IS_WINDOW (slist->data))	/* bad kludge in lack of a GtkAcceleratable */
	if (_gtk_window_query_nonaccels (slist->data, accel_key, accel_mods))
	  {
	    seen_accel = TRUE;
	    break;
	  }
  removable = !seen_accel;
есть упоминание функции _gtk_window_query_nonaccels () из gtkwindow.c, с чудным кодом:
  /* movement keys are considered locked accels */
  if (!accel_mods)
    {
      static const guint bindings[] = {
	GDK_KEY_space, GDK_KEY_KP_Space, GDK_KEY_Return, GDK_KEY_ISO_Enter, GDK_KEY_KP_Enter, GDK_KEY_Up, GDK_KEY_KP_Up, GDK_KEY_Down, GDK_KEY_KP_Down,
	GDK_KEY_Left, GDK_KEY_KP_Left, GDK_KEY_Right, GDK_KEY_KP_Right, GDK_KEY_Tab, GDK_KEY_KP_Tab, GDK_KEY_ISO_Left_Tab,
      };
      guint i;
      
      for (i = 0; i < G_N_ELEMENTS (bindings); i++)
	if (bindings[i] == accel_key)
	  return TRUE;
    }
Нет слов. Буду писать свой велосипед.

Zveroy
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.