´ÙÀ½ ÀÌÀü Â÷·Ê

17. Selection °ü¸®Çϱâ

17.1 °³¿ä

GTK°¡ Á¦°øÇÏ´Â ÇÁ·Î¼¼½º »çÀÌÀÇ Åë½ÅÇüÅ Áß Çϳª´Â selectionÀÌ´Ù. SelectionÀº »ç¿ëÀÚ°¡ ¸¶¿ì½º·Î ±Ü°Å³ª Çؼ­ ¼±ÅÃµÈ ÅؽºÆ®ÀÇ ÀϺΰ°Àº, µ¥ÀÌÅÍ Á¶°¢µéÀ» ÀνÄÇÑ´Ù. »ç¿ëÀÚ°¡ ¾î¶² ¼ø°£¿¡ ¼±ÅÃÇÏ°í ÀÖÀ» ¼ö ÀÖ´Â ¾îÇÃÀº Çϳª »ÓÀ̸ç, µû¶ó¼­ ¾î¶² ¾îÇÿ¡ ÀÇÇØ ¼±ÅÃÀÌ ¿ä±¸µÇ¾úÀ» ¶§, ÀÌÀüÀÇ ¼ÒÀ¯ÀÚ´Â selectionÀÌ Æ÷±âµÇ¾úÀ½À» »ç¿ëÀÚ¿¡°Ô Ç¥½ÃÇØ ÁÖ¾î¾ß ÇÑ´Ù. ´Ù¸¥ ¾îÇõéÀº targetÀ̶ó ºÒ¸®´Â, ´Ù¸¥ ÇüÅÂÀÇ selectionÀ» ¿äûÇÑ´Ù. SelectionÀÇ °¹¼ö´Â Á¦ÇÑÀÌ ¾øÁö¸¸, ´ëºÎºÐÀÇ XÀ©µµ ¾îÇõéÀº primary selectionÀ̶ó°í ºÎ¸£´Â ´Ü Çϳª¸¸À» ´Ù·é´Ù.

´ëºÎºÐ °æ¿ì, GTK ¾îÇÃÀÌ selection ÀÚü¸¦ ´Ù·ê ÇÊ¿ä´Â ¾ø´Ù. Entry widget µî Ç¥ÁØÀûÀÎ widgetµéÀº »ç¿ëÀÚ°¡ ÅؽºÆ® À§·Î ¸¶¿ì½º¸¦ µå·¡±×ÇÏ´Â µîÀÇ ÇÕ´çÇÑ °æ¿ì¿¡ selectionÀ» Á¦±âÇÒ ´É·ÂÀ» ÀÌ¹Ì °¡Áö°í ÀÖÀ¸¸ç, ±×¸®°í »ç¿ëÀÚ°¡ ¸¶¿ì½º ÀÇ µÎ¹ø° ¹öÆ°À» Ŭ¸¯ÇÏ´Â °æ¿ìó·³ ´Ù¸¥ ¾îÇÃÀ̳ª widget¿¡ ÀÇÇØ ¼ÒÀ¯µÈ selection Ç׸ñµéÀ» µÇãÀ» ¼öµµ ÀÖ´Ù. ±×·¯³ª ¿ì¸®°¡ ´Ù¸¥ widgetµéÀÌ selection À» Á¦°øÇÏ´Â ´É·ÂÀ» °¡Áöµµ·Ï ÇÏ°í½ÍÀº °æ¿ìµµ ÀÖÀ» °ÍÀ̸ç, µðÆúÆ®·Î Á¦°øµÇÁö ¾Ê´Â targetÀ» µÇã°í ½ÍÀ» ¶§µµ ÀÖÀ» °ÍÀÌ´Ù.

