コード例 #1
0
/**
 * egg_accelerator_parse_virtual:
 * @accelerator:      string representing an accelerator
 * @accelerator_key:  return location for accelerator keyval
 * @accelerator_mods: return location for accelerator modifier mask
 *
 * Parses a string representing a virtual accelerator. The format
 * looks like "<Control>a" or "<Shift><Alt>F1" or
 * "<Release>z" (the last one is for key release).  The parser
 * is fairly liberal and allows lower or upper case, and also
 * abbreviations such as "<Ctl>" and "<Ctrl>".
 *
 * If the parse fails, @accelerator_key and @accelerator_mods will
 * be set to 0 (zero) and %FALSE will be returned. If the string contains
 * only modifiers, @accelerator_key will be set to 0 but %TRUE will be
 * returned.
 *
 * The virtual vs. concrete accelerator distinction is a relic of
 * how the X Window System works; there are modifiers Mod2-Mod5 that
 * can represent various keyboard keys (numlock, meta, hyper, etc.),
 * the virtual modifier represents the keyboard key, the concrete
 * modifier the actual Mod2-Mod5 bits in the key press event.
 *
 * Returns: %TRUE on success.
 */
gboolean
egg_accelerator_parse_virtual (const gchar            *accelerator,
                               guint                  *accelerator_key,
                               EggVirtualModifierType *accelerator_mods)
{
  guint keyval;
  unsigned mods;
  gint len;
  gboolean bad_keyval;

  if (accelerator_key)
    *accelerator_key = 0;
  if (accelerator_mods)
    *accelerator_mods = (EggVirtualModifierType)0;

  g_return_val_if_fail (accelerator != NULL, FALSE);

  bad_keyval = FALSE;

  keyval = 0;
  mods = 0;
  len = strlen (accelerator);
  while (len)
    {
      if (*accelerator == '<')
	{
	  if (len >= 9 && is_release (accelerator))
	    {
	      accelerator += 9;
	      len -= 9;
	      mods |= EGG_VIRTUAL_RELEASE_MASK;
	    }
	  else if (len >= 9 && is_control (accelerator))
	    {
	      accelerator += 9;
	      len -= 9;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 7 && is_shift (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_SHIFT_MASK;
	    }
	  else if (len >= 6 && is_shft (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_SHIFT_MASK;
	    }
	  else if (len >= 6 && is_ctrl (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 6 && is_modx (accelerator))
	    {
	      static const guint mod_vals[] = {
		EGG_VIRTUAL_ALT_MASK, EGG_VIRTUAL_MOD2_MASK, EGG_VIRTUAL_MOD3_MASK,
		EGG_VIRTUAL_MOD4_MASK, EGG_VIRTUAL_MOD5_MASK
	      };

	      len -= 6;
	      accelerator += 4;
	      mods |= mod_vals[*accelerator - '1'];
	      accelerator += 2;
	    }
	  else if (len >= 5 && is_ctl (accelerator))
	    {
	      accelerator += 5;
	      len -= 5;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 5 && is_alt (accelerator))
	    {
	      accelerator += 5;
	      len -= 5;
	      mods |= EGG_VIRTUAL_ALT_MASK;
	    }
          else if (len >= 6 && is_meta (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_META_MASK;
	    }
          else if (len >= 7 && is_hyper (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_HYPER_MASK;
	    }
          else if (len >= 7 && is_super (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_SUPER_MASK;
	    }
	  else
	    {
	      gchar last_ch;

	      last_ch = *accelerator;
	      while (last_ch && last_ch != '>')
		{
		  last_ch = *accelerator;
		  accelerator += 1;
		  len -= 1;
		}
	    }
	}
      else
	{
          keyval = gdk_keyval_from_name (accelerator);

          if (keyval == 0)
            bad_keyval = TRUE;

          accelerator += len;
          len -= len;
	}
    }

  if (accelerator_key)
    *accelerator_key = gdk_keyval_to_lower (keyval);
  if (accelerator_mods)
    *accelerator_mods = (EggVirtualModifierType)mods;

  return !bad_keyval;
}
コード例 #2
0
static gboolean grab_key_callback(GtkWidget* widget, GdkEventKey* event, void* data)
{
	GdkModifierType accel_mods = 0;
	guint accel_keyval;
	EggCellRendererKeys *keys;
	char *path;
	gboolean edited;
	gboolean cleared;
	GdkModifierType consumed_modifiers;
	guint upper;
	GdkModifierType ignored_modifiers;

	keys = EGG_CELL_RENDERER_KEYS(data);

	if (is_modifier(event->hardware_keycode))
	{
		return TRUE;
	}

	edited = FALSE;
	cleared = FALSE;

	consumed_modifiers = 0;
	gdk_keymap_translate_keyboard_state(gdk_keymap_get_default(),
		event->hardware_keycode,
		event->state,
		event->group,
		NULL, NULL, NULL, &consumed_modifiers);

	upper = event->keyval;
	accel_keyval = gdk_keyval_to_lower(upper);

	if (accel_keyval == GDK_ISO_Left_Tab)
	{
		accel_keyval = GDK_Tab;
	}

	/* Put shift back if it changed the case of the key, not otherwise. */
	if (upper != accel_keyval && (consumed_modifiers & GDK_SHIFT_MASK))
	{
		consumed_modifiers &= ~(GDK_SHIFT_MASK);
	}

	egg_keymap_resolve_virtual_modifiers(gdk_keymap_get_default(),
		EGG_VIRTUAL_NUM_LOCK_MASK |
		EGG_VIRTUAL_SCROLL_LOCK_MASK |
		EGG_VIRTUAL_LOCK_MASK,
		&ignored_modifiers);

	/* http://bugzilla.gnome.org/show_bug.cgi?id=139605
	 * mouse keys should effect keybindings */
	ignored_modifiers |= GDK_BUTTON1_MASK |
		GDK_BUTTON2_MASK |
		GDK_BUTTON3_MASK |
		GDK_BUTTON4_MASK |
		GDK_BUTTON5_MASK;

	/* filter consumed/ignored modifiers */
	if (keys->accel_mode == EGG_CELL_RENDERER_KEYS_MODE_GTK)
	{
		accel_mods = event->state & GDK_MODIFIER_MASK & ~(consumed_modifiers | ignored_modifiers);
	}
	else if (keys->accel_mode == EGG_CELL_RENDERER_KEYS_MODE_X)
	{
		accel_mods = event->state & GDK_MODIFIER_MASK & ~(ignored_modifiers);
	}
	else
	{
		g_assert_not_reached();
	}

	if (accel_mods == 0 && accel_keyval == GDK_Escape)
	{
		goto out; /* cancel */
	}

	/* clear the accelerator on Backspace */
	if (accel_mods == 0 && accel_keyval == GDK_BackSpace)
	{
		cleared = TRUE;
		goto out;
	}

	if (keys->accel_mode == EGG_CELL_RENDERER_KEYS_MODE_GTK)
	{
		if (!gtk_accelerator_valid (accel_keyval, accel_mods))
		{
			accel_keyval = 0;
			accel_mods = 0;
		}
	}

	edited = TRUE;

	out:

	gdk_keyboard_ungrab(event->time);
	gdk_pointer_ungrab(event->time);

	path = g_strdup(g_object_get_data(G_OBJECT(keys->edit_widget), EGG_CELL_RENDERER_TEXT_PATH));

	gtk_cell_editable_editing_done(GTK_CELL_EDITABLE(keys->edit_widget));
	gtk_cell_editable_remove_widget(GTK_CELL_EDITABLE(keys->edit_widget));
	keys->edit_widget = NULL;
	keys->grab_widget = NULL;

	if (edited)
	{
		g_signal_emit_by_name(G_OBJECT(keys), "accel_edited", path, accel_keyval, accel_mods, event->hardware_keycode);
	}
	else if (cleared)
	{
		g_signal_emit_by_name(G_OBJECT(keys), "accel_cleared", path);
	}

	g_free (path);
	return TRUE;
}
コード例 #3
0
ファイル: eggaccelerators.c プロジェクト: Daksh/sugar-toolkit
/**
 * egg_virtual_accelerator_name:
 * @accelerator_key:  accelerator keyval
 * @accelerator_mods: accelerator modifier mask
 * @returns:          a newly-allocated accelerator name
 *
 * Converts an accelerator keyval and modifier mask
 * into a string parseable by egg_accelerator_parse_virtual().
 * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK,
 * this function returns "&lt;Control&gt;q".
 *
 * The caller of this function must free the returned string.
 */
gchar*
egg_virtual_accelerator_name (guint                  accelerator_key,
			      guint		     keycode,
                              EggVirtualModifierType accelerator_mods)
{
  static const gchar text_release[] = "<Release>";
  static const gchar text_shift[] = "<Shift>";
  static const gchar text_control[] = "<Control>";
  static const gchar text_mod1[] = "<Alt>";
  static const gchar text_mod2[] = "<Mod2>";
  static const gchar text_mod3[] = "<Mod3>";
  static const gchar text_mod4[] = "<Mod4>";
  static const gchar text_mod5[] = "<Mod5>";
  static const gchar text_meta[] = "<Meta>";
  static const gchar text_super[] = "<Super>";
  static const gchar text_hyper[] = "<Hyper>";
  guint l;
  gchar *keyval_name;
  gchar *accelerator;

  accelerator_mods &= EGG_VIRTUAL_MODIFIER_MASK;

  if (!accelerator_key)
    {
      keyval_name = g_strdup_printf ("0x%02x", keycode);
    }
  else
    {
      keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
      if (!keyval_name)
        keyval_name = "";
    }

  l = 0;
  if (accelerator_mods & EGG_VIRTUAL_RELEASE_MASK)
    l += sizeof (text_release) - 1;
  if (accelerator_mods & EGG_VIRTUAL_SHIFT_MASK)
    l += sizeof (text_shift) - 1;
  if (accelerator_mods & EGG_VIRTUAL_CONTROL_MASK)
    l += sizeof (text_control) - 1;
  if (accelerator_mods & EGG_VIRTUAL_ALT_MASK)
    l += sizeof (text_mod1) - 1;
  if (accelerator_mods & EGG_VIRTUAL_MOD2_MASK)
    l += sizeof (text_mod2) - 1;
  if (accelerator_mods & EGG_VIRTUAL_MOD3_MASK)
    l += sizeof (text_mod3) - 1;
  if (accelerator_mods & EGG_VIRTUAL_MOD4_MASK)
    l += sizeof (text_mod4) - 1;
  if (accelerator_mods & EGG_VIRTUAL_MOD5_MASK)
    l += sizeof (text_mod5) - 1;
  if (accelerator_mods & EGG_VIRTUAL_META_MASK)
    l += sizeof (text_meta) - 1;
  if (accelerator_mods & EGG_VIRTUAL_HYPER_MASK)
    l += sizeof (text_hyper) - 1;
  if (accelerator_mods & EGG_VIRTUAL_SUPER_MASK)
    l += sizeof (text_super) - 1;
  l += strlen (keyval_name);

  accelerator = g_new (gchar, l + 1);

  l = 0;
  accelerator[l] = 0;
  if (accelerator_mods & EGG_VIRTUAL_RELEASE_MASK)
    {
      strcpy (accelerator + l, text_release);
      l += sizeof (text_release) - 1;
    }
  if (accelerator_mods & EGG_VIRTUAL_SHIFT_MASK)
    {
      strcpy (accelerator + l, text_shift);
      l += sizeof (text_shift) - 1;
    }
  if (accelerator_mods & EGG_VIRTUAL_CONTROL_MASK)
    {
      strcpy (accelerator + l, text_control);
      l += sizeof (text_control) - 1;
    }
  if (accelerator_mods & EGG_VIRTUAL_ALT_MASK)
    {
      strcpy (accelerator + l, text_mod1);
      l += sizeof (text_mod1) - 1;
    }
  if (accelerator_mods & EGG_VIRTUAL_MOD2_MASK)
    {
      strcpy (accelerator + l, text_mod2);
      l += sizeof (text_mod2) - 1;
    }
  if (accelerator_mods & EGG_VIRTUAL_MOD3_MASK)
    {
      strcpy (accelerator + l, text_mod3);
      l += sizeof (text_mod3) - 1;
    }
  if (accelerator_mods & EGG_VIRTUAL_MOD4_MASK)
    {
      strcpy (accelerator + l, text_mod4);
      l += sizeof (text_mod4) - 1;
    }
  if (accelerator_mods & EGG_VIRTUAL_MOD5_MASK)
    {
      strcpy (accelerator + l, text_mod5);
      l += sizeof (text_mod5) - 1;
    }
  if (accelerator_mods & EGG_VIRTUAL_META_MASK)
    {
      strcpy (accelerator + l, text_meta);
      l += sizeof (text_meta) - 1;
    }
  if (accelerator_mods & EGG_VIRTUAL_HYPER_MASK)
    {
      strcpy (accelerator + l, text_hyper);
      l += sizeof (text_hyper) - 1;
    }
  if (accelerator_mods & EGG_VIRTUAL_SUPER_MASK)
    {
      strcpy (accelerator + l, text_super);
      l += sizeof (text_super) - 1;
    }

  strcpy (accelerator + l, keyval_name);

  return accelerator;
}
コード例 #4
0
ファイル: eggaccelerators.c プロジェクト: Daksh/sugar-toolkit
/**
 * egg_accelerator_parse_virtual:
 * @accelerator:      string representing an accelerator
 * @accelerator_key:  return location for accelerator keyval
 * @accelerator_mods: return location for accelerator modifier mask
 *
 * Parses a string representing a virtual accelerator. The format
 * looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or
 * "&lt;Release&gt;z" (the last one is for key release).  The parser
 * is fairly liberal and allows lower or upper case, and also
 * abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;".
 *
 * If the parse fails, @accelerator_key and @accelerator_mods will
 * be set to 0 (zero) and %FALSE will be returned. If the string contains
 * only modifiers, @accelerator_key will be set to 0 but %TRUE will be
 * returned.
 *
 * The virtual vs. concrete accelerator distinction is a relic of
 * how the X Window System works; there are modifiers Mod2-Mod5 that
 * can represent various keyboard keys (numlock, meta, hyper, etc.),
 * the virtual modifier represents the keyboard key, the concrete
 * modifier the actual Mod2-Mod5 bits in the key press event.
 *
 * Returns: %TRUE on success.
 */
gboolean
egg_accelerator_parse_virtual (const gchar            *accelerator,
                               guint                  *accelerator_key,
			       guint                  *keycode,
                               EggVirtualModifierType *accelerator_mods)
{
  guint keyval;
  GdkModifierType mods;
  gint len;
  gboolean bad_keyval;

  if (accelerator_key)
    *accelerator_key = 0;
  if (accelerator_mods)
    *accelerator_mods = 0;
  if (keycode)
    *keycode = 0;

  g_return_val_if_fail (accelerator != NULL, FALSE);

  bad_keyval = FALSE;

  keyval = 0;
  mods = 0;
  len = strlen (accelerator);
  while (len)
    {
      if (*accelerator == '<')
	{
	  if (len >= 9 && is_release (accelerator))
	    {
	      accelerator += 9;
	      len -= 9;
	      mods |= EGG_VIRTUAL_RELEASE_MASK;
	    }
	  else if (len >= 9 && is_control (accelerator))
	    {
	      accelerator += 9;
	      len -= 9;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 7 && is_shift (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_SHIFT_MASK;
	    }
	  else if (len >= 6 && is_shft (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_SHIFT_MASK;
	    }
	  else if (len >= 6 && is_ctrl (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 6 && is_modx (accelerator))
	    {
	      static const guint mod_vals[] = {
		EGG_VIRTUAL_ALT_MASK, EGG_VIRTUAL_MOD2_MASK, EGG_VIRTUAL_MOD3_MASK,
		EGG_VIRTUAL_MOD4_MASK, EGG_VIRTUAL_MOD5_MASK
	      };

	      len -= 6;
	      accelerator += 4;
	      mods |= mod_vals[*accelerator - '1'];
	      accelerator += 2;
	    }
	  else if (len >= 5 && is_ctl (accelerator))
	    {
	      accelerator += 5;
	      len -= 5;
	      mods |= EGG_VIRTUAL_CONTROL_MASK;
	    }
	  else if (len >= 5 && is_alt (accelerator))
	    {
	      accelerator += 5;
	      len -= 5;
	      mods |= EGG_VIRTUAL_ALT_MASK;
	    }
          else if (len >= 6 && is_meta (accelerator))
	    {
	      accelerator += 6;
	      len -= 6;
	      mods |= EGG_VIRTUAL_META_MASK;
	    }
          else if (len >= 7 && is_hyper (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_HYPER_MASK;
	    }
          else if (len >= 7 && is_super (accelerator))
	    {
	      accelerator += 7;
	      len -= 7;
	      mods |= EGG_VIRTUAL_SUPER_MASK;
	    }
	  else
	    {
	      gchar last_ch;

	      last_ch = *accelerator;
	      while (last_ch && last_ch != '>')
		{
		  last_ch = *accelerator;
		  accelerator += 1;
		  len -= 1;
		}
	    }
	}
      else
	{
          keyval = gdk_keyval_from_name (accelerator);

          if (keyval == 0)
	    {
	      /* If keyval is 0, than maybe it's a keycode.  Check for 0x## */
	      if (len >= 4 && is_keycode (accelerator))
		{
		  char keystring[5];
		  gchar *endptr;
		  gint tmp_keycode;

		  memcpy (keystring, accelerator, 4);
		  keystring [4] = '\000';

		  tmp_keycode = strtol (keystring, &endptr, 16);

		  if (endptr == NULL || *endptr != '\000')
		    {
		      bad_keyval = TRUE;
		    }
		  else if (keycode != NULL)
		    {
		      *keycode = tmp_keycode;
		      /* 0x00 is an invalid keycode too. */
		      if (*keycode == 0)
			bad_keyval = TRUE;
		    }
		}
	    } else if (keycode != NULL)
		*keycode = XKeysymToKeycode (GDK_DISPLAY(), keyval);

          accelerator += len;
          len -= len;
	}
    }

  if (accelerator_key)
    *accelerator_key = gdk_keyval_to_lower (keyval);
  if (accelerator_mods)
    *accelerator_mods = mods;

  return !bad_keyval;
}
コード例 #5
0
static gboolean
grab_key_callback (GtkWidget            *widget,
                   GdkEventKey          *event,
                   GtkCellRendererAccel *accel)
{
  GdkModifierType accel_mods = 0;
  guint accel_key;
  gchar *path;
  gboolean edited;
  gboolean cleared;
  GdkModifierType consumed_modifiers;
  GdkDisplay *display;

  display = gtk_widget_get_display (widget);

  if (event->is_modifier)
    return TRUE;

  edited = FALSE;
  cleared = FALSE;

  gdk_keymap_translate_keyboard_state (gdk_keymap_get_for_display (display),
				       event->hardware_keycode,
                                       event->state,
                                       event->group,
				       NULL, NULL, NULL, &consumed_modifiers);

  accel_key = gdk_keyval_to_lower (event->keyval);
  if (accel_key == GDK_ISO_Left_Tab) 
    accel_key = GDK_Tab;

  accel_mods = event->state & gtk_accelerator_get_default_mod_mask ();

  /* Filter consumed modifiers 
   */
  if (accel->accel_mode == GTK_CELL_RENDERER_ACCEL_MODE_GTK)
    accel_mods &= ~consumed_modifiers;
  
  /* Put shift back if it changed the case of the key, not otherwise.
   */
  if (accel_key != event->keyval)
    accel_mods |= GDK_SHIFT_MASK;
    
  if (accel_mods == 0)
    {
      switch (event->keyval)
	{
	case GDK_Escape:
	  goto out; /* cancel */
	case GDK_BackSpace:
	  /* clear the accelerator on Backspace */
	  cleared = TRUE;
	  goto out;
	default:
	  break;
	}
    }

  if (accel->accel_mode == GTK_CELL_RENDERER_ACCEL_MODE_GTK)
    {
      if (!gtk_accelerator_valid (accel_key, accel_mods))
	{
	  gtk_widget_error_bell (widget);

	  return TRUE;
	}
    }

  edited = TRUE;

 out:
  gtk_grab_remove (accel->grab_widget);
  gdk_display_keyboard_ungrab (display, event->time);
  gdk_display_pointer_ungrab (display, event->time);

  path = g_strdup (g_object_get_data (G_OBJECT (accel->edit_widget), "gtk-cell-renderer-text"));

  gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (accel->edit_widget));
  gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (accel->edit_widget));
  accel->edit_widget = NULL;
  accel->grab_widget = NULL;
  
  if (edited)
    g_signal_emit (accel, signals[ACCEL_EDITED], 0, path, 
		   accel_key, accel_mods, event->hardware_keycode);
  else if (cleared)
    g_signal_emit (accel, signals[ACCEL_CLEARED], 0, path);

  g_free (path);

  return TRUE;
}
コード例 #6
0
ファイル: fkeys.c プロジェクト: cremno/hexchat
static char *
key_get_key_name (int keyval)
{
	return gdk_keyval_name (gdk_keyval_to_lower (keyval));
}