¸®´ª½º ±âŸ ÀÚ·á |
---|
Á¦¸ñ | gtk °Á #14 1998/07/10 (17:35) |
À̸§ | ±èÈ¿¿ø |
¹øÈ£ | 98 |
Á¶È¸ | 309 |
º»¹® |
*** *** 20-4. Input support¸¦ ´õÇϱâ *** ÀÌÁ¦ drawing tablet °°ÀÌ, ±×´ÙÁö ºñ½ÎÁö ¾ÊÀ¸¸é¼ ¸¶¿ì½ºº¸´Ù ÈξÀ ¿¹¼úÀûÀΠǥÇöÀ» ÆíÇÏ°Ô ±×¸± ¼ö ÀÖ°Ô ÇØÁÖ´Â ÀÔ·ÂÀåÄ¡(input device)¸¦ ±¸ÀÔÇÏ´Â °ÍÀÌ °¡´ÉÇÑ ½Ã´ë´Ù. ÀÌ·± ÀåÄ¡¸¦ ÀÌ¿ëÇÏ´Â °¡Àå °£´ÜÇÑ ¹æ¹ýÀÌ¾ß °£´ÜÈ÷ ¸¶¿ì½º¸¦ ´ëÄ¡ÇØ ¹ö¸®´Â °ÍÀÌ°ÚÁö¸¸, ÀÌ·² °æ¿ì ±×·± ÀÔ·ÂÀåÄ¡ÀÇ ´ÙÀ½°ú °°Àº ¸¹Àº ÀåÁ¡À» ÀÒ°Ô µÉ ¼öµµ ÀÖ´Ù. o Pressure sensitivity o Tilt reporting o Sub-pixel positioning o Multiple inputs (for example, a stylus with a point and eraser) XInput extension¿¡ ´ëÇÑ Á¤º¸¸¦ ¾òÀ¸·Á¸é XInput-HOWTO <http://www.msc. cornell.edu/~otaylor/xinput/XInput-HOWTO.html> ¸¦ º¸¶ó. ¿¹¸¦µé¾î GdkEvent Motion ±¸Á¶Ã¼ÀÇ Àüü Á¤ÀÇ°°Àº °É ºÁµµ, extended device¸¦ Áö¿øÇϱâ À§ÇÑ Çʵ带 °¡Áö°í ÀÖÀ½À» ¾Ë °ÍÀÌ´Ù. struct _GdkEventMotion { GdkEventType type; GdkWindow *window; guint32 time; gdouble x; gdouble y; gdouble pressure; gdouble xtilt; gdouble ytilt; guint state; gint16 is_hint; GdkInputSource source; guint32 deviceid; }; pressure ÀÎÀÚ´Â 0°ú 1 »çÀÌÀÇ ºÎµ¿¼Ò¼öÁ¡¼ö·Î µÈ pressure¸¦ ÁØ´Ù. xtilt¿Í ytile´Â °¢ ¹æÇâÀ¸·ÎÀÇ tilt °¢µµ¿¡ ÇØ´çÇÏ´Â -1ºÎÅÍ 1 »çÀÌÀÇ °ªÀ» °¡Áú ¼ö ÀÖ´Ù. source¿Í deviceid ÀÎÀÚ´Â µÎ°¡Áö ´Ù¸¥ ¹æ½ÄÀ¸·Î ¹ß»ýÇÑ À̺¥Æ®¿¡ ´ëÇØ ÀåÄ¡(device)¸¦ ¼³Á¤ÇÑ´Ù. source´Â ÀåÄ¡ÀÇ Å¸ÀÔ¿¡ ´ëÇÑ °£´ÜÇÑ Á¤º¸¸¦ ÁØ´Ù. ÀÌ°ÍÀº ´ÙÀ½ÀÇ enumeration °ªµéÀ» °¡Áú ¼ö ÀÖ´Ù. GDK_SOURCE_MOUSE GDK_SOURCE_PEN GDK_SOURCE_ERASER GDK_SOURCE_CURSOR deviceid´Â °¢ ÀåÄ¡¿¡ ´ëÇØ °íÀ¯ÀÇ ¼ýÀÚ ID¸¦ ¼³Á¤ÇÑ´Ù. ÀÌ°ÍÀº gdk_input_ list_devices()ÇÔ¼ö·Î(µÚ¿¡ ³ª¿È) ±× ÀåÄ¡¿¡ ´ëÇÑ ´õ ¸¹Àº Á¤º¸¸¦ Á¶»çÇÏ°íÀÚ ÇÒ ¶§ ¾²ÀÏ ¼ö ÀÖ´Ù. Core pointer device(º¸Åë ¸¶¿ì½º)¿¡ ´ëÇØ Æ¯º°È÷ GDK_CORE_ POINTER¶ó´Â »ó¼ö°ªÀÌ ¾²ÀδÙ. *** *** 20-4.1. Extended device Á¤º¸¸¦ »ç¿ë°¡´ÉÇÏ°Ô Çϱâ *** GTK¿¡°Ô ¿ì¸®°¡ °ü½ÉÀ» °¡Áø extended deviceÀÇ Á¤º¸°¡ ¹«¾ùÀÎÁö ¾Ë·Á ÁÖ·Á¸é, ¿ì¸® ÇÁ·Î±×·¥¿¡ ´Ü ÇÑ ÁÙ¸¸ ´õÇØÁÖ¸é µÈ´Ù. gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR); GDK_EXTENSION_EVENTS_CURSOR¶ó´Â °ªÀ» ÁÜÀ¸·Î½á ¿ì¸®´Â È®ÀåµÈ À̺¥Æ®µé¿¡ °ü½ÉÀÌ ÀÖÀ½À» ¾Ë¸°´Ù. ´Ü, À̶§ ¿ì¸®´Â »õ·Î Ä¿¼¸¦ ±×·Á¼´Â ¾ÈµÈ´Ù. Ä¿¼¸¦ ±×¸®´Â ¹®Á¦¿¡ ´ëÇؼ´Â µÚ¿¡ ³ª¿Ã '´õ º¹ÀâÇÑ ÀÌ¿ë' ºÎºÐÀ» ÂüÁ¶Ç϶ó. ¿ì¸®°¡ ¿ì¸®¸¸ÀÇ Ä¿¼¸¦ ±×¸®·Á ÇÑ´Ù¸é GDK_EXTENSION_EVENTS_ALLÀ» ¾²¸é µÇ°í, µðÆúÆ® ·Î µ¹¾Æ°¡·Á¸é GDK_EXTENSION_EVENTS_NONEÀ» ¾´´Ù. À̾߱â´Â ÀÌ°ÍÀ¸·Î ³¡³ªÁö ¾Ê´Â´Ù. µðÆúÆ®·Î, extension device´Â disable µÇ¾î ÀÖ´Ù. ¿ì¸®´Â »ç¿ëÀÚ·Î ÇÏ¿©±Ý ±×µéÀÇ extension deviceµéÀ» enable½ÃÅ°°í ¼³Á¤ÇÒ ¼ö ÀÖ°Ô ÇØÁÖ´Â ¸ÅÄ¿´ÏÁòÀÌ ÇÊ¿äÇÏ´Ù. GTK´Â ÀÌ °úÁ¤À» ÀÚµ¿ÀûÀ¸·Î ÇØ ÁÖ´Â InputDialog widgetÀ» Á¦°øÇÑ´Ù. ´ÙÀ½°ú °°Àº °úÁ¤´ë·Î InputDialog widgetÀ» °ü¸®ÇÑ´Ù. ÀÌ°ÍÀº device°¡ Á¸ÀçÇÏÁö ¾ÊÀ¸¸é dialog·Î ¾Ë·ÁÁÖ°í, ³ª¸ÓÁö °æ¿ì¿£ topÀ¸·Î ¿Ã·Áº¸³½´Ù. void input_dialog_destroy (GtkWidget *w, gpointer data) { *((GtkWidget **)data) = NULL; } void create_input_dialog () { static GtkWidget *inputd = NULL; if (!inputd) { inputd = gtk_input_dialog_new(); gtk_signal_connect (GTK_OBJECT(inputd), "destroy", (GtkSignalFunc)input_dialog_destroy, &inputd); gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button), "clicked", (GtkSignalFunc)gtk_widget_hide, GTK_OBJECT(inputd)); gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button); gtk_widget_show (inputd); } else { if (!GTK_WIDGET_MAPPED(inputd)) gtk_widget_show(inputd); else gdk_window_raise(inputd->window); } } (¿ì¸®°¡ ÀÌ dialog¸¦ ´Ù·ç´Â ¹æ¹ý¿¡ ÁÖÀǸ¦ ±â¿ï¿©¾ß ÇÒ °ÍÀÌ´Ù. "destroy" ½Ã±×³Î¿¡ ¿¬°á½ÃÄÑ µÎ´Â °ÍÀ¸·Î, ¿ì¸®´Â dialog°¡ Æı«µÈ ÀÌÈÄ Æ÷ÀÎÅ͸¦ dialog ¿¡ ³²°ÜµÎ´Â ½Ç¼ö - ÀÌ°ÍÀº Segfault(!)¸¦ ºÎ¸¥´Ù - ¸¦ ÇÇÇÒ ¼ö ÀÖ´Ù.) InputDialog´Â "Close" ±×¸®°í "Save"¶ó´Â µÎ ¹öÆ°À» °¡Áö°í ÀÖÀ¸¸ç, µðÆúÆ® ·Î´Â ¾Æ¹«·± µ¿ÀÛÀÌ ¿¬°áµÇ¾î ÀÖÁö ¾Ê´Ù. À§¿¡¼´Â "Close" ¹öÆ°À» dialog¸¦ °¨Ãߴµ¥ ½è°í, "Save" ¹öÆ°Àº °¨Ãß¾î ¹ö·È´Ù. ÀÌ ÇÁ·Î±×·¥¿¡¼ XInputÀ» ÀúÀå ÇÏ´Â ¿É¼ÇÀ» °®ÃßÁö ¾Ê¾Ò±â ¶§¹®ÀÌ´Ù. *** *** 20.4.2. Extended device Á¤º¸¸¦ ÀÌ¿ëÇϱâ *** ÀÏ´Ü ÀåÄ¡(device)¸¦ enable½ÃÄ×À¸¸é, ¿ì¸®´Â À̺¥Æ® ±¸Á¶Ã¼ÀÇ ³ª¸ÓÁö Çʵ忡 ÀÖ´Â extended deviceÀÇ Á¤º¸¸¦ ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù. »ç½Ç, ÀÌ Á¤º¸¸¦ ÀÌ¿ëÇÏ´Â °Ç ¾ðÁ¦³ª ¾ÈÀüÇÏ´Ù. Extended event°¡ disableµÇ¾î ÀÖ´õ¶óµµ À̵éÀº ÀûÀýÇÑ µðÆúÆ®°ªÀ» °¡Áö°í Àֱ⠶§¹®ÀÌ´Ù. ÇÑ °¡Áö ÁÖÀÇÇÒ °ÍÀº gdk_window_get_pointer() ´ë½Å¿¡ gdk_input_window_get_ pointer()¸¦ È£ÃâÇÑ´Ù´Â °ÍÀÌ´Ù. ÀÌ°ÍÀº gdk_window_get_pointer°¡ extended device Á¤º¸¸¦ ¸®ÅÏÇÏÁö ¸øÇϱ⠶§¹®ÀÌ´Ù. void gdk_input_window_get_pointer (GdkWindow *window, guint32 deviceid, gdouble *x, gdouble *y, gdouble *pressure, gdouble *xtilt, gdouble *ytilt, GdkModifierType *mask); ÀÌ ÇÔ¼ö¸¦ ºÎ¸¦ ¶§, À©µµÀÇ °æ¿ì¿Í ¸¶Âù°¡Áö·Î deviceÀÇ ID¸¦ ¸í½ÃÇØ Áà¾ß ÇÑ´Ù. º¸Åë, ¿ì¸®´Â device ID¸¦ event ±¸Á¶Ã¼ÀÇ deviceid Çʵå·ÎºÎÅÍ ÃëÇÒ °ÍÀÌ´Ù. ´Ù½Ã Çѹø, ÀÌ ÇÔ¼ö´Â extension event°¡ disableµÈ »óÅ¿¡¼µµ ÇÕ´çÇÑ °ªÀ» ¸®ÅÏÇÔÀ» ±â¾ïÇÏÀÚ. (ÀÌ °æ¿ì¿£, event->deviceid´Â GDK_CORE_POINTER¶ó´Â °ªÀ» °¡Áú °ÍÀÌ´Ù.) ±×·¡¼ ¿ì¸®ÀÇ button-press ¿Í motion À̺¥Æ® Çڵ鷯ÀÇ ±âº»ÀûÀÎ ±¸Á¶´Â ±×¸® º¯ÇÏÁö ¾Ê´Â´Ù - ¿ì¸° ´ÜÁö extended¿¡ ÇØ´çÇÏ´Â Á¤º¸¸¦ ´Ù·ê Äڵ带 Ãß°¡Çϱ⸸ ÇÏ¸é µÈ´Ù. static gint button_press_event (GtkWidget *widget, GdkEventButton *event) { print_button_press (event->deviceid); if (event->button == 1 && pixmap != NULL) draw_brush (widget, event->source, event->x, event->y, event->pressure); return TRUE; } static gint motion_notify_event (GtkWidget *widget, GdkEventMotion *event) { gdouble x, y; gdouble pressure; GdkModifierType state; if (event->is_hint) gdk_input_window_get_pointer (event->window, event->deviceid, &x, &y, &pressure, NULL, NULL, &state); else { x = event->x; y = event->y; pressure = event->pressure; state = event->state; } if (state & GDK_BUTTON1_MASK && pixmap != NULL) draw_brush (widget, event->source, x, y, pressure); return TRUE; } ¿ì¸° ¶ÇÇÑ »õ·Î¿î Á¤º¸¸¦ ÀÌ¿ëÇÏ´Â ÀÏÀ» ¹º°¡ ÇØ¾ß ÇÑ´Ù. ¿ì¸®ÀÇ draw_brush() ÇÔ¼ö´Â °¢ event->source¸¶´Ù ´Ù¸¥ »ö±ò·Î ±×¸± ¼ö ÀÖ°Ô ÇÏ°í, ±×¸®°í pressure¿¡ µû¶ó brushÀÇ Å©±â¸¦ º¯ÇÏ°Ô ÇÑ´Ù. /* ½ºÅ©¸°¿¡ »ç°¢ÇüÀ» ±×¸°´Ù. Å©±â´Â pressure¿¡ ÀÇÁ¸ÇÏ°í, * ±×¸®°í »ö±òÀº deviceÀÇ Å¸ÀÔ¿¡ ÀÇÁ¸ÇÑ´Ù. */ static void draw_brush (GtkWidget *widget, GdkInputSource source, gdouble x, gdouble y, gdouble pressure) { GdkGC *gc; GdkRectangle update_rect; switch (source) { case GDK_SOURCE_MOUSE: gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)]; break; case GDK_SOURCE_PEN: gc = widget->style->black_gc; break; case GDK_SOURCE_ERASER: gc = widget->style->white_gc; break; default: gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)]; } update_rect.x = x - 10 * pressure; update_rect.y = y - 10 * pressure; update_rect.width = 20 * pressure; update_rect.height = 20 * pressure; gdk_draw_rectangle (pixmap, gc, TRUE, update_rect.x, update_rect.y, update_rect.width, update_rect.height); gtk_widget_draw (widget, &update_rect); } *** *** 20.4.3. Device¿¡ ´ëÇØ ´õ ¸¹Àº °É ¾Ë¾Æ³»±â *** Device¿¡ ´ëÇÑ Á¤º¸¸¦ ¾î¶»°Ô ´õ ¾Ë¾Æ³»´ÂÁö º¸¿©ÁÖ´Â ¿¹Á¦·Î¼, ¿ì¸® ÇÁ·Î ±×·¥Àº °¢ ¹öÆ°À» ´©¸£¸é deviceÀÇ À̸§À» ÇÁ¸°Æ®ÇÒ °ÍÀÌ´Ù. DeviceÀÇ À̸§À» ¾Ë¾Æ³»±â À§ÇÏ¿© ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù. GList *gdk_input_list_devices (void); ÀÌ°ÍÀº GdkDeviceInfo ±¸Á¶Ã¼ÀÇ GList(glib ¶óÀ̺귯¸®¿¡¼ ¿Â ¿¬°á¸®½ºÆ® ŸÀÔ)¸¦ ¸®ÅÏÇÑ´Ù. GdkDeviceInfo ±¸Á¶Ã¼´Â ÀÌ·¸°Ô Á¤ÀǵǾî ÀÖ´Ù. struct _GdkDeviceInfo { guint32 deviceid; gchar *name; GdkInputSource source; GdkInputMode mode; gint has_cursor; gint num_axes; GdkAxisUse *axes; gint num_keys; GdkDeviceKey *keys; }; ¿©±âÀÖ´Â ´ëºÎºÐÀÇ Çʵå´Â ¿©·¯ºÐÀÌ XInput ¼³Á¤À» ÀúÀåÇÏ´Â ±â´ÉÀ» Ãß°¡ÇÏÁö ¾Ê¾Ò´Ù¸é ¹«½ÃÇصµ ±¦ÂúÀº ¼³Á¤ Á¤º¸µéÀÌ´Ù. Áö±Ý ¿ì¸®°¡ °ü½ÉÀ» °¡Áø °ÍÀº ´Ü¼øÈ÷ X°¡ device¿¡ ºÎ¿©ÇÑ À̸§(name)ÀÌ´Ù. ¼³Á¤(configuration)Çʵ忡 ÇØ´çÇÏÁö ¾Ê´Â °ÍÀº has_cursorÀÌ´Ù. ±×·±µ¥ ¿ì¸®´Â GDK_EXTENSION_EVENTS_ CURSOR¸¦ ¼³Á¤ÇßÀ¸¹Ç·Î, ÀÌ Çʵ忡 ´ëÇؼ´Â °ÆÁ¤ÇÏÁö ¸»ÀÚ. print_button_press() ÇÔ¼ö´Â ¸ÅÄ¡µÇ´Â ¸®½ºÆ®¸¦ ¸®ÅÏÇÒ ¶§±îÁö ´Ü¼øÈ÷ ¹Ýº¹µÉ °ÍÀ̸ç, deviceÀÇ À̸§À» ÇÁ¸°Æ®ÇØ ÁÙ °ÍÀÌ´Ù. static void print_button_press (guint32 deviceid) { GList *tmp_list; /* gdk_input_list_devices´Â ³»ºÎÀûÀÎ ¸®½ºÆ®¸¦ ¸®ÅÏÇϸç, * µû¶ó¼ ¿ì¸®´Â ÈÄ¿¡ ÀÌ°ÍÀ» ÇØÁ¦ÇØ ÁÖÁö ¾ÊÀ» °ÍÀÌ´Ù. */ tmp_list = gdk_input_list_devices(); while (tmp_list) { GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data; if (info->deviceid == deviceid) { printf("Button press on device '%s'\n", info->name); return; } tmp_list = tmp_list->next; } } *** *** 20-4.4. ´õ º¹ÀâÇÑ ÀÌ¿ë *** ºñ·Ï ¿ì¸® ÇÁ·Î±×·¥ÀÌ ÀÌÁ¦ XInputÀ» ²Ï Àß Áö¿øÇÔ¿¡µµ ºÒ±¸ÇÏ°í, ¾îÇà ÀüüÀû À¸·Î ºÁ¼ ¹º°¡ ºÎÁ·ÇØ º¸ÀÌ´Â ¸éµµ ÀÖ´Ù. ¸ÕÀú, »ç¿ëÀÚ´Â ÇÁ·Î±×·¥À» ½ÇÇàÇÒ ¶§¸¶´Ù ±×µéÀÇ ÀåÄ¡µéÀ» ¼³Á¤ÇÏ·Á°í ÇÏÁø ¾ÊÀ» °ÍÀ̹ǷÎ, ¿ì¸®´Â ±× ÀåÄ¡µéÀÇ ¼³Á¤À» ÀúÀåÇÒ ¼ö ÀÖµµ·Ï ÇØÁà¾ß ÇÑ´Ù. ÀÌ°ÍÀº gdk_input_list_devices()ÀÇ ¸®ÅÏÀ» µÇÇ®ÀÌÇÏ°í, ¼³Á¤À» ÆÄÀÏ¿¡ ±â·Ï(write)ÇÏ´Â °ÍÀ¸·Î ÀÌ·ç¾îÁø´Ù. ÇÁ·Î ±×·¥ÀÌ ´ÙÀ½ ¹ø ½ÇÇàµÉ ¶§ ÇöÀçÀÇ state¸¦ º¹±¸ÇØ ÁÖ±â À§Çؼ, GDK´Â device ¼³Á¤¿¡ ´ëÇÑ ´ÙÀ½ ÇÔ¼öµéÀ» Á¦°øÇÑ´Ù. gdk_input_set_extension_events() gdk_input_set_source() gdk_input_set_mode() gdk_input_set_axes() gdk_input_set_key() (gdk_input_list_devices()°¡ ¸®ÅÏÇÑ ¸®½ºÆ®´Â Á¤È®È÷ º¯°æµÇÁö ¾ÊÀ» ¼ö ÀÖ´Ù.) ÀÌ°Í¿¡ ´ëÇÑ ¿¹Á¦´Â ±×¸®±â ÇÁ·Î±×·¥ÀÎ Gsumi(http://www.msc.cornell.edu/~ otaylor/gsumi/¿¡ ÀÖ´Ù.)°¡ µÉ °ÍÀÌ´Ù. °á±¹, ¸ðµç ¾îÇõ鿡 ´ëÇØ ÀÌ ¸ñÀûÀ¸·Î Ç¥ÁØÀûÀÎ ¹æ½ÄÀ» °¡Áú ¼ö ÀÖ´Ù¸é ¸ÚÁø ÀÏÀÌ µÉ °ÍÀÌ´Ù. ÀÌ°ÍÀº ¾Æ¸¶ GNOME ¶óÀ̺귯¸®°¡ GTKº¸´Ù ¾à°£ ³ôÀº ·¹º§¿¡ ¼ÓÇÒ °ÍÀÌ´Ù. ¿ì¸®°¡ ¾Õ¿¡¼ ´Ù·é °Í¿¡¼ ºüÁø ¶ÇÇϳª Áß¿äÇÑ °ÍÀº cursor¿¡ ´ëÇÑ °ÍÀÌ´Ù. XFree86°ú ´Ù¸¥ Ç÷§ÆûµéÀº ÇöÀç·Î¼´Â µ¿½Ã¿¡ µÑÀ» - Core pointer, ±×¸®°í ¾îÇÿ¡ ÀÇÇÑ Á÷Á¢ÀûÀÎ Á¶ÀÛ - »ç¿ëÇÏ¿© ÀåÄ¡¸¦ ´Ù·ê ¼ö ¾ø´Ù. ÀÌ°Í¿¡ ´ëÇØ ´õ ÀÚ¼¼ÇÑ Á¤º¸´Â XInput-HOWTO¸¦ º¸¶ó. <http://www.msc.cornell.edu/~otaylor/ xinput/XInput-HOWTO.html>¿¡ ÀÖ´Ù. ÀÌ°ÍÀº ÃÖ´ëÇÑÀÇ ÀÌ¿ëÀÚ¸¦ È®º¸ÇÏ·Á´Â ¾îÇÃÀ̶ó¸é ÀڽŸ¸ÀÇ Ä¿¼¸¦ ±×·ÁÁÖ´Â °Ô ÇÊ¿äÇÔÀ» ÀǹÌÇÑ´Ù. ÀڽŸ¸ÀÇ Ä¿¼¸¦ ±×¸®´Â ¾îÇÃÀº ´ÙÀ½ÀÇ µÎ ÀÏÀ» ÇØ¾ß ÇÑ´Ù. ù°·Î ÇöÀçÀÇ ÀåÄ¡°¡ ±×·ÁÁø Ä¿¼¸¦ ÇÊ¿ä·Î ÇÏ´ÂÁöÀÇ ¿©ºÎ¸¦ °áÁ¤ÇÏ°í, µÑ°·Î ÇöÀçÀÇ ÀåÄ¡°¡ Á¢±Ù(proximity)µÇ¾î ÀÖ´ÂÁöÀÇ ¿©ºÎ¸¦ °áÁ¤ÇÑ´Ù. (ÇöÀçÀÇ ÀåÄ¡°¡ drawing tabletÀÏ °æ¿ì, stylus°¡ tablet¿¡¼ ¶³¾îÁ³À» ¶§ Ä¿¼°¡ º¸ÀÌÁö ¾Ê°Ô ÇÏ´Â °ÍÀÌ ÁÁÀ» °ÍÀÌ´Ù. ÀåÄ¡°¡ stylus¿Í ºÙ¾î ÀÖÀ» ¶§, À̸¦ Á¢±ÙµÇ¾ú´Ù(in proximity)°í Ç¥ÇöÇÑ´Ù.) ù¹ø° ÀÛ¾÷Àº ¿ì¸®°¡ deviceÀÇ À̸§À» ¾Ë¾Æ³»±â À§ÇØ ÇßµíÀÌ, deviceÀÇ ¸®½ºÆ®¸¦ Á¶»ç ÇÔÀ¸·Î½á ÇØ°áµÈ´Ù. µÎ¹ø° ÀÛ¾÷Àº "proximity_out" À̺¥Æ®¸¦ ¼³Á¤ÇÔÀ¸·Î½á ÇØ°áÇÑ´Ù. °¢ÀÚÀÇ Ä¿¼¸¦ ±×¸®´Â ¿¹Á¦´Â GTK ¹èÆ÷ÆÇ¿¡ ÀÖ´Â 'testinput' ÇÁ·Î ±×·¥¿¡¼ ãÀ» ¼ö ÀÖÀ» °ÍÀÌ´Ù. |