Selection ´Ù·ç±â¸¦ ÀÌÇØÇϱâ À§ÇØ ÇÊ¿äÇÑ ±âº»ÀûÀÎ °³³äÀº atomÀ̶ó´Â °ÍÀÌ´Ù. AtomÀ̶õ ¾î¶² display¿¡¼­, ÇÑ ¹®ÀÚ¿­À» À¯ÀÏÇÏ°Ô ±¸º°ÇÒ ¼ö ÀÖ´Â ¿ÏÀüÇÑ °ÍÀÌ´Ù. ¾î¶² atomµéÀº X ¼­¹ö¿¡ ÀÇÇØ ¹Ì¸® Á¤ÀǵǾî ÀÖÀ¸¸ç, ¾î¶² °æ¿ì¿£ ÀÌ·± atomµé¿¡ ´ëÇÑ constantµéÀÌ gtk.h¿¡ ÀÖÀ» ¼öµµ ÀÖ´Ù. ¿¹¸¦µé¾î »ó¼ö GDK_PRIMARY_SELECTIONÀº ¹®ÀÚ¿­ "PRIMARY"¿¡ ÇØ´çµÈ´Ù. ´Ù¸¥ °æ¿ì¶ó¸é, ¿ì¸®´Â ¾î¶² ¹®ÀÚ¿­ ¿¡ ´ëÀÀÇÏ´Â atomÀ» ÃëÇϱâ À§ÇØ gdk_atom_interm()À», ±×¸®°í atomÀÇ À̸§À» ÃëÇϱâ À§Çؼ± gdk_atom_name()À» ÀÌ¿ëÇØ¾ß ÇÑ´Ù. Selection°ú targetµéÀº ¸ðµÎ atom¿¡ ÀÇÇÏ¿© ½Äº°µÈ´Ù.

17.2 SelectionÀ» º¹±¸Çϱâ

SelectionÀ» µÇã´Â´Ù´Â °ÍÀº ÇϳªÀÇ ºñµ¿½Ã¼ºÀÇ °úÁ¤ÀÌ´Ù. ÀÌ °úÁ¤À» ½ÃÀÛ Çϱâ À§ÇØ ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù.

gint gtk_selection_convert   (GtkWidget           *widget,
                              GdkAtom              selection,
                              GdkAtom              target,
                              guint32              time)

ÀÌ°ÍÀº target¿¡ ÀÇÇØ ¼³Á¤µÈ ÇüÅ·ΠselectionÀ» º¯È¯ÇÑ´Ù. ¸¸¾à °¡´ÉÇÏ´Ù¸é, time ÀÎÀÚ´Â selectionÀ» °áÁ¤ÇÑ À̺¥Æ®·ÎºÎÅÍÀÇ ½Ã°£ÀÌ µÇ¾î¾ß ÇÑ´Ù. ÀÌ°ÍÀº »ç¿ëÀÚ°¡ ¿äûÇÑ ¼ø¼­´ë·Î À̺¥Æ®°¡ ¹ß»ýÇÏ´Â °ÍÀ» È®½ÇÈ÷ ÇØÁØ´Ù. ±×·¯³ª ¸¸¾à ÀÌ°ÍÀÌ ¾²¿©Áú ¼ö ¾ø´Ù¸é(¿¹¸¦µé¾î º¯È¯ÀÌ "clicked"½Ã±×³Î¿¡ ÀÇÇØ ÀÌ·ç¾îÁ³´Ù¸é) ¿ì¸®´Â »ó¼ö GDK_CURRENT_TIME¸¦ ÀÌ¿ëÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù.

Selecting owner°¡ ¾î¶² ¿ä±¸¿¡ ¹ÝÀÀÇϸé "selection_received"¶ó´Â ½Ã±×³ÎÀÌ ¿ì¸®ÀÇ ¾îÇÿ¡ º¸³»Áö°Ô µÈ´Ù. ÀÌ ½Ã±×³Î¿¡ ´ëÇÑ Çڵ鷯´Â ¾Æ·¡¿Í °°ÀÌ Á¤ÀÇµÈ GtkSelectionData ±¸Á¶Ã¼¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ¹Þ´Â´Ù.

struct _GtkSelectionData
{
  GdkAtom selection;
  GdkAtom target;
  GdkAtom type;
  gint    format;
  guchar *data;
  gint    length;
};

ÀÎÀÚ selection°ú targetÀº ¿ì¸®°¡ gtk_selection_convert()ÇÔ¼ö¿¡ ÁØ °ªµéÀÌ´Ù. ÀÎÀÚ typeÀº selection owner¿¡ ÀÇÇØ ¸®ÅÏµÈ µ¥ÀÌÅÍ Å¸ÀÔÀ» ½Äº°ÇÏ´Â atomÀÌ´Ù. ¸î°¡Áö °¡´ÉÇÑ °ªÀ¸·Î´Â ¶óƾ ¹®ÀÚÀÇ ¹®ÀÚ¿­ "STRING", atomÀÇ ½Ã¸®Áî "ATOM", ÇϳªÀÇ Á¤¼ö "INTEGER" µîÀÌ ÀÖ´Ù. ´ëºÎºÐÀÇ targetµéÀº ¿ÀÁ÷ ÇÑ °¡Áö typeÀ» ¸®ÅÏÇÒ ¼ö ÀÖ´Ù. ÀÎÀÚ formatÀº °¢ ´ÜÀ§ÀÇ ±æÀ̸¦ ºñÆ® ´ÜÀ§·Î ÁØ °ÍÀÌ´Ù. º¸Åë, µ¥ÀÌÅ͸¦ ¹ÞÀ» ¶© ÀÌ°Í¿¡ ´ëÇؼ­ ½Å°æ¾µ ÇÊ¿ä°¡ ¾ø´Ù. ÀÎÀÚ data´Â ¸®ÅÏµÈ µ¥ÀÌÅÍ¿¡ ´ëÇÑ Æ÷ÀÎÅ͸ç, length´Â ÀÌ µ¥ÀÌÅÍÀÇ ±æÀ̸¦ ¹ÙÀÌÆ® ´ÜÀ§·Î ÁØ °ÍÀÌ´Ù. ¸¸¾à length°¡ À½¼ö¶ó¸é ¿¡·¯°¡ ¹ß»ýÇÑ °ÍÀÌ°í selectionÀº º¹±¸µÉ ¼ö ¾øÀ» °ÍÀÌ ´Ù. ÀÌ°ÍÀº ±× selectionÀ» ¼ÒÀ¯ÇÑ ¾îÇÃÀÌ ¾ø°Å³ª, ¶Ç´Â ¾îÇÃÀÌ Áö¿øÇÏÁö ¾Ê´Â targetÀ» ¿äûÇßÀ» ¶§ ÀϾ ¼ö ÀÖ´Â ÀÏÀÌ´Ù. ½ÇÁ¦·Î ¹öÆÛ´Â lengthº¸´Ù 1¹ÙÀÌÆ® ±æ°Ô µÇ´Â °ÍÀ» º¸Àå¹Þ´Â´Ù. ³²´Â ¹ÙÀÌÆ®´Â ¾ðÁ¦³ª zero°¡ µÉ °ÍÀÌ°í, µû¶ó¼­ NULL·Î½á ¹®ÀÚ¿­À» ³¡³»±â À§ÇØ µû·Î ¹®ÀÚ¿­ÀÇ º¹»çº»À» ¸¸µé¾î µÑ ÇÊ¿ä°¡ ¾ø´Ù.

À̹ø ¿¹Á¦¿¡¼­, ¿ì¸®´Â "TARGETS"¶ó´Â Ưº°ÇÑ targetÀ» º¹±¸ÇÒ °ÍÀÌ´Ù. ÀÌ°ÍÀº selectionÀÌ º¯È¯µÉ ¼ö ÀÖ´Â ¸ðµç targetÀÇ ¸®½ºÆ®ÀÌ´Ù.

#include <gtk/gtk.h>

void selection_received (GtkWidget *widget,
                         GtkSelectionData *selection_data,
                         gpointer data);

/* »ç¿ëÀÚ°¡ "Get Targets" ¹öÆ°À» Ŭ¸¯ÇßÀ» ¶§ ¿äûµÇ´Â ½Ã±×³Î Çڵ鷯 */
void
get_targets (GtkWidget *widget, gpointer data)
{
  static GdkAtom targets_atom = GDK_NONE;

  /* ¹®ÀÚ¿­ "TARGETS"¿¡ ÇØ´çÇÏ´Â atomÀ» ÃëÇÑ´Ù. */
  if (targets_atom == GDK_NONE)
    targets_atom = gdk_atom_intern ("TARGETS", FALSE);

  /* ±×¸®°í primary selectionÀ¸·Î¼­ "TARGETS"¶ó´Â targetÀ» ¿äûÇÑ´Ù. */
  gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
                         GDK_CURRENT_TIME);
}

