📄 gdkevents.c
字号:
GdkEvent*gdk_event_get (void){ gdk_events_queue (); return gdk_event_unqueue ();}/* *-------------------------------------------------------------- * gdk_event_peek * * Gets the next event. * * Arguments: * * Results: * If an event is waiting that we care about, returns * a copy of that event, but does not remove it from * the queue. The pointer is to be freed with gdk_event_free. * Otherwise, returns NULL. * * Side effects: * *-------------------------------------------------------------- */GdkEvent*gdk_event_peek (void){ GList *tmp_list; tmp_list = gdk_event_queue_find_first (); if (tmp_list) return gdk_event_copy (tmp_list->data); else return NULL;}voidgdk_event_put (GdkEvent *event){ GdkEvent *new_event; g_return_if_fail (event != NULL); new_event = gdk_event_copy (event); gdk_event_queue_append (new_event);}/* *-------------------------------------------------------------- * gdk_event_copy * * Copy a event structure into new storage. * * Arguments: * "event" is the event struct to copy. * * Results: * A new event structure. Free it with gdk_event_free. * * Side effects: * The reference count of the window in the event is increased. * *-------------------------------------------------------------- */static GMemChunk *event_chunk = NULL;static GdkEvent*gdk_event_new (void){ GdkEventPrivate *new_event; if (event_chunk == NULL) event_chunk = g_mem_chunk_new ("events", sizeof (GdkEventPrivate), 4096, G_ALLOC_AND_FREE); new_event = g_chunk_new (GdkEventPrivate, event_chunk); new_event->flags = 0; return (GdkEvent*) new_event;}GdkEvent*gdk_event_copy (GdkEvent *event){ GdkEvent *new_event; g_return_val_if_fail (event != NULL, NULL); new_event = gdk_event_new (); *new_event = *event; gdk_window_ref (new_event->any.window); switch (event->any.type) { case GDK_KEY_PRESS: case GDK_KEY_RELEASE: new_event->key.string = g_strdup (event->key.string); break; case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: if (event->crossing.subwindow != NULL) gdk_window_ref (event->crossing.subwindow); break; case GDK_DRAG_ENTER: case GDK_DRAG_LEAVE: case GDK_DRAG_MOTION: case GDK_DRAG_STATUS: case GDK_DROP_START: case GDK_DROP_FINISHED: gdk_drag_context_ref (event->dnd.context); break; default: break; } return new_event;}/* *-------------------------------------------------------------- * gdk_event_free * * Free a event structure obtained from gdk_event_copy. Do not use * with other event structures. * * Arguments: * "event" is the event struct to free. * * Results: * * Side effects: * The reference count of the window in the event is decreased and * might be freed, too. * *-------------------------------------------------------------- */voidgdk_event_free (GdkEvent *event){ g_return_if_fail (event != NULL); g_assert (event_chunk != NULL); /* paranoid */ if (event->any.window) gdk_window_unref (event->any.window); switch (event->any.type) { case GDK_KEY_PRESS: case GDK_KEY_RELEASE: g_free (event->key.string); break; case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: if (event->crossing.subwindow != NULL) gdk_window_unref (event->crossing.subwindow); break; case GDK_DRAG_ENTER: case GDK_DRAG_LEAVE: case GDK_DRAG_MOTION: case GDK_DRAG_STATUS: case GDK_DROP_START: case GDK_DROP_FINISHED: gdk_drag_context_unref (event->dnd.context); break; default: break; } g_mem_chunk_free (event_chunk, event);}/* *-------------------------------------------------------------- * gdk_event_get_time: * Get the timestamp from an event. * arguments: * event: * results: * The event's time stamp, if it has one, otherwise * GDK_CURRENT_TIME. *-------------------------------------------------------------- */guint32gdk_event_get_time (GdkEvent *event){ if (event) switch (event->type) { case GDK_MOTION_NOTIFY: return event->motion.time; case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: case GDK_BUTTON_RELEASE: return event->button.time; case GDK_KEY_PRESS: case GDK_KEY_RELEASE: return event->key.time; case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: return event->crossing.time; case GDK_PROPERTY_NOTIFY: return event->property.time; case GDK_SELECTION_CLEAR: case GDK_SELECTION_REQUEST: case GDK_SELECTION_NOTIFY: return event->selection.time; case GDK_PROXIMITY_IN: case GDK_PROXIMITY_OUT: return event->proximity.time; case GDK_DRAG_ENTER: case GDK_DRAG_LEAVE: case GDK_DRAG_MOTION: case GDK_DRAG_STATUS: case GDK_DROP_START: case GDK_DROP_FINISHED: return event->dnd.time; default: /* use current time */ break; } return GDK_CURRENT_TIME;}/* *-------------------------------------------------------------- * gdk_set_show_events * * Turns on/off the showing of events. * * Arguments: * "show_events" is a boolean describing whether or * not to show the events gdk receives. * * Results: * * Side effects: * When "show_events" is TRUE, calls to "gdk_event_get" * will output debugging informatin regarding the event * received to stdout. * *-------------------------------------------------------------- */voidgdk_set_show_events (gint show_events){ if (show_events) gdk_debug_flags |= GDK_DEBUG_EVENTS; else gdk_debug_flags &= ~GDK_DEBUG_EVENTS;}gintgdk_get_show_events (void){ return gdk_debug_flags & GDK_DEBUG_EVENTS;}static voidgdk_io_destroy (gpointer data){ GdkIOClosure *closure = data; if (closure->notify) closure->notify (closure->data); g_free (closure);}/* What do we do with G_IO_NVAL? */#define READ_CONDITION (G_IO_IN | G_IO_HUP | G_IO_ERR)#define WRITE_CONDITION (G_IO_OUT | G_IO_ERR)#define EXCEPTION_CONDITION (G_IO_PRI)static gboolean gdk_io_invoke (GIOChannel *source, GIOCondition condition, gpointer data){ GdkIOClosure *closure = data; GdkInputCondition gdk_cond = 0; if (condition & READ_CONDITION) gdk_cond |= GDK_INPUT_READ; if (condition & WRITE_CONDITION) gdk_cond |= GDK_INPUT_WRITE; if (condition & EXCEPTION_CONDITION) gdk_cond |= GDK_INPUT_EXCEPTION; if (closure->condition & gdk_cond) closure->function (closure->data, g_io_channel_unix_get_fd (source), gdk_cond); return TRUE;}gintgdk_input_add_full (gint source, GdkInputCondition condition, GdkInputFunction function, gpointer data, GdkDestroyNotify destroy){ guint result; GdkIOClosure *closure = g_new (GdkIOClosure, 1); GIOChannel *channel; GIOCondition cond = 0; closure->function = function; closure->condition = condition; closure->notify = destroy; closure->data = data; if (condition & GDK_INPUT_READ) cond |= READ_CONDITION; if (condition & GDK_INPUT_WRITE) cond |= WRITE_CONDITION; if (condition & GDK_INPUT_EXCEPTION) cond |= EXCEPTION_CONDITION; channel = g_io_channel_unix_new (source); result = g_io_add_watch_full (channel, G_PRIORITY_DEFAULT, cond, gdk_io_invoke, closure, gdk_io_destroy); g_io_channel_unref (channel); return result;}gintgdk_input_add (gint source, GdkInputCondition condition, GdkInputFunction function, gpointer data){ return gdk_input_add_full (source, condition, function, data, NULL);}voidgdk_input_remove (gint tag){ g_source_remove (tag);}static gintgdk_event_apply_filters (XEvent *xevent, GdkEvent *event, GList *filters){ GList *tmp_list; GdkFilterReturn result; tmp_list = filters; while (tmp_list) { GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data; tmp_list = tmp_list->next; result = filter->function (xevent, event, filter->data); if (result != GDK_FILTER_CONTINUE) return result; } return GDK_FILTER_CONTINUE;}void gdk_add_client_message_filter (GdkAtom message_type, GdkFilterFunc func, gpointer data){ GdkClientFilter *filter = g_new (GdkClientFilter, 1); filter->type = message_type; filter->function = func; filter->data = data; client_filters = g_list_prepend (client_filters, filter);}static gintgdk_event_translate (GdkEvent *event, XEvent *xevent){ GdkWindow *window; GdkWindowPrivate *window_private; static XComposeStatus compose; KeySym keysym; int charcount;#ifdef USE_XIM static gchar* buf = NULL; static gint buf_len= 0;#else char buf[16];#endif gint return_val; return_val = FALSE; /* Find the GdkWindow that this event occurred in. * * We handle events with window=None * specially - they are generated by XFree86's XInput under * some circumstances. */ if ((xevent->xany.window == None) && gdk_input_vtable.window_none_event) { return_val = gdk_input_vtable.window_none_event (event,xevent); if (return_val >= 0) /* was handled */ return return_val; else return_val = FALSE; } window = gdk_window_lookup (xevent->xany.window); window_private = (GdkWindowPrivate *) window; if (window != NULL) gdk_window_ref (window); event->any.window = window; event->any.send_event = xevent->xany.send_event ? TRUE : FALSE; if (window_private && window_private->destroyed) { if (xevent->type != DestroyNotify) return FALSE; } else { /* Check for filters for this window */ GdkFilterReturn result; result = gdk_event_apply_filters (xevent, event, window_private ?window_private->filters :gdk_default_filters); if (result != GDK_FILTER_CONTINUE) { return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE; } }#ifdef USE_XIM if (window == NULL && gdk_xim_window && xevent->type == KeyPress && !((GdkWindowPrivate *) gdk_xim_window)->destroyed) { /* * If user presses a key in Preedit or Status window, keypress event * is sometimes sent to these windows. These windows are not managed * by GDK, so we redirect KeyPress event to xim_window. * * If someone want to use the window whitch is not managed by GDK * and want to get KeyPress event, he/she must register the filter * function to gdk_default_filters to intercept the event. */ GdkFilterReturn result; window = gdk_xim_window; window_private = (GdkWindowPrivate *) window; gdk_window_ref (window); event->any.window = window; GDK_NOTE (XIM, g_message ("KeyPress event is redirected to xim_window: %#lx", xevent->xany.window)); result = gdk_event_apply_filters (xevent, event, window_private->filters); if (result != GDK_FILTER_CONTINUE) return (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE; }#endif /* We do a "manual" conversion of the XEvent to a * GdkEvent. The structures are mostly the same so * the conversion is fairly straightforward. We also * optionally print debugging info regarding events * received. */ return_val = TRUE; switch (xevent->type) { case KeyPress: /* Lookup the string corresponding to the given keysym. */ #ifdef USE_XIM if (buf_len == 0) { buf_len = 128; buf = g_new (gchar, buf_len); } keysym = GDK_VoidSymbol; if (gdk_xim_ic && gdk_xim_ic->xic) { Status status; /* Clear keyval. Depending on status, may not be set */ charcount = XmbLookupString(gdk_xim_ic->xic, &xevent->xkey, buf, buf_len-1, &keysym, &status); if (status == XBufferOverflow) { /* retry */ /* alloc adequate size of buffer */ GDK_NOTE (XIM, g_message("XIM: overflow (required %i)", charcount)); while (buf_len <= charcount) buf_len *= 2; buf = (gchar *) g_realloc (buf, buf_len); charcount = XmbLookupString (gdk_xim_ic->xic, &xevent->xkey, buf, buf_len-1, &keysym, &status); } if (status == XLookupNone) { return_val = FALSE; break; } } else charcount = XLookupString (&xevent->xkey, buf, buf_len, &keysym, &compose);#else charcount = XLookupString (&xevent->xkey, buf, 16, &keysym, &compose);#endif event->key.keyval = keysym; if (charcount > 0 && buf[charcount-1] == '\0') charcount --; else buf[charcount] = '\0'; /* Print debugging info. */ #ifdef G_ENABLE_DEBUG if (gdk_debug_flags & GDK_DEBUG_EVENTS) { g_message ("key press:\twindow: %ld key: %12s %d", xevent->xkey.window, event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -