From 7fa13eaf35adf77fe945cd2972abad799832d479 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 6 Dec 2000 17:27:52 +0000 Subject: [PATCH] Add gdkmouse-fb.c 2000-12-06 Alexander Larsson * gdk/linux-fb/Makefile.am: Add gdkmouse-fb.c * gdk/linux-fb/gdkmouse-fb.c: New file. Abstracted the mouse drivers a bit. * gdk/linux-fb/gdkcursor-fb.c: The cursor hide/show functions was moved here from gdkinput-ps2.c. * gdk/linux-fb/gdkinput-ps2.c: Removed old mouse handling code. Moved cursor handling code to gdkcursor-fb.c, moved gdk_fb_window_send_crossing_events() to gdkwindow-fb.c. gdk_input_get_mouseinfo was renamed to gdk_mouse_get_info. * gdk/linux-fb/gdkmain-fb.c: Pass NULL pointers for x,y in gdk_mouse_get_info call. * gdk/linux-fb/gdkprivate-fb.h: Removed public gdk_fb_find_common_ancestor, added and renamed functions for the new mouse handling code. * gdk/linux-fb/gdkwindow-fb.c: Moved gdk_fb_window_send_crossing_events here. added global variable gdk_fb_window_containing_pointer. made gdk_fb_find_common_ancestor static. gdk_input_get_mouseinfo was renamed to gdk_mouse_get_info. --- ChangeLog | 30 + ChangeLog.pre-2-0 | 30 + ChangeLog.pre-2-10 | 30 + ChangeLog.pre-2-2 | 30 + ChangeLog.pre-2-4 | 30 + ChangeLog.pre-2-6 | 30 + ChangeLog.pre-2-8 | 30 + gdk/linux-fb/Makefile.am | 1 + gdk/linux-fb/gdkcursor-fb.c | 236 ++++++++ gdk/linux-fb/gdkinput-ps2.c | 1000 +--------------------------------- gdk/linux-fb/gdkmain-fb.c | 3 +- gdk/linux-fb/gdkmouse-fb.c | 618 +++++++++++++++++++++ gdk/linux-fb/gdkprivate-fb.h | 13 +- gdk/linux-fb/gdkwindow-fb.c | 180 +++++- 14 files changed, 1253 insertions(+), 1008 deletions(-) create mode 100644 gdk/linux-fb/gdkmouse-fb.c diff --git a/ChangeLog b/ChangeLog index ec294fc959..b10aac88b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2000-12-06 Alexander Larsson + + * gdk/linux-fb/Makefile.am: + Add gdkmouse-fb.c + + * gdk/linux-fb/gdkmouse-fb.c: + New file. Abstracted the mouse drivers a bit. + + * gdk/linux-fb/gdkcursor-fb.c: + The cursor hide/show functions was moved here from gdkinput-ps2.c. + + * gdk/linux-fb/gdkinput-ps2.c: + Removed old mouse handling code. Moved cursor handling code + to gdkcursor-fb.c, moved gdk_fb_window_send_crossing_events() to + gdkwindow-fb.c. gdk_input_get_mouseinfo was renamed to + gdk_mouse_get_info. + + * gdk/linux-fb/gdkmain-fb.c: + Pass NULL pointers for x,y in gdk_mouse_get_info call. + + * gdk/linux-fb/gdkprivate-fb.h: + Removed public gdk_fb_find_common_ancestor, added and renamed + functions for the new mouse handling code. + + * gdk/linux-fb/gdkwindow-fb.c: + Moved gdk_fb_window_send_crossing_events here. added global + variable gdk_fb_window_containing_pointer. made + gdk_fb_find_common_ancestor static. gdk_input_get_mouseinfo was + renamed to gdk_mouse_get_info. + 2000-12-06 Alexander Larsson * gdk/linux-fb/gdkevents-fb.c: diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index ec294fc959..b10aac88b3 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,33 @@ +2000-12-06 Alexander Larsson + + * gdk/linux-fb/Makefile.am: + Add gdkmouse-fb.c + + * gdk/linux-fb/gdkmouse-fb.c: + New file. Abstracted the mouse drivers a bit. + + * gdk/linux-fb/gdkcursor-fb.c: + The cursor hide/show functions was moved here from gdkinput-ps2.c. + + * gdk/linux-fb/gdkinput-ps2.c: + Removed old mouse handling code. Moved cursor handling code + to gdkcursor-fb.c, moved gdk_fb_window_send_crossing_events() to + gdkwindow-fb.c. gdk_input_get_mouseinfo was renamed to + gdk_mouse_get_info. + + * gdk/linux-fb/gdkmain-fb.c: + Pass NULL pointers for x,y in gdk_mouse_get_info call. + + * gdk/linux-fb/gdkprivate-fb.h: + Removed public gdk_fb_find_common_ancestor, added and renamed + functions for the new mouse handling code. + + * gdk/linux-fb/gdkwindow-fb.c: + Moved gdk_fb_window_send_crossing_events here. added global + variable gdk_fb_window_containing_pointer. made + gdk_fb_find_common_ancestor static. gdk_input_get_mouseinfo was + renamed to gdk_mouse_get_info. + 2000-12-06 Alexander Larsson * gdk/linux-fb/gdkevents-fb.c: diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index ec294fc959..b10aac88b3 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,33 @@ +2000-12-06 Alexander Larsson + + * gdk/linux-fb/Makefile.am: + Add gdkmouse-fb.c + + * gdk/linux-fb/gdkmouse-fb.c: + New file. Abstracted the mouse drivers a bit. + + * gdk/linux-fb/gdkcursor-fb.c: + The cursor hide/show functions was moved here from gdkinput-ps2.c. + + * gdk/linux-fb/gdkinput-ps2.c: + Removed old mouse handling code. Moved cursor handling code + to gdkcursor-fb.c, moved gdk_fb_window_send_crossing_events() to + gdkwindow-fb.c. gdk_input_get_mouseinfo was renamed to + gdk_mouse_get_info. + + * gdk/linux-fb/gdkmain-fb.c: + Pass NULL pointers for x,y in gdk_mouse_get_info call. + + * gdk/linux-fb/gdkprivate-fb.h: + Removed public gdk_fb_find_common_ancestor, added and renamed + functions for the new mouse handling code. + + * gdk/linux-fb/gdkwindow-fb.c: + Moved gdk_fb_window_send_crossing_events here. added global + variable gdk_fb_window_containing_pointer. made + gdk_fb_find_common_ancestor static. gdk_input_get_mouseinfo was + renamed to gdk_mouse_get_info. + 2000-12-06 Alexander Larsson * gdk/linux-fb/gdkevents-fb.c: diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index ec294fc959..b10aac88b3 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,33 @@ +2000-12-06 Alexander Larsson + + * gdk/linux-fb/Makefile.am: + Add gdkmouse-fb.c + + * gdk/linux-fb/gdkmouse-fb.c: + New file. Abstracted the mouse drivers a bit. + + * gdk/linux-fb/gdkcursor-fb.c: + The cursor hide/show functions was moved here from gdkinput-ps2.c. + + * gdk/linux-fb/gdkinput-ps2.c: + Removed old mouse handling code. Moved cursor handling code + to gdkcursor-fb.c, moved gdk_fb_window_send_crossing_events() to + gdkwindow-fb.c. gdk_input_get_mouseinfo was renamed to + gdk_mouse_get_info. + + * gdk/linux-fb/gdkmain-fb.c: + Pass NULL pointers for x,y in gdk_mouse_get_info call. + + * gdk/linux-fb/gdkprivate-fb.h: + Removed public gdk_fb_find_common_ancestor, added and renamed + functions for the new mouse handling code. + + * gdk/linux-fb/gdkwindow-fb.c: + Moved gdk_fb_window_send_crossing_events here. added global + variable gdk_fb_window_containing_pointer. made + gdk_fb_find_common_ancestor static. gdk_input_get_mouseinfo was + renamed to gdk_mouse_get_info. + 2000-12-06 Alexander Larsson * gdk/linux-fb/gdkevents-fb.c: diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index ec294fc959..b10aac88b3 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,33 @@ +2000-12-06 Alexander Larsson + + * gdk/linux-fb/Makefile.am: + Add gdkmouse-fb.c + + * gdk/linux-fb/gdkmouse-fb.c: + New file. Abstracted the mouse drivers a bit. + + * gdk/linux-fb/gdkcursor-fb.c: + The cursor hide/show functions was moved here from gdkinput-ps2.c. + + * gdk/linux-fb/gdkinput-ps2.c: + Removed old mouse handling code. Moved cursor handling code + to gdkcursor-fb.c, moved gdk_fb_window_send_crossing_events() to + gdkwindow-fb.c. gdk_input_get_mouseinfo was renamed to + gdk_mouse_get_info. + + * gdk/linux-fb/gdkmain-fb.c: + Pass NULL pointers for x,y in gdk_mouse_get_info call. + + * gdk/linux-fb/gdkprivate-fb.h: + Removed public gdk_fb_find_common_ancestor, added and renamed + functions for the new mouse handling code. + + * gdk/linux-fb/gdkwindow-fb.c: + Moved gdk_fb_window_send_crossing_events here. added global + variable gdk_fb_window_containing_pointer. made + gdk_fb_find_common_ancestor static. gdk_input_get_mouseinfo was + renamed to gdk_mouse_get_info. + 2000-12-06 Alexander Larsson * gdk/linux-fb/gdkevents-fb.c: diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index ec294fc959..b10aac88b3 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,33 @@ +2000-12-06 Alexander Larsson + + * gdk/linux-fb/Makefile.am: + Add gdkmouse-fb.c + + * gdk/linux-fb/gdkmouse-fb.c: + New file. Abstracted the mouse drivers a bit. + + * gdk/linux-fb/gdkcursor-fb.c: + The cursor hide/show functions was moved here from gdkinput-ps2.c. + + * gdk/linux-fb/gdkinput-ps2.c: + Removed old mouse handling code. Moved cursor handling code + to gdkcursor-fb.c, moved gdk_fb_window_send_crossing_events() to + gdkwindow-fb.c. gdk_input_get_mouseinfo was renamed to + gdk_mouse_get_info. + + * gdk/linux-fb/gdkmain-fb.c: + Pass NULL pointers for x,y in gdk_mouse_get_info call. + + * gdk/linux-fb/gdkprivate-fb.h: + Removed public gdk_fb_find_common_ancestor, added and renamed + functions for the new mouse handling code. + + * gdk/linux-fb/gdkwindow-fb.c: + Moved gdk_fb_window_send_crossing_events here. added global + variable gdk_fb_window_containing_pointer. made + gdk_fb_find_common_ancestor static. gdk_input_get_mouseinfo was + renamed to gdk_mouse_get_info. + 2000-12-06 Alexander Larsson * gdk/linux-fb/gdkevents-fb.c: diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index ec294fc959..b10aac88b3 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,33 @@ +2000-12-06 Alexander Larsson + + * gdk/linux-fb/Makefile.am: + Add gdkmouse-fb.c + + * gdk/linux-fb/gdkmouse-fb.c: + New file. Abstracted the mouse drivers a bit. + + * gdk/linux-fb/gdkcursor-fb.c: + The cursor hide/show functions was moved here from gdkinput-ps2.c. + + * gdk/linux-fb/gdkinput-ps2.c: + Removed old mouse handling code. Moved cursor handling code + to gdkcursor-fb.c, moved gdk_fb_window_send_crossing_events() to + gdkwindow-fb.c. gdk_input_get_mouseinfo was renamed to + gdk_mouse_get_info. + + * gdk/linux-fb/gdkmain-fb.c: + Pass NULL pointers for x,y in gdk_mouse_get_info call. + + * gdk/linux-fb/gdkprivate-fb.h: + Removed public gdk_fb_find_common_ancestor, added and renamed + functions for the new mouse handling code. + + * gdk/linux-fb/gdkwindow-fb.c: + Moved gdk_fb_window_send_crossing_events here. added global + variable gdk_fb_window_containing_pointer. made + gdk_fb_find_common_ancestor static. gdk_input_get_mouseinfo was + renamed to gdk_mouse_get_info. + 2000-12-06 Alexander Larsson * gdk/linux-fb/gdkevents-fb.c: diff --git a/gdk/linux-fb/Makefile.am b/gdk/linux-fb/Makefile.am index 2bc07b88c2..95c4a3079e 100644 --- a/gdk/linux-fb/Makefile.am +++ b/gdk/linux-fb/Makefile.am @@ -50,6 +50,7 @@ libgdk_linux_fb_la_SOURCES = \ gdkprivate-fb.h \ gdkinputprivate.h \ gdkinput-ps2.c \ + gdkmouse-fb.c \ gdkevents-fb.c \ gdkrender-fb.c \ mi.h \ diff --git a/gdk/linux-fb/gdkcursor-fb.c b/gdk/linux-fb/gdkcursor-fb.c index 80d51332c4..6dab9f8bd6 100644 --- a/gdk/linux-fb/gdkcursor-fb.c +++ b/gdk/linux-fb/gdkcursor-fb.c @@ -284,3 +284,239 @@ _gdk_cursor_destroy (GdkCursor *cursor) g_free (private); } + +/* Global data to keep track of cursor */ +static GdkPixmap *last_contents = NULL; +static GdkPoint last_location, last_contents_size; +static GdkCursor *last_cursor = NULL; +static GdkFBDrawingContext *gdk_fb_cursor_dc = NULL; +static GdkFBDrawingContext cursor_dc_dat; +static GdkGC *cursor_gc; +static gint cursor_visibility_count = 1; + +static GdkFBDrawingContext * +gdk_fb_cursor_dc_reset (void) +{ + if (gdk_fb_cursor_dc) + gdk_fb_drawing_context_finalize (gdk_fb_cursor_dc); + + gdk_fb_cursor_dc = &cursor_dc_dat; + gdk_fb_drawing_context_init (gdk_fb_cursor_dc, + GDK_DRAWABLE_IMPL(gdk_parent_root), + cursor_gc, + TRUE, + FALSE); + + return gdk_fb_cursor_dc; +} + +void +gdk_fb_cursor_hide (void) +{ + GdkFBDrawingContext *mydc = gdk_fb_cursor_dc; + + cursor_visibility_count--; + g_assert (cursor_visibility_count <= 0); + + if (cursor_visibility_count < 0) + return; + + if (!mydc) + mydc = gdk_fb_cursor_dc_reset (); + + if (last_contents) + { + gdk_gc_set_clip_mask (cursor_gc, NULL); + /* Restore old picture */ + gdk_fb_draw_drawable_3 (GDK_DRAWABLE_IMPL(gdk_parent_root), + cursor_gc, + GDK_DRAWABLE_IMPL(last_contents), + mydc, + 0, 0, + last_location.x, + last_location.y, + last_contents_size.x, + last_contents_size.y); + } +} + +void +gdk_fb_cursor_invalidate (void) +{ + if (last_contents) + { + gdk_pixmap_unref (last_contents); + last_contents = NULL; + } +} + +void +gdk_fb_cursor_unhide() +{ + GdkFBDrawingContext *mydc = gdk_fb_cursor_dc; + GdkCursorPrivateFB *last_private; + GdkDrawableFBData *pixmap_last; + + last_private = GDK_CURSOR_FB (last_cursor); + pixmap_last = GDK_DRAWABLE_IMPL_FBDATA (last_private->cursor); + cursor_visibility_count++; + g_assert (cursor_visibility_count <= 1); + if (cursor_visibility_count < 1) + return; + + if (!mydc) + mydc = gdk_fb_cursor_dc_reset (); + + if (last_cursor) + { + if (!last_contents || + pixmap_last->width > GDK_DRAWABLE_IMPL_FBDATA (last_contents)->width || + pixmap_last->height > GDK_DRAWABLE_IMPL_FBDATA (last_contents)->height) + { + if (last_contents) + gdk_pixmap_unref (last_contents); + + last_contents = gdk_pixmap_new (gdk_parent_root, + pixmap_last->width, + pixmap_last->height, + GDK_DRAWABLE_IMPL_FBDATA (gdk_parent_root)->depth); + } + + gdk_gc_set_clip_mask (cursor_gc, NULL); + gdk_fb_draw_drawable_2 (GDK_DRAWABLE_IMPL (last_contents), + cursor_gc, + GDK_DRAWABLE_IMPL (gdk_parent_root), + last_location.x, + last_location.y, + 0, 0, + pixmap_last->width, + pixmap_last->height, + TRUE, FALSE); + last_contents_size.x = pixmap_last->width; + last_contents_size.y = pixmap_last->height; + + gdk_gc_set_clip_mask (cursor_gc, last_private->mask); + gdk_gc_set_clip_origin (cursor_gc, + last_location.x, + last_location.y); + + gdk_fb_cursor_dc_reset (); + gdk_fb_draw_drawable_3 (GDK_DRAWABLE_IMPL (gdk_parent_root), + cursor_gc, + GDK_DRAWABLE_IMPL (last_private->cursor), + mydc, + 0, 0, + last_location.x, last_location.y, + pixmap_last->width, + pixmap_last->height); + } + else + gdk_fb_cursor_invalidate (); +} + +gboolean +gdk_fb_cursor_region_need_hide (GdkRegion *region) +{ + GdkRectangle testme; + + if (!last_cursor) + return FALSE; + + testme.x = last_location.x; + testme.y = last_location.y; + testme.width = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->width; + testme.height = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->height; + + return (gdk_region_rect_in (region, &testme) != GDK_OVERLAP_RECTANGLE_OUT); +} + +gboolean +gdk_fb_cursor_need_hide (GdkRectangle *rect) +{ + GdkRectangle testme; + + if (!last_cursor) + return FALSE; + + testme.x = last_location.x; + testme.y = last_location.y; + testme.width = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->width; + testme.height = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->height; + + return gdk_rectangle_intersect (rect, &testme, &testme); +} + +void +gdk_fb_get_cursor_rect (GdkRectangle *rect) +{ + if (last_cursor) + { + rect->x = last_location.x; + rect->y = last_location.y; + rect->width = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->width; + rect->height = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->height; + } + else + { + rect->x = rect->y = -1; + rect->width = rect->height = 0; + } +} + +void +gdk_fb_cursor_move (gint x, gint y, GdkWindow *in_window) +{ + GdkCursor *the_cursor; + + if (!cursor_gc) + { + GdkColor white, black; + cursor_gc = gdk_gc_new (gdk_parent_root); + gdk_color_black (gdk_colormap_get_system (), &black); + gdk_color_white (gdk_colormap_get_system (), &white); + gdk_gc_set_foreground (cursor_gc, &black); + gdk_gc_set_background (cursor_gc, &white); + } + + gdk_fb_cursor_hide (); + + if (_gdk_fb_pointer_grab_window) + { + if (_gdk_fb_pointer_grab_cursor) + the_cursor = _gdk_fb_pointer_grab_cursor; + else + { + GdkWindow *win = _gdk_fb_pointer_grab_window; + while (!GDK_WINDOW_IMPL_FBDATA (win)->cursor && GDK_WINDOW_OBJECT (win)->parent) + win = (GdkWindow *)GDK_WINDOW_OBJECT (win)->parent; + the_cursor = GDK_WINDOW_IMPL_FBDATA (win)->cursor; + } + } + else + { + while (!GDK_WINDOW_IMPL_FBDATA (in_window)->cursor && GDK_WINDOW_P (in_window)->parent) + in_window = (GdkWindow *)GDK_WINDOW_P (in_window)->parent; + the_cursor = GDK_WINDOW_IMPL_FBDATA (in_window)->cursor; + } + + last_location.x = x - GDK_CURSOR_FB (the_cursor)->hot_x; + last_location.y = y - GDK_CURSOR_FB (the_cursor)->hot_y; + + if (the_cursor) + gdk_cursor_ref (the_cursor); + if (last_cursor) + gdk_cursor_unref (last_cursor); + last_cursor = the_cursor; + + gdk_fb_cursor_unhide (); +} + +void +gdk_fb_cursor_reset(void) +{ + GdkWindow *win = gdk_window_at_pointer (NULL, NULL); + gint x, y; + + gdk_mouse_get_info (&x, &y, NULL); + gdk_fb_cursor_move (x, y, win); +} diff --git a/gdk/linux-fb/gdkinput-ps2.c b/gdk/linux-fb/gdkinput-ps2.c index 7c5a46a5bd..2eccb61bd7 100644 --- a/gdk/linux-fb/gdkinput-ps2.c +++ b/gdk/linux-fb/gdkinput-ps2.c @@ -49,18 +49,6 @@ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ -typedef struct { - gint fd, fd_tag; - - gdouble x, y; - GdkWindow *prev_window; - gboolean button1_pressed, button2_pressed, button3_pressed; - gboolean click_grab; - - guchar mouse_packet[5]; - int packet_nbytes; -} MouseDevice; - typedef struct { gint fd, fd_tag, consfd; @@ -73,7 +61,6 @@ static guint blanking_timer = 0; static Keyboard * tty_keyboard_open(void); -static MouseDevice *gdk_fb_mouse = NULL; static Keyboard *keyboard = NULL; #ifndef VESA_NO_BLANKING @@ -107,977 +94,6 @@ input_activity (void) #endif } -static void -send_button_event (MouseDevice *mouse, - guint button, - gboolean press_event, - guint32 the_time) -{ - GdkEvent *event; - gint x, y; - GdkWindow *window; - int nbuttons = 0; - - if (_gdk_fb_pointer_grab_window_events) - window = _gdk_fb_pointer_grab_window_events; - else - window = gdk_window_at_pointer(NULL, NULL); - - event = gdk_event_make (window, press_event ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE, FALSE); - - if (event) - { - gdk_window_get_origin (window, &x, &y); - x = mouse->x - x; - y = mouse->y - y; - - event->button.x = x; - event->button.y = y; - event->button.button = button; - event->button.state = (mouse->button1_pressed?GDK_BUTTON1_MASK:0) | - (mouse->button2_pressed ? GDK_BUTTON2_MASK : 0) | - (mouse->button3_pressed ? GDK_BUTTON3_MASK : 0) | - (1 << (button + 8)) /* badhack */ | - keyboard->modifier_state; - event->button.device = gdk_core_pointer; - event->button.x_root = mouse->x; - event->button.y_root = mouse->y; - - event->button.time = the_time; - -#if 0 - g_message ("Button #%d %s [%d, %d] in %p", - button, press_event?"pressed":"released", - x, y, window); - - /* Debugging aid */ - if (window && window != gdk_parent_root) - { - GdkGC *tmp_gc; - - tmp_gc = gdk_gc_new (window); - GDK_GC_FBDATA (tmp_gc)->values.foreground.pixel = 0; - gdk_fb_draw_rectangle (GDK_DRAWABLE_IMPL(window), tmp_gc, TRUE, 0, 0, - GDK_DRAWABLE_IMPL_FBDATA(window)->width, GDK_DRAWABLE_IMPL_FBDATA(window)->height); - gdk_gc_unref(tmp_gc); - } -#endif - - gdk_event_queue_append (event); - - /* For double-clicks */ - if (press_event) - gdk_event_button_generate (event); - - } - - if (mouse->button1_pressed) - nbuttons++; - if (mouse->button2_pressed) - nbuttons++; - if (mouse->button3_pressed) - nbuttons++; - - /* Handle implicit button grabs: */ - if (press_event && nbuttons == 1) - { - gdk_fb_pointer_grab (window, FALSE, - gdk_window_get_events (window), - NULL, NULL, - GDK_CURRENT_TIME, TRUE); - mouse->click_grab = TRUE; - } - else if (!press_event && nbuttons == 0 && mouse->click_grab) - { - gdk_fb_pointer_ungrab (GDK_CURRENT_TIME, TRUE); - mouse->click_grab = FALSE; - } -} - -static GdkPixmap *last_contents = NULL; -static GdkPoint last_location, last_contents_size; -static GdkCursor *last_cursor = NULL; -static GdkFBDrawingContext *gdk_fb_cursor_dc = NULL; -static GdkFBDrawingContext cursor_dc_dat; -static GdkGC *cursor_gc; -static gint cursor_visibility_count = 1; - -static GdkFBDrawingContext * -gdk_fb_cursor_dc_reset (void) -{ - if (gdk_fb_cursor_dc) - gdk_fb_drawing_context_finalize (gdk_fb_cursor_dc); - - gdk_fb_cursor_dc = &cursor_dc_dat; - gdk_fb_drawing_context_init (gdk_fb_cursor_dc, - GDK_DRAWABLE_IMPL(gdk_parent_root), - cursor_gc, - TRUE, - FALSE); - - return gdk_fb_cursor_dc; -} - -void -gdk_fb_cursor_hide (void) -{ - GdkFBDrawingContext *mydc = gdk_fb_cursor_dc; - - cursor_visibility_count--; - g_assert (cursor_visibility_count <= 0); - - if (cursor_visibility_count < 0) - return; - - if (!mydc) - mydc = gdk_fb_cursor_dc_reset (); - - if (last_contents) - { - gdk_gc_set_clip_mask (cursor_gc, NULL); - /* Restore old picture */ - gdk_fb_draw_drawable_3 (GDK_DRAWABLE_IMPL(gdk_parent_root), - cursor_gc, - GDK_DRAWABLE_IMPL(last_contents), - mydc, - 0, 0, - last_location.x, - last_location.y, - last_contents_size.x, - last_contents_size.y); - } -} - -void -gdk_fb_cursor_invalidate (void) -{ - if (last_contents) - { - gdk_pixmap_unref (last_contents); - last_contents = NULL; - } -} - -void -gdk_fb_cursor_unhide() -{ - GdkFBDrawingContext *mydc = gdk_fb_cursor_dc; - GdkCursorPrivateFB *last_private; - GdkDrawableFBData *pixmap_last; - - last_private = GDK_CURSOR_FB (last_cursor); - pixmap_last = GDK_DRAWABLE_IMPL_FBDATA (last_private->cursor); - cursor_visibility_count++; - g_assert (cursor_visibility_count <= 1); - if (cursor_visibility_count < 1) - return; - - if (!mydc) - mydc = gdk_fb_cursor_dc_reset (); - - if (last_cursor) - { - if (!last_contents || - pixmap_last->width > GDK_DRAWABLE_IMPL_FBDATA (last_contents)->width || - pixmap_last->height > GDK_DRAWABLE_IMPL_FBDATA (last_contents)->height) - { - if (last_contents) - gdk_pixmap_unref (last_contents); - - last_contents = gdk_pixmap_new (gdk_parent_root, - pixmap_last->width, - pixmap_last->height, - GDK_DRAWABLE_IMPL_FBDATA (gdk_parent_root)->depth); - } - - gdk_gc_set_clip_mask (cursor_gc, NULL); - gdk_fb_draw_drawable_2 (GDK_DRAWABLE_IMPL (last_contents), - cursor_gc, - GDK_DRAWABLE_IMPL (gdk_parent_root), - last_location.x, - last_location.y, - 0, 0, - pixmap_last->width, - pixmap_last->height, - TRUE, FALSE); - last_contents_size.x = pixmap_last->width; - last_contents_size.y = pixmap_last->height; - - gdk_gc_set_clip_mask (cursor_gc, last_private->mask); - gdk_gc_set_clip_origin (cursor_gc, - last_location.x, - last_location.y); - - gdk_fb_cursor_dc_reset (); - gdk_fb_draw_drawable_3 (GDK_DRAWABLE_IMPL (gdk_parent_root), - cursor_gc, - GDK_DRAWABLE_IMPL (last_private->cursor), - mydc, - 0, 0, - last_location.x, last_location.y, - pixmap_last->width, - pixmap_last->height); - } - else - gdk_fb_cursor_invalidate (); -} - -gboolean -gdk_fb_cursor_region_need_hide (GdkRegion *region) -{ - GdkRectangle testme; - - if (!last_cursor) - return FALSE; - - testme.x = last_location.x; - testme.y = last_location.y; - testme.width = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->width; - testme.height = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->height; - - return (gdk_region_rect_in (region, &testme) != GDK_OVERLAP_RECTANGLE_OUT); -} - -gboolean -gdk_fb_cursor_need_hide (GdkRectangle *rect) -{ - GdkRectangle testme; - - if (!last_cursor) - return FALSE; - - testme.x = last_location.x; - testme.y = last_location.y; - testme.width = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->width; - testme.height = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->height; - - return gdk_rectangle_intersect (rect, &testme, &testme); -} - -void -gdk_fb_get_cursor_rect (GdkRectangle *rect) -{ - if (last_cursor) - { - rect->x = last_location.x; - rect->y = last_location.y; - rect->width = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->width; - rect->height = GDK_DRAWABLE_IMPL_FBDATA (GDK_CURSOR_FB (last_cursor)->cursor)->height; - } - else - { - rect->x = rect->y = -1; - rect->width = rect->height = 0; - } -} - -static void -move_pointer (MouseDevice *mouse, GdkWindow *in_window) -{ - GdkCursor *the_cursor; - - if (!cursor_gc) - { - GdkColor white, black; - cursor_gc = gdk_gc_new (gdk_parent_root); - gdk_color_black (gdk_colormap_get_system (), &black); - gdk_color_white (gdk_colormap_get_system (), &white); - gdk_gc_set_foreground (cursor_gc, &black); - gdk_gc_set_background (cursor_gc, &white); - } - - gdk_fb_cursor_hide (); - - if (_gdk_fb_pointer_grab_window) - { - if (_gdk_fb_pointer_grab_cursor) - the_cursor = _gdk_fb_pointer_grab_cursor; - else - { - GdkWindow *win = _gdk_fb_pointer_grab_window; - while (!GDK_WINDOW_IMPL_FBDATA (win)->cursor && GDK_WINDOW_OBJECT (win)->parent) - win = (GdkWindow *)GDK_WINDOW_OBJECT (win)->parent; - the_cursor = GDK_WINDOW_IMPL_FBDATA (win)->cursor; - } - } - else - { - while (!GDK_WINDOW_IMPL_FBDATA (in_window)->cursor && GDK_WINDOW_P (in_window)->parent) - in_window = (GdkWindow *)GDK_WINDOW_P (in_window)->parent; - the_cursor = GDK_WINDOW_IMPL_FBDATA (in_window)->cursor; - } - - last_location.x = mouse->x - GDK_CURSOR_FB (the_cursor)->hot_x; - last_location.y = mouse->y - GDK_CURSOR_FB (the_cursor)->hot_y; - - if (the_cursor) - gdk_cursor_ref (the_cursor); - if (last_cursor) - gdk_cursor_unref (last_cursor); - last_cursor = the_cursor; - - gdk_fb_cursor_unhide (); -} - -void -gdk_fb_cursor_reset(void) -{ - GdkWindow *win = gdk_window_at_pointer (NULL, NULL); - - move_pointer (gdk_fb_mouse, win); -} - -void -gdk_fb_window_send_crossing_events (GdkWindow *dest, - GdkCrossingMode mode) -{ - GdkWindow *c; - GdkWindow *win, *last, *next; - GdkEvent *event; - gint x, y, x_int, y_int; - GdkModifierType my_mask; - GList *path, *list; - gboolean non_linear; - gboolean only_grabbed_window; - GdkWindow *a; - GdkWindow *b; - - if (gdk_fb_mouse->prev_window == NULL) - gdk_fb_mouse->prev_window = gdk_window_ref (gdk_parent_root); - - if (mode == GDK_CROSSING_UNGRAB) - a = _gdk_fb_pointer_grab_window; - else - a = gdk_fb_mouse->prev_window; - b = dest; - - /* When grab in progress only send normal crossing events about - * the grabbed window. - */ - only_grabbed_window = (_gdk_fb_pointer_grab_window_events != NULL) && - (mode == GDK_CROSSING_NORMAL); - - if (a==b) - return; - - gdk_input_get_mouseinfo (&x, &y, &my_mask); - - c = gdk_fb_find_common_ancestor (a, b); - - non_linear = (c != a) && (c != b); - - if (!only_grabbed_window || (a == _gdk_fb_pointer_grab_window)) - event = gdk_event_make (a, GDK_LEAVE_NOTIFY, TRUE); - else - event = NULL; - if (event) - { - event->crossing.subwindow = NULL; - gdk_window_get_root_origin (a, &x_int, &y_int); - event->crossing.x = x - x_int; - event->crossing.y = y - y_int; - event->crossing.x_root = x; - event->crossing.y_root = y; - event->crossing.mode = mode; - if (non_linear) - event->crossing.detail = GDK_NOTIFY_NONLINEAR; - else if (c==a) - event->crossing.detail = GDK_NOTIFY_INFERIOR; - else - event->crossing.detail = GDK_NOTIFY_ANCESTOR; - event->crossing.focus = FALSE; - event->crossing.state = my_mask; - } - - /* Traverse up from a to (excluding) c */ - if (c != a) - { - last = a; - win = GDK_WINDOW (GDK_WINDOW_OBJECT (a)->parent); - while (win != c) - { - if (!only_grabbed_window || (win == _gdk_fb_pointer_grab_window)) - event = gdk_event_make (win, GDK_LEAVE_NOTIFY, TRUE); - else - event = NULL; - if (event) - { - event->crossing.subwindow = gdk_window_ref (last); - gdk_window_get_root_origin (win, &x_int, &y_int); - event->crossing.x = x - x_int; - event->crossing.y = y - y_int; - event->crossing.x_root = x; - event->crossing.y_root = y; - event->crossing.mode = mode; - if (non_linear) - event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL; - else - event->crossing.detail = GDK_NOTIFY_VIRTUAL; - event->crossing.focus = FALSE; - event->crossing.state = my_mask; - } - last = win; - win = GDK_WINDOW (GDK_WINDOW_OBJECT (win)->parent); - } - } - - /* Traverse down from c to b */ - if (c != b) - { - path = NULL; - win = GDK_WINDOW( GDK_WINDOW_OBJECT (b)->parent); - while (win != c) - { - path = g_list_prepend (path, win); - win = GDK_WINDOW( GDK_WINDOW_OBJECT (win)->parent); - } - - list = path; - while (list) - { - win = (GdkWindow *)list->data; - list = g_list_next (list); - if (list) - next = (GdkWindow *)list->data; - else - next = b; - - if (!only_grabbed_window || (win == _gdk_fb_pointer_grab_window)) - event = gdk_event_make (win, GDK_ENTER_NOTIFY, TRUE); - else - event = NULL; - if (event) - { - event->crossing.subwindow = gdk_window_ref (next); - gdk_window_get_root_origin (win, &x_int, &y_int); - event->crossing.x = x - x_int; - event->crossing.y = y - y_int; - event->crossing.x_root = x; - event->crossing.y_root = y; - event->crossing.mode = mode; - if (non_linear) - event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL; - else - event->crossing.detail = GDK_NOTIFY_VIRTUAL; - event->crossing.focus = FALSE; - event->crossing.state = my_mask; - } - } - g_list_free (path); - } - - if (!only_grabbed_window || (b == _gdk_fb_pointer_grab_window)) - event = gdk_event_make (b, GDK_ENTER_NOTIFY, TRUE); - else - event = NULL; - if (event) - { - event->crossing.subwindow = NULL; - gdk_window_get_root_origin (b, &x_int, &y_int); - event->crossing.x = x - x_int; - event->crossing.y = y - y_int; - event->crossing.x_root = x; - event->crossing.y_root = y; - event->crossing.mode = mode; - if (non_linear) - event->crossing.detail = GDK_NOTIFY_NONLINEAR; - else if (c==a) - event->crossing.detail = GDK_NOTIFY_ANCESTOR; - else - event->crossing.detail = GDK_NOTIFY_INFERIOR; - event->crossing.focus = FALSE; - event->crossing.state = my_mask; - } - - if ((mode != GDK_CROSSING_GRAB) && - (b != gdk_fb_mouse->prev_window)) - { - gdk_window_unref (gdk_fb_mouse->prev_window); - gdk_fb_mouse->prev_window = gdk_window_ref (b); - } -} - -static void -handle_mouse_input(MouseDevice *mouse, - gboolean got_motion) -{ - GdkWindow *mousewin; - GdkEvent *event; - gint x, y; - GdkWindow *win, *grabwin; - guint state; - - if (_gdk_fb_pointer_grab_confine) - mousewin = _gdk_fb_pointer_grab_confine; - else - mousewin = gdk_parent_root; - - if (mouse->x < GDK_DRAWABLE_IMPL_FBDATA (mousewin)->llim_x) - mouse->x = GDK_DRAWABLE_IMPL_FBDATA (mousewin)->llim_x; - else if (mouse->x > (GDK_DRAWABLE_IMPL_FBDATA (mousewin)->lim_x - 1)) - mouse->x = GDK_DRAWABLE_IMPL_FBDATA (mousewin)->lim_x - 1; - - if (mouse->y < GDK_DRAWABLE_IMPL_FBDATA (mousewin)->llim_y) - mouse->y = GDK_DRAWABLE_IMPL_FBDATA (mousewin)->llim_y; - else if (mouse->y > (GDK_DRAWABLE_IMPL_FBDATA (mousewin)->lim_y - 1)) - mouse->y = GDK_DRAWABLE_IMPL_FBDATA (mousewin)->lim_y - 1; - - if (!got_motion) - return; - - win = gdk_window_at_pointer (NULL, NULL); - if (_gdk_fb_pointer_grab_window_events) - grabwin = _gdk_fb_pointer_grab_window_events; - else - grabwin = win; - - move_pointer (mouse, grabwin); - - gdk_window_get_origin (grabwin, &x, &y); - x = mouse->x - x; - y = mouse->y - y; - - - state = (mouse->button1_pressed?GDK_BUTTON1_MASK:0) | - (mouse->button2_pressed?GDK_BUTTON2_MASK:0) | - (mouse->button3_pressed?GDK_BUTTON3_MASK:0) | - keyboard->modifier_state; - - event = gdk_event_make (grabwin, GDK_MOTION_NOTIFY, TRUE); - if (event) - { - event->motion.x = x; - event->motion.y = y; - event->motion.state = state; - event->motion.is_hint = FALSE; - event->motion.device = gdk_core_pointer; - event->motion.x_root = mouse->x; - event->motion.y_root = mouse->y; - event->motion.time = gdk_fb_get_time (); - } - - if (win != mouse->prev_window) - gdk_fb_window_send_crossing_events (win, - GDK_CROSSING_NORMAL); - - input_activity (); -} - -static gboolean -pull_fidmour_packet (MouseDevice *mouse, - gboolean *btn_down, - gdouble *x, - gdouble *y) -{ - gboolean keep_reading = TRUE; - - while (keep_reading) - { - int n; - - n = read (mouse->fd, mouse->mouse_packet + mouse->packet_nbytes, 5 - mouse->packet_nbytes); - if (n < 0) - return FALSE; - else if (n == 0) - { - g_error ("EOF on mouse device!"); - g_source_remove (mouse->fd_tag); - return FALSE; - } - - mouse->packet_nbytes += n; - - n = 0; - if (!(mouse->mouse_packet[0] & 0x80)) - { - int i; - /* We haven't received any of the packet yet but there is no header at the beginning */ - for (i = 1; i < mouse->packet_nbytes; i++) - { - if (mouse->mouse_packet[i] & 0x80) - { - n = i; - break; - } - } - } - else if (mouse->packet_nbytes > 1 && - ((mouse->mouse_packet[0] & 0x90) == 0x90)) - { - /* eat the 0x90 and following byte, no clue what it's for */ - n = 2; - } - else if (mouse->packet_nbytes == 5) - { - switch (mouse->mouse_packet[0] & 0xF) - { - case 2: - *btn_down = 0; - break; - case 1: - case 0: - *btn_down = 1; - break; - default: - g_assert_not_reached (); - break; - } - - *x = mouse->mouse_packet[1] + (mouse->mouse_packet[2] << 7); - if (*x > 8192) - *x -= 16384; - *y = mouse->mouse_packet[3] + (mouse->mouse_packet[4] << 7); - if (*y > 8192) - *y -= 16384; - /* Now map touchscreen coords to screen coords */ - *x *= ((double)gdk_display->modeinfo.xres)/4096.0; - *y *= ((double)gdk_display->modeinfo.yres)/4096.0; - n = 5; - keep_reading = FALSE; - } - - if (n) - { - memmove (mouse->mouse_packet, mouse->mouse_packet+n, mouse->packet_nbytes-n); - mouse->packet_nbytes -= n; - } - } - - return TRUE; -} - -static gboolean -handle_input_fidmour (GIOChannel *gioc, - GIOCondition cond, - gpointer data) -{ - MouseDevice *mouse = data; - gdouble x, y, oldx, oldy; - gboolean got_motion = FALSE; - gboolean btn_down; - guint32 the_time; - - the_time = gdk_fb_get_time (); - - oldx = mouse->x; - oldy = mouse->y; - while (pull_fidmour_packet (mouse, &btn_down, &x, &y)) - { - if (fabs(x - mouse->x) >= 1.0 || fabs(x - mouse->y) >= 1.0) - { - got_motion = TRUE; - mouse->x = x; - mouse->y = y; - } - - if (btn_down != mouse->button1_pressed) - { - if (got_motion) - { - handle_mouse_input (mouse, TRUE); - got_motion = FALSE; - } - - mouse->button1_pressed = btn_down; - send_button_event (mouse, 1, btn_down, the_time); - } - } - - if (got_motion) - handle_mouse_input (mouse, TRUE); - - return TRUE; -} - -static gboolean -handle_input_ps2 (GIOChannel *gioc, - GIOCondition cond, - gpointer data) -{ - MouseDevice *mouse = data; - int n, dx=0, dy=0; - gboolean new_button1, new_button2, new_button3; - guint32 the_time; - gboolean got_motion = FALSE; - guchar *buf; - - the_time = gdk_fb_get_time (); - - while (1) /* Go through as many mouse events as we can */ - { - n = read (mouse->fd, mouse->mouse_packet + mouse->packet_nbytes, 3 - mouse->packet_nbytes); - if (n<=0) /* error or nothing to read */ - break; - - mouse->packet_nbytes += n; - - if (mouse->packet_nbytes < 3) /* Mouse packet not finished */ - break; - - mouse->packet_nbytes = 0; - - /* Finished reading a packet */ - buf = mouse->mouse_packet; - - new_button1 = (buf[0] & 1) && 1; - new_button3 = (buf[0] & 2) && 1; - new_button2 = (buf[0] & 4) && 1; - - if (got_motion && - (new_button1 != mouse->button1_pressed || - new_button2 != mouse->button2_pressed || - new_button3 != mouse->button3_pressed)) - { - /* If a mouse button state changes we need to get correct ordering with enter/leave events, - so push those out via handle_mouse_input */ - got_motion = FALSE; - handle_mouse_input (mouse, TRUE); - } - - if (new_button1 != mouse->button1_pressed) - { - mouse->button1_pressed = new_button1; - send_button_event (mouse, 1, new_button1, the_time); - } - - if (new_button2 != mouse->button2_pressed) - { - mouse->button2_pressed = new_button2; - send_button_event (mouse, 2, new_button2, the_time); - } - - if (new_button3 != mouse->button3_pressed) - { - mouse->button3_pressed = new_button3; - send_button_event (mouse, 3, new_button3, the_time); - } - - if (buf[1] != 0) - dx = ((buf[0] & 0x10) ? ((gint)buf[1])-256 : buf[1]); - else - dx = 0; - if (buf[2] != 0) - dy = -((buf[0] & 0x20) ? ((gint)buf[2])-256 : buf[2]); - else - dy = 0; - - mouse->x += dx; - mouse->y += dy; - if (dx || dy) - got_motion = TRUE; - } - - if (got_motion) - handle_mouse_input (mouse, TRUE); - - return TRUE; -} - -static gboolean -handle_input_ms (GIOChannel *gioc, - GIOCondition cond, - gpointer data) -{ - MouseDevice *mouse = data; - guchar byte1, byte2, byte3; - int n, dx=0, dy=0; - gboolean new_button1, new_button2, new_button3; - guint32 the_time; - - the_time = gdk_fb_get_time (); - - n = read (mouse->fd, &byte1, 1); - if ( (n!=1) || (byte1 & 0x40) != 0x40) - return TRUE; - - n = read (mouse->fd, &byte2, 1); - if ( (n!=1) || (byte2 & 0x40) != 0x00) - return TRUE; - - n = read (mouse->fd, &byte3, 1); - if (n!=1) - return TRUE; - - new_button1 = (byte1 & 0x20) && 1; - new_button2 = (byte1 & 0x10) && 1; - new_button3 = 0; - - if (new_button1 != mouse->button1_pressed) - { - mouse->button1_pressed = new_button1; - send_button_event (mouse, 1, new_button1, the_time); - } - - if (new_button2 != mouse->button2_pressed) - { - mouse->button2_pressed = new_button2; - send_button_event (mouse, 2, new_button2, the_time); - } - - if (new_button3 != mouse->button3_pressed) - { - mouse->button3_pressed = new_button3; - send_button_event (mouse, 3, new_button3, the_time); - } - - dx = (signed char)(((byte1 & 0x03) << 6) | (byte2 & 0x3F)); - dy = (signed char)(((byte1 & 0x0C) << 4) | (byte3 & 0x3F)); - - mouse->x += dx; - mouse->y += dy; - - if (dx || dy) - handle_mouse_input (mouse, TRUE); - - return TRUE; -} - -static MouseDevice * -mouse_open(void) -{ - MouseDevice *retval; - guchar buf[7]; - int i = 0; - GIOChannel *gioc; - char *mousedev, *ctmp; - int mode; - struct termios tty; - enum { PS2_MOUSE, FIDMOUR_MOUSE, MS_MOUSE, UNKNOWN_MOUSE } type; - int flags; - fd_set fds; - char c; - struct timeval tv; - - retval = g_new0 (MouseDevice, 1); - retval->fd = -1; - mode = O_RDWR; - ctmp = getenv ("GDK_MOUSETYPE"); - if (ctmp) - { - if (!strcmp (ctmp, "fidmour")) - type = FIDMOUR_MOUSE; - else if (!strcmp (ctmp, "ps2")) - type = PS2_MOUSE; - else if (!strcmp (ctmp, "ms")) - type = MS_MOUSE; - else - { - g_print ("Unknown mouse type %s\n", ctmp); - type = UNKNOWN_MOUSE; - } - } - else - type = PS2_MOUSE; - - switch (type) - { - case PS2_MOUSE: - mousedev = "/dev/psaux"; - mode = O_RDWR; - break; - case MS_MOUSE: - mousedev = "/dev/ttyS0"; - mode = O_RDWR; - break; - case FIDMOUR_MOUSE: - mousedev = "/dev/fidmour"; - mode = O_RDONLY; - break; - default: - goto error; - break; - } - - ctmp = getenv ("GDK_MOUSEDEV"); - if (ctmp) - mousedev = ctmp; - - /* Use nonblocking mode to open, to not hang on device */ - retval->fd = open (mousedev, mode | O_NONBLOCK); - if (retval->fd < 0) - goto error; - - flags = fcntl (retval->fd, F_GETFL); - fcntl (retval->fd, F_SETFL, flags & ~O_NONBLOCK); - - switch (type) - { - case PS2_MOUSE: - /* From xf86_Mouse.c */ - buf[i++] = 230; /* 1:1 scaling */ - buf[i++] = 244; /* enable mouse */ - buf[i++] = 243; /* Sample rate */ - buf[i++] = 200; - buf[i++] = 232; /* device resolution */ - buf[i++] = 1; - write (retval->fd, buf, i); - fcntl (retval->fd, F_SETFL, O_RDWR|O_NONBLOCK); - - usleep (10000); /* sleep 10 ms, then read whatever junk we can get from the mouse, in a vain attempt - to get synchronized with the event stream */ - while ((i = read (retval->fd, buf, sizeof(buf))) > 0) - g_print ("Got %d bytes of junk from psaux\n", i); - - gioc = g_io_channel_unix_new (retval->fd); - retval->fd_tag = g_io_add_watch (gioc, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, handle_input_ps2, retval); - break; - - case MS_MOUSE: - /* Read all data from fd: */ - FD_ZERO (&fds); - FD_SET (retval->fd, &fds); - tv.tv_sec = 0; - tv.tv_usec = 0; - while (select (retval->fd+1, &fds, NULL, NULL, &tv) > 0) { - FD_ZERO (&fds); - FD_SET (retval->fd, &fds); - tv.tv_sec = 0; - tv.tv_usec = 0; - read (retval->fd, &c, 1); - } - - tcgetattr (retval->fd, &tty); - tty.c_iflag = IGNBRK | IGNPAR; - tty.c_cflag = CREAD|CLOCAL|HUPCL|CS7|B1200; - tty.c_oflag = 0; - tty.c_lflag = 0; - tty.c_line = 0; - tty.c_cc[VTIME] = 0; - tty.c_cc[VMIN] = 1; - tcsetattr (retval->fd, TCSAFLUSH, &tty); - - write (retval->fd, "*n", 2); - - gioc = g_io_channel_unix_new (retval->fd); - retval->fd_tag = g_io_add_watch (gioc, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, handle_input_ms, retval); - break; - - case FIDMOUR_MOUSE: - fcntl (retval->fd, F_SETFL, O_RDONLY|O_NONBLOCK); - gioc = g_io_channel_unix_new (retval->fd); - /* We set the priority lower here because otherwise it will flood out all the other stuff */ - retval->fd_tag = g_io_add_watch_full (gioc, G_PRIORITY_DEFAULT, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, - handle_input_fidmour, retval, NULL); - break; - default: - g_assert_not_reached (); - break; - } - - retval->x = gdk_display->modeinfo.xres >> 1; - retval->y = gdk_display->modeinfo.yres >> 1; - - return retval; - - error: - /* No errors allowed once fd_tag is added */ - g_warning ("Failed to open mouse device\n"); - if (retval->fd >= 0) - close (retval->fd); - g_free (retval); - return NULL; -} - void gdk_input_init (void) { @@ -1085,21 +101,7 @@ gdk_input_init (void) gdk_input_ignore_core = FALSE; - gdk_fb_mouse = mouse_open (); -} - -void -gdk_input_get_mouseinfo (gint *x, - gint *y, - GdkModifierType *mask) -{ - *x = gdk_fb_mouse->x; - *y = gdk_fb_mouse->y; - *mask = - (gdk_fb_mouse->button1_pressed?GDK_BUTTON1_MASK:0) | - (gdk_fb_mouse->button2_pressed?GDK_BUTTON2_MASK:0) | - (gdk_fb_mouse->button3_pressed?GDK_BUTTON3_MASK:0) | - keyboard->modifier_state; + gdk_fb_mouse_open (); } GdkWindow * diff --git a/gdk/linux-fb/gdkmain-fb.c b/gdk/linux-fb/gdkmain-fb.c index 8a7d258f79..c8f8d12a9e 100644 --- a/gdk/linux-fb/gdkmain-fb.c +++ b/gdk/linux-fb/gdkmain-fb.c @@ -966,10 +966,9 @@ gdk_event_make (GdkWindow *window, if (evmask & (GDK_BUTTON1_MOTION_MASK|GDK_BUTTON2_MOTION_MASK|GDK_BUTTON3_MOTION_MASK)) { - gint x, y; GdkModifierType mask; - gdk_input_get_mouseinfo (&x, &y, &mask); + gdk_mouse_get_info (NULL, NULL, &mask); if (((mask & GDK_BUTTON1_MASK) && (evmask & GDK_BUTTON1_MOTION_MASK)) || ((mask & GDK_BUTTON2_MASK) && (evmask & GDK_BUTTON2_MOTION_MASK)) || diff --git a/gdk/linux-fb/gdkmouse-fb.c b/gdk/linux-fb/gdkmouse-fb.c new file mode 100644 index 0000000000..3a149a28da --- /dev/null +++ b/gdk/linux-fb/gdkmouse-fb.c @@ -0,0 +1,618 @@ +#include +#include +#include "gdkprivate-fb.h" +#include +#include +#include +#include +#include +#include +#include + +typedef struct _GdkFBMouse GdkFBMouse; +typedef struct _GdkFBMouseDevice GdkFBMouseDevice; + +struct _GdkFBMouse { + gint fd; /* Set by open */ + + /* These are written to by parse_packet */ + gdouble x, y; + gboolean button_pressed[3]; + + guchar mouse_packet[5]; /* read by parse_packet */ + gint packet_nbytes; + + gboolean click_grab; + GIOChannel *io; + gint io_tag; + + GdkFBMouseDevice *dev; +}; + +static GdkFBMouse *gdk_fb_mouse = NULL; + +void +gdk_mouse_get_info (gint *x, + gint *y, + GdkModifierType *mask) +{ + if (x) + *x = gdk_fb_mouse->x; + if (y) + *y = gdk_fb_mouse->y; + if (mask) + *mask = + (gdk_fb_mouse->button_pressed[0]?GDK_BUTTON1_MASK:0) | + (gdk_fb_mouse->button_pressed[1]?GDK_BUTTON2_MASK:0) | + (gdk_fb_mouse->button_pressed[2]?GDK_BUTTON3_MASK:0) | + /*keyboard->modifier_state*/0; //TODO +} + +static void +handle_mouse_movement(GdkFBMouse *mouse) +{ + GdkWindow *mousewin; + GdkEvent *event; + gint x, y; + GdkWindow *win, *grabwin; + guint state; + GdkDrawableFBData *mousewin_private; + + if (_gdk_fb_pointer_grab_confine) + mousewin = _gdk_fb_pointer_grab_confine; + else + mousewin = gdk_parent_root; + + mousewin_private = GDK_DRAWABLE_IMPL_FBDATA (mousewin); + + if (mouse->x < mousewin_private->llim_x) + mouse->x = mousewin_private->llim_x; + else if (mouse->x > mousewin_private->lim_x - 1) + mouse->x = mousewin_private->lim_x - 1; + + if (mouse->y < mousewin_private->llim_y) + mouse->y = mousewin_private->llim_y; + else if (mouse->y > mousewin_private->lim_y - 1) + mouse->y = mousewin_private->lim_y - 1; + + win = gdk_window_at_pointer (NULL, NULL); + if (_gdk_fb_pointer_grab_window_events) + grabwin = _gdk_fb_pointer_grab_window_events; + else + grabwin = win; + + gdk_fb_cursor_move (mouse->x, mouse->y, grabwin); + + gdk_window_get_origin (grabwin, &x, &y); + x = mouse->x - x; + y = mouse->y - y; + + state = (mouse->button_pressed[0]?GDK_BUTTON1_MASK:0) | + (mouse->button_pressed[1]?GDK_BUTTON2_MASK:0) | + (mouse->button_pressed[2]?GDK_BUTTON3_MASK:0) | + /*keyboard->modifier_state*/0; // TODO + + event = gdk_event_make (grabwin, GDK_MOTION_NOTIFY, TRUE); + if (event) + { + event->motion.x = x; + event->motion.y = y; + event->motion.state = state; + event->motion.is_hint = FALSE; + event->motion.device = gdk_core_pointer; + event->motion.x_root = mouse->x; + event->motion.y_root = mouse->y; + } + + gdk_fb_window_send_crossing_events (win, GDK_CROSSING_NORMAL); +} + +static void +send_button_event (GdkFBMouse *mouse, + guint button, + gboolean press_event) +{ + GdkEvent *event; + gint x, y, i; + GdkWindow *window; + int nbuttons; + + if (_gdk_fb_pointer_grab_window_events) + window = _gdk_fb_pointer_grab_window_events; + else + window = gdk_window_at_pointer(NULL, NULL); + + event = gdk_event_make (window, press_event ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE, FALSE); + + if (event) + { + gdk_window_get_origin (window, &x, &y); + x = mouse->x - x; + y = mouse->y - y; + + event->button.x = x; + event->button.y = y; + event->button.button = button; + event->button.state = (mouse->button_pressed[0]?GDK_BUTTON1_MASK:0) | + (mouse->button_pressed[1] ? GDK_BUTTON2_MASK : 0) | + (mouse->button_pressed[2] ? GDK_BUTTON3_MASK : 0) | + (1 << (button + 8)) /* badhack */ | + /*keyboard->modifier_state*/0; // TODO + event->button.device = gdk_core_pointer; + event->button.x_root = mouse->x; + event->button.y_root = mouse->y; + + gdk_event_queue_append (event); + + /* For double-clicks */ + if (press_event) + gdk_event_button_generate (event); + } + + nbuttons = 0; + for (i=0;i<3;i++) + if (mouse->button_pressed[i]) + nbuttons++; + + /* Handle implicit button grabs: */ + if (press_event && nbuttons == 1) + { + gdk_fb_pointer_grab (window, FALSE, + gdk_window_get_events (window), + NULL, NULL, + GDK_CURRENT_TIME, TRUE); + mouse->click_grab = TRUE; + } + else if (!press_event && nbuttons == 0 && mouse->click_grab) + { + gdk_fb_pointer_ungrab (GDK_CURRENT_TIME, TRUE); + mouse->click_grab = FALSE; + } +} + +/****************************************************** + ************ Device specific mouse code ************** + ******************************************************/ + +struct _GdkFBMouseDevice { + char *name; + gint packet_size; + gboolean (*open)(GdkFBMouse *mouse); + void (*close)(GdkFBMouse *mouse); + gboolean (*parse_packet)(GdkFBMouse *mouse, gboolean *got_motion); +}; + +static gboolean handle_mouse_io (GIOChannel *gioc, + GIOCondition cond, + gpointer data); +static gboolean gdk_fb_mouse_ps2_open (GdkFBMouse *mouse); +static void gdk_fb_mouse_ps2_close (GdkFBMouse *mouse); +static gboolean gdk_fb_mouse_ps2_packet (GdkFBMouse *mouse, + gboolean *got_motion); +static gboolean gdk_fb_mouse_ms_open (GdkFBMouse *mouse); +static void gdk_fb_mouse_ms_close (GdkFBMouse *mouse); +static gboolean gdk_fb_mouse_ms_packet (GdkFBMouse *mouse, + gboolean *got_motion); +static gboolean gdk_fb_mouse_fidmour_open (GdkFBMouse *mouse); +static void gdk_fb_mouse_fidmour_close (GdkFBMouse *mouse); +static gboolean gdk_fb_mouse_fidmour_packet (GdkFBMouse *mouse, + gboolean *got_motion); + +static GdkFBMouseDevice mouse_devs[] = +{ + { "ps2", + 3, + gdk_fb_mouse_ps2_open, + gdk_fb_mouse_ps2_close, + gdk_fb_mouse_ps2_packet + }, + { "ms", + 3, + gdk_fb_mouse_ms_open, + gdk_fb_mouse_ms_close, + gdk_fb_mouse_ms_packet + }, + { "fidmour", + 5, + gdk_fb_mouse_fidmour_open, + gdk_fb_mouse_fidmour_close, + gdk_fb_mouse_fidmour_packet + } +}; + + +gboolean +gdk_fb_mouse_open (void) +{ + GdkFBMouse *mouse; + GdkFBMouseDevice *device; + char *mouse_type; + int i; + + mouse = g_new0 (GdkFBMouse, 1); + mouse->fd = -1; + mouse_type = getenv ("GDK_MOUSETYPE"); + if (!mouse_type) + mouse_type = "ps2"; + + for (i=0;idev = device; + + mouse->x = gdk_display->modeinfo.xres / 2; + mouse->y = gdk_display->modeinfo.yres / 2; + + if (!device->open(mouse)) + { + g_warning ("Mouse driver open failed\n"); + g_free (mouse); + return FALSE; + } + + mouse->io = g_io_channel_unix_new (mouse->fd); + mouse->io_tag = g_io_add_watch (mouse->io, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, handle_mouse_io, mouse); + + gdk_fb_mouse = mouse; + return TRUE; +} + +void +gdk_fb_mouse_close (void) +{ + g_source_remove (gdk_fb_mouse->io_tag); + gdk_fb_mouse->dev->close(gdk_fb_mouse); + g_io_channel_unref (gdk_fb_mouse->io); + g_free (gdk_fb_mouse); +} + +static gboolean +handle_mouse_io (GIOChannel *gioc, + GIOCondition cond, + gpointer data) +{ + GdkFBMouse *mouse = (GdkFBMouse *)data; + GdkFBMouseDevice *dev = mouse->dev; + gboolean got_motion; + gint n; + + got_motion = FALSE; + + while (1) + { + n = read (mouse->fd, mouse->mouse_packet + mouse->packet_nbytes, dev->packet_size - mouse->packet_nbytes); + if (n<=0) /* error or nothing to read */ + break; + + mouse->packet_nbytes += n; + + if (mouse->packet_nbytes == dev->packet_size) + { + if (dev->parse_packet (mouse, &got_motion)) + mouse->packet_nbytes = 0; + } + } + + if (got_motion) + handle_mouse_movement (mouse); + + return TRUE; +} + +static gint +gdk_fb_mouse_dev_open (char *devname, gint mode) +{ + gint fd; + + /* Use nonblocking mode to open, to not hang on device */ + fd = open (devname, mode | O_NONBLOCK); + return fd; +} + +static gboolean +gdk_fb_mouse_ps2_open (GdkFBMouse *mouse) +{ + gint fd; + guchar buf[7]; + int i = 0; + + fd = gdk_fb_mouse_dev_open ("/dev/psaux", O_RDWR); + if (fd < 0) + return FALSE; + + /* From xf86_Mouse.c */ + buf[i++] = 230; /* 1:1 scaling */ + buf[i++] = 244; /* enable mouse */ + buf[i++] = 243; /* Sample rate */ + buf[i++] = 200; + buf[i++] = 232; /* device resolution */ + buf[i++] = 1; + + write (fd, buf, i); + + usleep (10000); /* sleep 10 ms, then read whatever junk we can get from the mouse, in a vain attempt + to get synchronized with the event stream */ + + while ((i = read (fd, buf, sizeof(buf))) > 0) + g_print ("Got %d bytes of junk from psaux\n", i); + + mouse->fd = fd; + return TRUE; +} + +static void +gdk_fb_mouse_ps2_close (GdkFBMouse *mouse) +{ + close (mouse->fd); +} + +static gboolean +gdk_fb_mouse_ps2_packet (GdkFBMouse *mouse, gboolean *got_motion) +{ + int dx=0, dy=0; + gboolean new_button1, new_button2, new_button3; + guchar *buf; + + buf = mouse->mouse_packet; + + new_button1 = (buf[0] & 1) && 1; + new_button3 = (buf[0] & 2) && 1; + new_button2 = (buf[0] & 4) && 1; + + + if (*got_motion && + (new_button1 != mouse->button_pressed[0] || + new_button2 != mouse->button_pressed[1] || + new_button3 != mouse->button_pressed[2])) + { + /* If a mouse button state changes we need to get correct ordering with enter/leave events, + so push those out via handle_mouse_input */ + *got_motion = FALSE; + handle_mouse_movement (mouse); + } + + if (new_button1 != mouse->button_pressed[0]) + { + mouse->button_pressed[0] = new_button1; + send_button_event (mouse, 1, new_button1); + } + + if (new_button2 != mouse->button_pressed[1]) + { + mouse->button_pressed[1] = new_button2; + send_button_event (mouse, 2, new_button2); + } + + if (new_button3 != mouse->button_pressed[2]) + { + mouse->button_pressed[2] = new_button3; + send_button_event (mouse, 3, new_button3); + } + + if (buf[1] != 0) + dx = ((buf[0] & 0x10) ? ((gint)buf[1])-256 : buf[1]); + else + dx = 0; + if (buf[2] != 0) + dy = -((buf[0] & 0x20) ? ((gint)buf[2])-256 : buf[2]); + else + dy = 0; + + mouse->x += dx; + mouse->y += dy; + + if (dx || dy) + *got_motion = TRUE; + + return TRUE; +} + + +static gboolean +gdk_fb_mouse_ms_open (GdkFBMouse *mouse) +{ + gint fd; + gint i; + guchar buf[7]; + struct termios tty; + + fd = gdk_fb_mouse_dev_open ("/dev/ttyS0", O_RDWR); + if (fd < 0) + return FALSE; + + while ((i = read (fd, buf, sizeof(buf))) > 0) + g_print ("Got %d bytes of junk from psaux\n", i); + + tcgetattr (fd, &tty); + tty.c_iflag = IGNBRK | IGNPAR; + tty.c_cflag = CREAD|CLOCAL|HUPCL|CS7|B1200; + tty.c_oflag = 0; + tty.c_lflag = 0; + tty.c_line = 0; + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 1; + tcsetattr (fd, TCSAFLUSH, &tty); + + write (fd, "*n", 2); + + mouse->fd = fd; + return TRUE; +} + +static void +gdk_fb_mouse_ms_close (GdkFBMouse *mouse) +{ + close (mouse->fd); +} + +static gboolean +gdk_fb_mouse_ms_packet (GdkFBMouse *mouse, + gboolean *got_motion) +{ + int dx=0, dy=0; + gboolean new_button1, new_button2, new_button3; + guchar *buf; + + buf = mouse->mouse_packet; + + new_button1 = (buf[0] & 0x20) && 1; + new_button2 = (buf[1] & 0x10) && 1; + new_button3 = 0; + + if (*got_motion && + (new_button1 != mouse->button_pressed[0] || + new_button2 != mouse->button_pressed[1] || + new_button3 != mouse->button_pressed[2])) + { + /* If a mouse button state changes we need to get correct ordering with enter/leave events, + so push those out via handle_mouse_input */ + *got_motion = FALSE; + handle_mouse_movement (mouse); + } + + if (new_button1 != mouse->button_pressed[0]) + { + mouse->button_pressed[0] = new_button1; + send_button_event (mouse, 1, new_button1); + } + + if (new_button2 != mouse->button_pressed[1]) + { + mouse->button_pressed[1] = new_button2; + send_button_event (mouse, 2, new_button2); + } + + if (new_button3 != mouse->button_pressed[2]) + { + mouse->button_pressed[2] = new_button3; + send_button_event (mouse, 3, new_button3); + } + + dx = (signed char)(((buf[0] & 0x03) << 6) | (buf[1] & 0x3F)); + dy = (signed char)(((buf[0] & 0x0C) << 4) | (buf[2] & 0x3F)); + + mouse->x += dx; + mouse->y += dy; + + if (dx || dy) + *got_motion = TRUE; + + return TRUE; +} + +static gboolean +gdk_fb_mouse_fidmour_open (GdkFBMouse *mouse) +{ + gint fd; + + fd = gdk_fb_mouse_dev_open ("/dev/fidmour", O_RDONLY); + if (fd < 0) + return FALSE; + + mouse->fd = fd; + return TRUE; +} + +static void +gdk_fb_mouse_fidmour_close (GdkFBMouse *mouse) +{ + close (mouse->fd); +} + +static gboolean +gdk_fb_mouse_fidmour_packet (GdkFBMouse *mouse, + gboolean *got_motion) +{ + int n; + gboolean btn_down = 0; + gdouble x = 0.0, y = 0.0; + + n = 0; + if (!(mouse->mouse_packet[0] & 0x80)) + { + int i; + /* We haven't received any of the packet yet but there is no header at the beginning */ + for (i = 1; i < mouse->packet_nbytes; i++) + { + if (mouse->mouse_packet[i] & 0x80) + { + n = i; + break; + } + } + } + else if (mouse->packet_nbytes > 1 && + ((mouse->mouse_packet[0] & 0x90) == 0x90)) + { + /* eat the 0x90 and following byte, no clue what it's for */ + n = 2; + } + else + { + switch (mouse->mouse_packet[0] & 0xF) + { + case 2: + btn_down = 0; + break; + case 1: + case 0: + btn_down = 1; + break; + default: + g_assert_not_reached (); + break; + } + + x = mouse->mouse_packet[1] + (mouse->mouse_packet[2] << 7); + if (x > 8192) + x -= 16384; + y = mouse->mouse_packet[3] + (mouse->mouse_packet[4] << 7); + if (y > 8192) + y -= 16384; + /* Now map touchscreen coords to screen coords */ + x *= ((double)gdk_display->modeinfo.xres)/4096.0; + y *= ((double)gdk_display->modeinfo.yres)/4096.0; + } + + if (n) + { + memmove (mouse->mouse_packet, mouse->mouse_packet+n, mouse->packet_nbytes-n); + mouse->packet_nbytes -= n; + return FALSE; + } + + if (btn_down != mouse->button_pressed[0]) + { + if (*got_motion) + { + /* If a mouse button state changes we need to get correct + ordering with enter/leave events, so push those out + via handle_mouse_input */ + *got_motion = FALSE; + handle_mouse_movement (mouse); + } + + mouse->button_pressed[0] = btn_down; + send_button_event (mouse, 1, btn_down); + } + + if (fabs(x - mouse->x) >= 1.0 || fabs(x - mouse->y) >= 1.0) + { + *got_motion = TRUE; + mouse->x = x; + mouse->y = y; + } + + return TRUE; +} diff --git a/gdk/linux-fb/gdkprivate-fb.h b/gdk/linux-fb/gdkprivate-fb.h index 5f830e7dfe..06d026ca94 100644 --- a/gdk/linux-fb/gdkprivate-fb.h +++ b/gdk/linux-fb/gdkprivate-fb.h @@ -264,8 +264,6 @@ void gdk_window_invalidate_region_clear (GdkWindow *window, GdkRegion *region); void gdk_window_invalidate_rect_clear (GdkWindow *window, GdkRectangle *rect); -GdkWindow *gdk_fb_find_common_ancestor (GdkWindow *win1, - GdkWindow *win2); GdkGC * _gdk_fb_gc_new (GdkDrawable *drawable, GdkGCValues *values, @@ -386,13 +384,18 @@ void gdk_fb_cursor_unhide(void); void gdk_fb_cursor_reset(void); void gdk_fb_cursor_hide(void); void gdk_fb_redraw_all(void); +void gdk_fb_cursor_move (gint x, gint y, GdkWindow *in_window); -void gdk_input_get_mouseinfo (gint *x, - gint *y, - GdkModifierType *mask); void gdk_fb_window_send_crossing_events (GdkWindow *dest, GdkCrossingMode mode); +gboolean gdk_fb_mouse_open (void); +void gdk_fb_mouse_close (void); +void gdk_mouse_get_info (gint *x, + gint *y, + GdkModifierType *mask); + + #define PANGO_TYPE_FB_FONT (pango_fb_font_get_type ()) #define PANGO_FB_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FB_FONT, PangoFBFont)) diff --git a/gdk/linux-fb/gdkwindow-fb.c b/gdk/linux-fb/gdkwindow-fb.c index b4b691d039..0d03563a8e 100644 --- a/gdk/linux-fb/gdkwindow-fb.c +++ b/gdk/linux-fb/gdkwindow-fb.c @@ -34,6 +34,8 @@ #include +/* Global variables: */ +static GdkWindow *gdk_fb_window_containing_pointer = NULL; static gpointer parent_class = NULL; static void recompute_drawable (GdkDrawable *drawable); @@ -438,7 +440,7 @@ gdk_fb_redraw_all (void) gdk_window_process_all_updates (); } -GdkWindow * +static GdkWindow * gdk_fb_find_common_ancestor (GdkWindow *win1, GdkWindow *win2) { @@ -474,6 +476,180 @@ gdk_fb_find_common_ancestor (GdkWindow *win1, return GDK_WINDOW (tmp); } +void +gdk_fb_window_send_crossing_events (GdkWindow *dest, + GdkCrossingMode mode) +{ + GdkWindow *c; + GdkWindow *win, *last, *next; + GdkEvent *event; + gint x, y, x_int, y_int; + GdkModifierType my_mask; + GList *path, *list; + gboolean non_linear; + gboolean only_grabbed_window; + GdkWindow *a; + GdkWindow *b; + + if ((mode == GDK_CROSSING_NORMAL) && + (dest == gdk_fb_window_containing_pointer)) + return; + + if (gdk_fb_window_containing_pointer == NULL) + gdk_fb_window_containing_pointer = gdk_window_ref (gdk_parent_root); + + if (mode == GDK_CROSSING_UNGRAB) + a = _gdk_fb_pointer_grab_window; + else + a = gdk_fb_window_containing_pointer; + b = dest; + + /* When grab in progress only send normal crossing events about + * the grabbed window. + */ + only_grabbed_window = (_gdk_fb_pointer_grab_window_events != NULL) && + (mode == GDK_CROSSING_NORMAL); + + if (a==b) + return; + + gdk_mouse_get_info (&x, &y, &my_mask); + + c = gdk_fb_find_common_ancestor (a, b); + + non_linear = (c != a) && (c != b); + + if (!only_grabbed_window || (a == _gdk_fb_pointer_grab_window)) + event = gdk_event_make (a, GDK_LEAVE_NOTIFY, TRUE); + else + event = NULL; + if (event) + { + event->crossing.subwindow = NULL; + gdk_window_get_root_origin (a, &x_int, &y_int); + event->crossing.x = x - x_int; + event->crossing.y = y - y_int; + event->crossing.x_root = x; + event->crossing.y_root = y; + event->crossing.mode = mode; + if (non_linear) + event->crossing.detail = GDK_NOTIFY_NONLINEAR; + else if (c==a) + event->crossing.detail = GDK_NOTIFY_INFERIOR; + else + event->crossing.detail = GDK_NOTIFY_ANCESTOR; + event->crossing.focus = FALSE; + event->crossing.state = my_mask; + } + + /* Traverse up from a to (excluding) c */ + if (c != a) + { + last = a; + win = GDK_WINDOW (GDK_WINDOW_OBJECT (a)->parent); + while (win != c) + { + if (!only_grabbed_window || (win == _gdk_fb_pointer_grab_window)) + event = gdk_event_make (win, GDK_LEAVE_NOTIFY, TRUE); + else + event = NULL; + if (event) + { + event->crossing.subwindow = gdk_window_ref (last); + gdk_window_get_root_origin (win, &x_int, &y_int); + event->crossing.x = x - x_int; + event->crossing.y = y - y_int; + event->crossing.x_root = x; + event->crossing.y_root = y; + event->crossing.mode = mode; + if (non_linear) + event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL; + else + event->crossing.detail = GDK_NOTIFY_VIRTUAL; + event->crossing.focus = FALSE; + event->crossing.state = my_mask; + } + last = win; + win = GDK_WINDOW (GDK_WINDOW_OBJECT (win)->parent); + } + } + + /* Traverse down from c to b */ + if (c != b) + { + path = NULL; + win = GDK_WINDOW( GDK_WINDOW_OBJECT (b)->parent); + while (win != c) + { + path = g_list_prepend (path, win); + win = GDK_WINDOW( GDK_WINDOW_OBJECT (win)->parent); + } + + list = path; + while (list) + { + win = (GdkWindow *)list->data; + list = g_list_next (list); + if (list) + next = (GdkWindow *)list->data; + else + next = b; + + if (!only_grabbed_window || (win == _gdk_fb_pointer_grab_window)) + event = gdk_event_make (win, GDK_ENTER_NOTIFY, TRUE); + else + event = NULL; + if (event) + { + event->crossing.subwindow = gdk_window_ref (next); + gdk_window_get_root_origin (win, &x_int, &y_int); + event->crossing.x = x - x_int; + event->crossing.y = y - y_int; + event->crossing.x_root = x; + event->crossing.y_root = y; + event->crossing.mode = mode; + if (non_linear) + event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL; + else + event->crossing.detail = GDK_NOTIFY_VIRTUAL; + event->crossing.focus = FALSE; + event->crossing.state = my_mask; + } + } + g_list_free (path); + } + + if (!only_grabbed_window || (b == _gdk_fb_pointer_grab_window)) + event = gdk_event_make (b, GDK_ENTER_NOTIFY, TRUE); + else + event = NULL; + if (event) + { + event->crossing.subwindow = NULL; + gdk_window_get_root_origin (b, &x_int, &y_int); + event->crossing.x = x - x_int; + event->crossing.y = y - y_int; + event->crossing.x_root = x; + event->crossing.y_root = y; + event->crossing.mode = mode; + if (non_linear) + event->crossing.detail = GDK_NOTIFY_NONLINEAR; + else if (c==a) + event->crossing.detail = GDK_NOTIFY_ANCESTOR; + else + event->crossing.detail = GDK_NOTIFY_INFERIOR; + event->crossing.focus = FALSE; + event->crossing.state = my_mask; + } + + if ((mode != GDK_CROSSING_GRAB) && + (b != gdk_fb_window_containing_pointer)) + { + gdk_window_unref (gdk_fb_window_containing_pointer); + gdk_fb_window_containing_pointer = gdk_window_ref (b); + } +} + void gdk_window_show (GdkWindow *window) { @@ -1231,7 +1407,7 @@ gdk_window_get_pointer (GdkWindow *window, window = gdk_parent_root; gdk_window_get_root_origin (window, &x_int, &y_int); - gdk_input_get_mouseinfo (&winx, &winy, &my_mask); + gdk_mouse_get_info (&winx, &winy, &my_mask); winx -= x_int; winy -= y_int;