/* Selection owner°¡ µ¥ÀÌÅ͸¦ ¸®ÅÏÇßÀ» ¶§ ºÒ·ÁÁö´Â ½Ã±×³Î Çڵ鷯 */
void
selection_received (GtkWidget *widget, GtkSelectionData *selection_data,
                      gpointer data)
{
  GdkAtom *atoms;
  GList *item_list;
  int i;

  /* **** Áß¿ä **** SelectionÀÇ º¹±¸°¡ ¼º°øÇÏ´ÂÁö üũÇÒ °Í. */
  if (selection_data->length < 0)
    {
      g_print ("Selection retrieval failed\n");
      return;
    }
  /* ±â´ëÇÑ ÇüÅ·Πµ¥ÀÌÅ͸¦ ÃëÇßÀ½À» È®ÀÎÇÑ´Ù. */
  if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
    {
      g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
      return;
    }

  /* ¿ì¸®°¡ ÀüÇعÞÀº atomÀ» ÇÁ¸°Æ®ÇÑ´Ù. */
  atoms = (GdkAtom *)selection_data->data;

  item_list = NULL;
  for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
    {
      char *name;
      name = gdk_atom_name (atoms[i]);
      if (name != NULL)
        g_print ("%s\n",name);
      else
        g_print ("(bad atom)\n");
    }

  return;
}

int
main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *button;

  gtk_init (&argc, &argv);

  /* Toplevel À©µµ¸¦ ¸¸µç´Ù. */

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Event Box");
  gtk_container_border_width (GTK_CONTAINER (window), 10);

  gtk_signal_connect (GTK_OBJECT (window), "destroy",
                      GTK_SIGNAL_FUNC (gtk_exit), NULL);

  /* »ç¿ëÀÚ°¡ targetÀ» ÃëÇÏ·Á°í Ŭ¸¯ÇÒ ¼ö ÀÖ´Â ¹öÆ°À» ¸¸µç´Ù. */

  button = gtk_button_new_with_label ("Get Targets");
  gtk_container_add (GTK_CONTAINER (window), button);

  gtk_signal_connect (GTK_OBJECT(button), "clicked",
                        GTK_SIGNAL_FUNC (get_targets), NULL);
  gtk_signal_connect (GTK_OBJECT(button), "selection_received",
                        GTK_SIGNAL_FUNC (selection_received), NULL);

  gtk_widget_show (button);
  gtk_widget_show (window);

  gtk_main ();

  return 0;
}

17.3 SelectionÀ» Á¦°øÇϱâ

SelectionÀ» Á¦°øÇÏ´Â °ÍÀº Á¶±Ý ´õ º¹ÀâÇÏ´Ù. ¿ì¸®´Â ¿ì¸®ÀÇ selectionÀÌ ¿äûµÇ¾úÀ» ¶§ È£ÃâµÉ Çڵ鷯µéÀ» µî·ÏÇØ µÖ¾ß ÇÑ´Ù. ¿ì¸®°¡ ´Ù·ê °¢°¢ÀÇ selection/target ½Öµé¿¡ ´ëÇØ ÀÌ·± È£ÃâÀ» ÇÏ´Â °ÍÀÌ´Ù.

void gtk_selection_add_handler (GtkWidget           *widget,
                                GdkAtom              selection,
                                GdkAtom              target,
                                GtkSelectionFunction function,
                                GtkRemoveFunction    remove_func,
                                gpointer             data);

