gdkevents.c

Go to the documentation of this file.
00001 /* GDK - The GIMP Drawing Kit
00002  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 /*
00021  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
00022  * file for a list of people on the GTK+ Team.  See the ChangeLog
00023  * files for a list of changes.  These files are distributed with
00024  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
00025  */
00026 
00027 #include "gdk.h"
00028 #include "gdkprivate.h"
00029 #include <stdio.h>
00030 
00031 typedef struct _GdkIOClosure GdkIOClosure;
00032 typedef struct _GdkEventPrivate GdkEventPrivate;
00033 
00034 #define DOUBLE_CLICK_TIME      250
00035 #define TRIPLE_CLICK_TIME      500
00036 #define DOUBLE_CLICK_DIST      5
00037 #define TRIPLE_CLICK_DIST      5
00038 
00039 typedef enum {
00040    /* Following flag is set for events on the event queue during
00041     * translation and cleared afterwards.
00042     */
00043    GDK_EVENT_PENDING = 1 << 0
00044 } GdkEventFlags;
00045 
00046 struct _GdkIOClosure {
00047    GdkInputFunction function;
00048    GdkInputCondition condition;
00049    GdkDestroyNotify notify;
00050    gpointer data;
00051 };
00052 
00053 struct _GdkEventPrivate {
00054    GdkEvent event;
00055    guint flags;
00056 };
00057 
00058 /* 
00059  * Private function declarations
00060  */
00061 
00062 GdkFilterReturn gdk_wm_protocols_filter(GdkXEvent * xev,
00063                                         GdkEvent * event, gpointer data);
00064 
00065 /* Private variable declarations
00066  */
00067 
00068 static guint32 button_click_time[2] = { 0, 0 }; /* The last 2 button click times. Used
00069          * to determine if the latest button click
00070          * is part of a double or triple click.
00071          */
00072 static GdkWindow *button_window[2] = { NULL, NULL };    /* The last 2 windows to receive button presses.
00073          *                                                                                                                                                                                                         Also used to determine if the latest button
00074          *                                                                                                                                                                                                         click is part of a double or triple click.
00075          */
00076 static guint button_number[2] = { -1, -1 };     /* The last 2 buttons to be pressed.
00077          */
00078 GdkEventFunc gdk_event_func = NULL;     /* Callback for events */
00079 gpointer gdk_event_data = NULL;
00080 GDestroyNotify gdk_event_notify = NULL;
00081 
00082 GPollFD event_poll_fd;
00083 
00084 /*********************************************
00085  * Functions for maintaining the event queue *
00086  *********************************************/
00087 
00088 /*************************************************************
00089  * gdk_event_queue_find_first:
00090  *     Find the first event on the queue that is not still
00091  *     being filled in.
00092  *   arguments:
00093  *     
00094  *   results:
00095  *     Pointer to the list node for that event, or NULL
00096  *************************************************************/
00097 
00098 GList *gdk_event_queue_find_first(void)
00099 {
00100    GList *tmp_list = gdk_queued_events;
00101 
00102    while (tmp_list) {
00103       GdkEventPrivate *event = tmp_list->data;
00104       if (!(event->flags & GDK_EVENT_PENDING))
00105          return tmp_list;
00106 
00107       tmp_list = g_list_next(tmp_list);
00108    }
00109 
00110    return NULL;
00111 }
00112 
00113 /*************************************************************
00114  * gdk_event_queue_remove_link:
00115  *     Remove a specified list node from the event queue.
00116  *   arguments:
00117  *     node: Node to remove.
00118  *   results:
00119  *************************************************************/
00120 
00121 void gdk_event_queue_remove_link(GList * node)
00122 {
00123    if (node->prev)
00124       node->prev->next = node->next;
00125    else
00126       gdk_queued_events = node->next;
00127 
00128    if (node->next)
00129       node->next->prev = node->prev;
00130    else
00131       gdk_queued_tail = node->prev;
00132 
00133 }
00134 
00135 /*************************************************************
00136  * gdk_event_queue_append:
00137  *     Append an event onto the tail of the event queue.
00138  *   arguments:
00139  *     event: Event to append.
00140  *   results:
00141  *************************************************************/
00142 
00143 void gdk_event_queue_append(GdkEvent * event)
00144 {
00145    gdk_queued_tail = g_list_append(gdk_queued_tail, event);
00146 
00147    if (!gdk_queued_events)
00148       gdk_queued_events = gdk_queued_tail;
00149    else
00150       gdk_queued_tail = gdk_queued_tail->next;
00151 }
00152 
00153 /*************************************************************
00154  * gdk_event_handler_set:
00155  *     
00156  *   arguments:
00157  *     func: Callback function to be called for each event.
00158  *     data: Data supplied to the function
00159  *     notify: function called when function is no longer needed
00160  * 
00161  *   results:
00162  *************************************************************/
00163 
00164 void
00165 gdk_event_handler_set(GdkEventFunc func,
00166                       gpointer data, GDestroyNotify notify)
00167 {
00168    if (gdk_event_notify)
00169       (*gdk_event_notify) (gdk_event_data);
00170 
00171    gdk_event_func = func;
00172    gdk_event_data = data;
00173    gdk_event_notify = notify;
00174 }
00175 
00176 /*
00177  *--------------------------------------------------------------
00178  * gdk_event_get
00179  *
00180  *   Gets the next event.
00181  *
00182  * Arguments:
00183  *
00184  * Results:
00185  *   If an event is waiting that we care about, returns 
00186  *   a pointer to that event, to be freed with gdk_event_free.
00187  *   Otherwise, returns NULL.
00188  *
00189  * Side effects:
00190  *
00191  *--------------------------------------------------------------
00192  */
00193 
00194 GdkEvent *gdk_event_get(void)
00195 {
00196    gdk_events_queue();
00197 
00198    return gdk_event_unqueue();
00199 }
00200 
00201 /*
00202  *--------------------------------------------------------------
00203  * gdk_event_peek
00204  *
00205  *   Gets the next event.
00206  *
00207  * Arguments:
00208  *
00209  * Results:
00210  *   If an event is waiting that we care about, returns 
00211  *   a copy of that event, but does not remove it from
00212  *   the queue. The pointer is to be freed with gdk_event_free.
00213  *   Otherwise, returns NULL.
00214  *
00215  * Side effects:
00216  *
00217  *--------------------------------------------------------------
00218  */
00219 
00220 GdkEvent *gdk_event_peek(void)
00221 {
00222    GList *tmp_list;
00223 
00224    tmp_list = gdk_event_queue_find_first();
00225 
00226    if (tmp_list)
00227       return gdk_event_copy(tmp_list->data);
00228    else
00229       return NULL;
00230 }
00231 
00232 void gdk_event_put(GdkEvent * event)
00233 {
00234    GdkEvent *new_event;
00235 
00236    g_return_if_fail(event != NULL);
00237 
00238    new_event = gdk_event_copy(event);
00239 
00240    gdk_event_queue_append(new_event);
00241 }
00242 
00243 /*
00244  *--------------------------------------------------------------
00245  * gdk_event_copy
00246  *
00247  *   Copy a event structure into new storage.
00248  *
00249  * Arguments:
00250  *   "event" is the event struct to copy.
00251  *
00252  * Results:
00253  *   A new event structure.  Free it with gdk_event_free.
00254  *
00255  * Side effects:
00256  *   The reference count of the window in the event is increased.
00257  *
00258  *--------------------------------------------------------------
00259  */
00260 
00261 static GMemChunk *event_chunk = NULL;
00262 
00263 GdkEvent *gdk_event_new(void)
00264 {
00265    GdkEventPrivate *new_event;
00266 
00267    if (event_chunk == NULL)
00268       event_chunk = g_mem_chunk_new("events",
00269                                     sizeof(GdkEventPrivate),
00270                                     4096, G_ALLOC_AND_FREE);
00271 
00272    new_event = g_chunk_new(GdkEventPrivate, event_chunk);
00273    new_event->flags = 0;
00274 
00275    return (GdkEvent *) new_event;
00276 }
00277 
00278 GdkEvent *gdk_event_copy(GdkEvent * event)
00279 {
00280    GdkEvent *new_event;
00281 
00282    g_return_val_if_fail(event != NULL, NULL);
00283 
00284    new_event = gdk_event_new();
00285 
00286    *new_event = *event;
00287    gdk_window_ref(new_event->any.window);
00288 
00289    switch (event->any.type) {
00290    case GDK_KEY_PRESS:
00291    case GDK_KEY_RELEASE:
00292       new_event->key.string = g_strdup(event->key.string);
00293       break;
00294 
00295    case GDK_ENTER_NOTIFY:
00296    case GDK_LEAVE_NOTIFY:
00297       if (event->crossing.subwindow != NULL)
00298          gdk_window_ref(event->crossing.subwindow);
00299       break;
00300 
00301    case GDK_DRAG_ENTER:
00302    case GDK_DRAG_LEAVE:
00303    case GDK_DRAG_MOTION:
00304    case GDK_DRAG_STATUS:
00305    case GDK_DROP_START:
00306    case GDK_DROP_FINISHED:
00307       gdk_drag_context_ref(event->dnd.context);
00308       break;
00309 
00310    default:
00311       break;
00312    }
00313 
00314    return new_event;
00315 }
00316 
00317 /*
00318  *--------------------------------------------------------------
00319  * gdk_event_free
00320  *
00321  *   Free a event structure obtained from gdk_event_copy.  Do not use
00322  *   with other event structures.
00323  *
00324  * Arguments:
00325  *   "event" is the event struct to free.
00326  *
00327  * Results:
00328  *
00329  * Side effects:
00330  *   The reference count of the window in the event is decreased and
00331  *   might be freed, too.
00332  *
00333  *-------------------------------------------------------------- */
00334 
00335 void gdk_event_free(GdkEvent * event)
00336 {
00337    g_return_if_fail(event != NULL);
00338 
00339    g_assert(event_chunk != NULL);       /* paranoid */
00340 
00341    if ((event->any.window) && (event->type != GDK_DESTROY))
00342       gdk_window_unref(event->any.window);
00343 
00344    switch (event->any.type) {
00345    case GDK_KEY_PRESS:
00346    case GDK_KEY_RELEASE:
00347       g_free(event->key.string);
00348       break;
00349 
00350    case GDK_ENTER_NOTIFY:
00351    case GDK_LEAVE_NOTIFY:
00352       if (event->crossing.subwindow != NULL)
00353          gdk_window_unref(event->crossing.subwindow);
00354       break;
00355 
00356    case GDK_DRAG_ENTER:
00357    case GDK_DRAG_LEAVE:
00358    case GDK_DRAG_MOTION:
00359    case GDK_DRAG_STATUS:
00360    case GDK_DROP_START:
00361    case GDK_DROP_FINISHED:
00362       gdk_drag_context_unref(event->dnd.context);
00363       break;
00364 
00365    default:
00366       break;
00367    }
00368 
00369    g_mem_chunk_free(event_chunk, event);
00370 }
00371 
00372 /*
00373  *--------------------------------------------------------------
00374  * gdk_event_get_time:
00375  *    Get the timestamp from an event.
00376  *   arguments:
00377  *     event:
00378  *   results:
00379  *    The event's time stamp, if it has one, otherwise
00380  *    GDK_CURRENT_TIME.
00381  *--------------------------------------------------------------
00382  */
00383 
00384 guint32 gdk_event_get_time(GdkEvent * event)
00385 {
00386    if (event)
00387       switch (event->type) {
00388       case GDK_MOTION_NOTIFY:
00389          return event->motion.time;
00390       case GDK_BUTTON_PRESS:
00391       case GDK_2BUTTON_PRESS:
00392       case GDK_3BUTTON_PRESS:
00393       case GDK_BUTTON_RELEASE:
00394       case GDK_SCROLL:
00395          return event->button.time;
00396       case GDK_KEY_PRESS:
00397       case GDK_KEY_RELEASE:
00398          return event->key.time;
00399       case GDK_ENTER_NOTIFY:
00400       case GDK_LEAVE_NOTIFY:
00401          return event->crossing.time;
00402       case GDK_PROPERTY_NOTIFY:
00403          return event->property.time;
00404       case GDK_SELECTION_CLEAR:
00405       case GDK_SELECTION_REQUEST:
00406       case GDK_SELECTION_NOTIFY:
00407          return event->selection.time;
00408       case GDK_PROXIMITY_IN:
00409       case GDK_PROXIMITY_OUT:
00410          return event->proximity.time;
00411       case GDK_DRAG_ENTER:
00412       case GDK_DRAG_LEAVE:
00413       case GDK_DRAG_MOTION:
00414       case GDK_DRAG_STATUS:
00415       case GDK_DROP_START:
00416       case GDK_DROP_FINISHED:
00417          return event->dnd.time;
00418       default:                 /* use current time */
00419          break;
00420       }
00421 
00422    return GDK_CURRENT_TIME;
00423 }
00424 
00425 /*
00426  *--------------------------------------------------------------
00427  * gdk_set_show_events
00428  *
00429  *   Turns on/off the showing of events.
00430  *
00431  * Arguments:
00432  *   "show_events" is a boolean describing whether or
00433  *   not to show the events gdk receives.
00434  *
00435  * Results:
00436  *
00437  * Side effects:
00438  *   When "show_events" is TRUE, calls to "gdk_event_get"
00439  *   will output debugging informatin regarding the event
00440  *   received to stdout.
00441  *
00442  *--------------------------------------------------------------
00443  */
00444 
00445 void gdk_set_show_events(gboolean show_events)
00446 {
00447    if (show_events)
00448       gdk_debug_flags |= GDK_DEBUG_EVENTS;
00449    else
00450       gdk_debug_flags &= ~GDK_DEBUG_EVENTS;
00451 }
00452 
00453 gboolean gdk_get_show_events(void)
00454 {
00455    return (gdk_debug_flags & GDK_DEBUG_EVENTS) != 0;
00456 }
00457 
00458 static void gdk_io_destroy(gpointer data)
00459 {
00460    GdkIOClosure *closure = data;
00461 
00462    if (closure->notify)
00463       closure->notify(closure->data);
00464 
00465    g_free(closure);
00466 }
00467 
00468 /* What do we do with G_IO_NVAL?
00469  */
00470 #define READ_CONDITION (G_IO_IN | G_IO_HUP | G_IO_ERR)
00471 #define WRITE_CONDITION (G_IO_OUT | G_IO_ERR)
00472 #define EXCEPTION_CONDITION (G_IO_PRI)
00473 
00474 static gboolean
00475 gdk_io_invoke(GIOChannel * source, GIOCondition condition, gpointer data)
00476 {
00477    GdkIOClosure *closure = data;
00478    GdkInputCondition gdk_cond = 0;
00479 
00480    if (condition & READ_CONDITION)
00481       gdk_cond |= GDK_INPUT_READ;
00482    if (condition & WRITE_CONDITION)
00483       gdk_cond |= GDK_INPUT_WRITE;
00484    if (condition & EXCEPTION_CONDITION)
00485       gdk_cond |= GDK_INPUT_EXCEPTION;
00486 
00487    if (closure->condition & gdk_cond)
00488       closure->function(closure->data, g_io_channel_unix_get_fd(source),
00489                         gdk_cond);
00490 
00491    return TRUE;
00492 }
00493 
00494 gint
00495 gdk_input_add_full(gint source,
00496                    GdkInputCondition condition,
00497                    GdkInputFunction function,
00498                    gpointer data, GdkDestroyNotify destroy)
00499 {
00500    guint result;
00501    GdkIOClosure *closure = g_new(GdkIOClosure, 1);
00502    GIOChannel *channel;
00503    GIOCondition cond = 0;
00504 
00505    closure->function = function;
00506    closure->condition = condition;
00507    closure->notify = destroy;
00508    closure->data = data;
00509 
00510    if (condition & GDK_INPUT_READ)
00511       cond |= READ_CONDITION;
00512    if (condition & GDK_INPUT_WRITE)
00513       cond |= WRITE_CONDITION;
00514    if (condition & GDK_INPUT_EXCEPTION)
00515       cond |= EXCEPTION_CONDITION;
00516 
00517    channel = g_io_channel_unix_new(source);
00518    result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
00519                                 gdk_io_invoke, closure, gdk_io_destroy);
00520    g_io_channel_unref(channel);
00521 
00522    return result;
00523 }
00524 
00525 gint
00526 gdk_input_add(gint source,
00527               GdkInputCondition condition,
00528               GdkInputFunction function, gpointer data)
00529 {
00530    return gdk_input_add_full(source, condition, function, data, NULL);
00531 }
00532 
00533 void gdk_input_remove(gint tag)
00534 {
00535    g_source_remove(tag);
00536 }
00537 
00538 GdkEvent *gdk_event_unqueue(void)
00539 {
00540    GdkEvent *event = NULL;
00541    GList *tmp_list;
00542 
00543    tmp_list = gdk_event_queue_find_first();
00544 
00545    if (tmp_list) {
00546       event = tmp_list->data;
00547       gdk_event_queue_remove_link(tmp_list);
00548       g_list_free_1(tmp_list);
00549    }
00550 
00551    return event;
00552 }
00553 
00554 void gdk_synthesize_click(GdkEvent * event, gint nclicks)
00555 {
00556    GdkEvent temp_event;
00557 
00558    g_return_if_fail(event != NULL);
00559 
00560    temp_event = *event;
00561    temp_event.type =
00562        (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
00563 
00564    gdk_event_put(&temp_event);
00565 }
00566 
00567 void gdk_event_button_generate(GdkEvent * event)
00568 {
00569    if ((event->button.time < (button_click_time[1] + TRIPLE_CLICK_TIME)) &&
00570        (event->button.window == button_window[1]) &&
00571        (event->button.button == button_number[1])) {
00572       gdk_synthesize_click(event, 3);
00573 
00574       button_click_time[1] = 0;
00575       button_click_time[0] = 0;
00576       button_window[1] = NULL;
00577       button_window[0] = 0;
00578       button_number[1] = -1;
00579       button_number[0] = -1;
00580    } else
00581        if ((event->button.time <
00582             (button_click_time[0] + DOUBLE_CLICK_TIME))
00583            && (event->button.window == button_window[0])
00584            && (event->button.button == button_number[0])) {
00585       gdk_synthesize_click(event, 2);
00586 
00587       button_click_time[1] = button_click_time[0];
00588       button_click_time[0] = event->button.time;
00589       button_window[1] = button_window[0];
00590       button_window[0] = event->button.window;
00591       button_number[1] = button_number[0];
00592       button_number[0] = event->button.button;
00593    } else {
00594       button_click_time[1] = 0;
00595       button_click_time[0] = event->button.time;
00596       button_window[1] = NULL;
00597       button_window[0] = event->button.window;
00598       button_number[1] = -1;
00599       button_number[0] = event->button.button;
00600    }
00601 }
00602 
00603 gboolean
00604 gdk_check_typed_window_event(GdkWindow * w, gint type, GdkEvent * event)
00605 {
00606 
00607    GList *cPtr;
00608    GdkEventPrivate *pevent;
00609    GList *head;
00610 
00611 //    GList *tmp_list = gdk_queued_events;
00612    GList *tmp_list = gdk_event_queue_find_first();
00613    while (tmp_list) {
00614       GdkEventPrivate *ev = tmp_list->data;
00615       if (ev->event.any.type == type) {
00616          if (ev->event.any.window == w) {
00617             *event = ev->event;
00618             gdk_event_queue_remove_link(tmp_list);
00619             g_list_free_1(tmp_list);
00620             return TRUE;
00621          }
00622       }
00623       tmp_list = g_list_next(tmp_list);
00624    }
00625    return FALSE;
00626 
00627 }

Generated on Tue Jul 5 14:14:37 2011 for ROOT_528-00b_version by  doxygen 1.5.1