00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00041
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
00060
00061
00062 GdkFilterReturn gdk_wm_protocols_filter(GdkXEvent * xev,
00063 GdkEvent * event, gpointer data);
00064
00065
00066
00067
00068 static guint32 button_click_time[2] = { 0, 0 };
00069
00070
00071
00072 static GdkWindow *button_window[2] = { NULL, NULL };
00073
00074
00075
00076 static guint button_number[2] = { -1, -1 };
00077
00078 GdkEventFunc gdk_event_func = NULL;
00079 gpointer gdk_event_data = NULL;
00080 GDestroyNotify gdk_event_notify = NULL;
00081
00082 GPollFD event_poll_fd;
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
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
00115
00116
00117
00118
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
00137
00138
00139
00140
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
00155
00156
00157
00158
00159
00160
00161
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
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
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
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
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
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
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
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
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);
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
00375
00376
00377
00378
00379
00380
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:
00419 break;
00420 }
00421
00422 return GDK_CURRENT_TIME;
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
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
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
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 }