widget, selection, targetÀº ÀÌ Çڵ鷯°¡ °ü¸®ÇÒ ¿äû(request)À» ½Äº°ÇÑ´Ù. remove_func ÀÎÀÚ´Â ½Ã±×³Î Çڵ鷯°¡ Á¦°ÅµÉ ¶§ NULLÀÌ ¾Æ´Ñ °ªÀÌ µÈ´Ù. ÀÌ°Ç ¿¹¸¦µé¾î, ÀÎÅÍÇÁ¸®ÅÍ ¾ð¾î°°ÀÌ µ¥ÀÌÅÍ¿¡ ´ëÇÑ reference countÀÇ Æ®·¢À» À¯ÁöÇÒ Çʿ伺ÀÌ ÀÖ´Â °æ¿ì µî¿¡ À¯¿ëÇÏ´Ù.

ÀÌ·± ¸ð¾çÀÇ callback ÇÔ¼ö¸¦ º¸ÀÚ.

typedef void (*GtkSelectionFunction) (GtkWidget *widget,
                                      GtkSelectionData *selection_data,
                                      gpointer data);

GtkSelectionData´Â À§¿¡¼­ÀÇ °æ¿ì¿Í °°Àº °ÍÀÌÁö¸¸, À̹ø¿£ ¿ì¸®´Â Çʵ带 type, format, data, ±×¸®°í length·Î ä¿ö¾ß ÇÑ´Ù. (Çʵå formatÀº ¿©±â¼­ ½ÇÁ¦·Î Áß¿äÇÏ´Ù. X ¼­¹ö´Â µ¥ÀÌÅÍ°¡ byte-swapµÇ¾î¾ß ÇÏ´ÂÁöÀÇ ¿©ºÎ¸¦ ÀÌ°Í À¸·Î½á °áÁ¤ÇÑ´Ù. º¸Åë ÀÌ°ÍÀº 8 Áï ÇϳªÀÇ ¹®ÀÚÀ̰ųª, ¶Ç´Â 32 Áï Á¤¼ö°¡ µÈ´Ù.) ÀÌ°Ç ÀÌ ÇÔ¼ö¸¦ È£ÃâÇؼ­ ÀÌ·ç¾îÁø´Ù.

void gtk_selection_data_set (GtkSelectionData *selection_data,
                             GdkAtom           type,
                             gint              format,
                             guchar           *data,
                             gint              length);

ÀÌ ÇÔ¼ö´Â ÀûÀýÈ÷ µ¥ÀÌÅÍÀÇ º¹»çº»À» ¸¸µéµµ·Ï ÇØÁֱ⠶§¹®¿¡ ¿ì¸®´Â µû·Î ÀÌ°Í¿¡ ½Å°æ¾µ ÇÊ¿ä°¡ ¾ø´Ù. (¿ì¸®´Â Á÷Á¢ GtkSelectionDataÀÇ ÇʵåµéÀ» ä¿ö ÁÖÁö ¾Ê¾Æµµ µÈ´Ù´Â ¸»ÀÌ´Ù.)

¿ì¸®´Â ´ÙÀ½ ÇÔ¼ö¸¦ È£ÃâÇؼ­ selectionÀÇ ¼ÒÀ¯±Ç(ownership)À» Á¦½ÃÇÒ ¼ö ÀÖ´Ù.

gint gtk_selection_owner_set (GtkWidget           *widget,
                              GdkAtom              selection,
                              guint32              time);

¸¸¾à ¶Ç´Ù¸¥ ¾îÇÃÀÌ selectionÀÇ ¼ÒÀ¯±ÇÀ» Á¦½ÃÇÑ´Ù¸é, ¿ì¸®´Â "selection_ clear_event"¸¦ ¹Þ°ÔµÉ °ÍÀÌ´Ù.

SelectionÀ» Á¦°øÇÏ´Â ¿¹Á¦·Î¼­, ´ÙÀ½ ÇÁ·Î±×·¥Àº ¾î¶² Åä±Û¹öÆ°¿¡ selection ±â´ÉÀ» ÷°¡ÇÒ °ÍÀÌ´Ù. ÀÌ Åä±Û¹öÆ°ÀÌ ´­·ÁÁø »óŶó¸é, ÇÁ·Î±×·¥Àº primary selectionÀ» Á¦±âÇÒ °ÍÀÌ´Ù. GTK ÀÚü¿¡ ÀÇÇØ ÁÖ¾îÁö´Â "TARGETS" °°Àº °ÍÀº Á¦ÃÄ µÎ°í, ¿©±â¼­ ÁÖ¾îÁø À¯ÀÏÇÑ targetÀº "STRING" targetÀÌ´Ù. ÀÌ targetÀÌ ¿äûµÇ¸é, ½Ã°¢À» º¸¿©ÁÖ´Â ÇÑ ¹®ÀÚ¿­ÀÌ ¸®ÅϵȴÙ.

#include <gtk/gtk.h>
#include <time.h>

/* »ç¿ëÀÚ°¡ selectionÀ» Åä±ÛÇÒ ¶§ È£ÃâµÇ´Â callback. */
void
selection_toggled (GtkWidget *widget, gint *have_selection)
{
  if (GTK_TOGGLE_BUTTON(widget)->active)
    {
      *have_selection = gtk_selection_owner_set (widget,
                                                 GDK_SELECTION_PRIMARY,
                                                 GDK_CURRENT_TIME);
      /* SelectionÀ» ¿ä±¸ÇÏ´Â µ¥ ½ÇÆÐÇϸé, out state·Î ±× ¹öÆ°À»
       * ¸®ÅÏÇÑ´Ù. */
      if (!*have_selection)
        gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);
    }
  else
    {
      if (*have_selection)
        {
          /* Selection owner¸¦ NULL·Î Çؼ­ selectionÀ» ºñ¿ì±â Àü¿¡,
           * ¿ì¸®°¡ ÇöÀç ½ÇÁ¦ÀÇ ownerÀÎÁö üũÇÏÀÚ. */
          if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
            gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
                                     GDK_CURRENT_TIME);
          *have_selection = FALSE;
        }
    }
}

/* ´Ù¸¥ ¾îÇÃÀÌ selectionÀ» Á¦±âÇßÀ» ¶§ È£ÃâµÈ´Ù. */
gint
selection_clear (GtkWidget *widget, GdkEventSelection *event,
                 gint *have_selection)
{
  *have_selection = FALSE;
  gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON(widget), FALSE);

  return TRUE;
}

/* SelectionÀ¸·Î¼­ ÇöÀç ½Ã°¢À» Á¦°øÇÑ´Ù. */
void
selection_handle (GtkWidget *widget,
                  GtkSelectionData *selection_data,
                  gpointer data)
{
  gchar *timestr;
  time_t current_time;

  current_time = time (NULL);
  timestr = asctime (localtime(&current_time));
  /* ¿ì¸®°¡ ÇϳªÀÇ ½ºÆ®¸µÀ» ¸®ÅÏÇÒ ¶§, µû·Î NULL ¹®ÀÚ·Î ³¡À» ³»Áö
   * ¾Ê¾Æµµ µÈ´Ù.  ÀÌ¹Ì Ã³¸®µÇ¾î Àֱ⠶§¹®ÀÌ´Ù. */

  gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
                          8, timestr, strlen(timestr));
}

int
main (int argc, char *argv[])
{
  GtkWidget *window;

  GtkWidget *selection_button;
  static int have_selection = FALSE;

  gtk_init (&argc, &argv);

  /* Toplevel À©µµ¸¦ ¸¸µç´Ù. */

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Event Box");
  gtk_container_border_width (GTK_CONTAINER (window), 10);

  gtk_signal_connect (GTK_OBJECT (window), "destroy",
                      GTK_SIGNAL_FUNC (gtk_exit), NULL);

  /* SelectionÀ¸·Î¼­ µ¿ÀÛÇÒ Åä±Û¹öÆ°À» Çϳª ¸¸µç´Ù. */

  selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
  gtk_container_add (GTK_CONTAINER (window), selection_button);
  gtk_widget_show (selection_button);

  gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
                      GTK_SIGNAL_FUNC (selection_toggled), &have_selection);
  gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
                      GTK_SIGNAL_FUNC (selection_clear), &have_selection);

  gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
                             GDK_SELECTION_TYPE_STRING,
                             selection_handle, NULL, NULL);

  gtk_widget_show (selection_button);
  gtk_widget_show (window);

  gtk_main ();

  return 0;
}


´ÙÀ½ ÀÌÀü Â÷·Ê