 9012254c1e
			
		
	
	9012254c1e
	
	
	
		
			
			2001-01-17 <alexl@redhat.com> * gdk/linux-fb/gdkdrawable-fb2.c (gdk_shadow_fb_draw_arc): Doh! Mixed up x and y. * gdk/linux-fb/gdkglobals-fb.c: Removed gdk_fb_pointer_grab_window_events, added _gdk_fb_pointer_grab_owner_events and _gdk_fb_keyboard_grab_owner_events. * gdk/linux-fb/gdkmain-fb.c (gdk_fb_pointer_grab): Set all button mask if GDK_BUTTON_MOTION_MASK set. Send crossing events before grabbing. Set _gdk_fb_pointer_grab_owner_events. (gdk_fb_pointer_ungrab): Unset _gdk_fb_pointer_grab_owner_events Send crossing events after ungrab finished. (gdk_keyboard_grab): Set ..._owner_events (type_masks): Move out of function. (gdk_fb_other_event_window, gdk_fb_pointer_event_window, gdk_fb_keyboard_event_window): New functions, return the window an event should be targeted at. Handles grabs and event propagation. Can return NULL. (gdk_event_make): Remove event_mask checking. Now always returns an event. * gdk/linux-fb/gdkkeyboard-fb.c: * gdk/linux-fb/gdkproperty-fb.c: * gdk/linux-fb/gdkselection-fb.c: Use new event_window/gdk_event_make() behaviour. * gdk/linux-fb/gdkmouse-fb.c: Use new event_window/gdk_event_make() behaviour. Only send motion events if in the same window. If grabbed, use cursor from window if sibling of grabbed window, and cursor from grabbed window otherwise. * gdk/linux-fb/gdkprivate-fb.h: Update gdk_fb_window_send_crossing_events, gdk_event_make and grab varaible declarations. Add gdk_fb_*_event_window(). * gdk/linux-fb/gdkwindow-fb.c: Use new event_window/gdk_event_make() behaviour. Keep correct track of focus window. (gdk_window_set_events): Set all specific button motion masks if GDK_BUTTON_MOTION_MASK set. * gtk/gtkdnd.c (gtk_drag_update): Free info->last_event if gdk_drag_motion returned FALSE.
		
			
				
	
	
		
			703 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			703 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* GDK - The GIMP Drawing Kit
 | |
|  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 | |
|  *
 | |
|  * This library is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU Lesser General Public
 | |
|  * License as published by the Free Software Foundation; either
 | |
|  * version 2 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This library is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  * Lesser General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Lesser General Public
 | |
|  * License along with this library; if not, write to the
 | |
|  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 | |
|  * Boston, MA 02111-1307, USA.
 | |
|  */
 | |
| 
 | |
| #include <gdk/gdk.h>
 | |
| #include <gdk/gdkinternals.h>
 | |
| #include "gdkprivate-fb.h"
 | |
| #include <stdlib.h>
 | |
| #include <sys/types.h>
 | |
| #include <fcntl.h>
 | |
| #include <termios.h>
 | |
| #include <sys/ioctl.h>
 | |
| #include <string.h>
 | |
| #include <math.h>
 | |
| 
 | |
| 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_fb_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) |
 | |
|       gdk_fb_keyboard_modifiers ();
 | |
| }
 | |
| 
 | |
| static void
 | |
| handle_mouse_movement(GdkFBMouse *mouse)
 | |
| {
 | |
|   GdkWindow *mousewin;
 | |
|   GdkEvent *event;
 | |
|   gint x, y;
 | |
|   GdkWindow *old_win, *win, *event_win, *cursor_win;
 | |
|   guint state;
 | |
|   GdkDrawableFBData *mousewin_private;
 | |
| 
 | |
|   old_win = gdk_window_at_pointer (NULL, NULL);
 | |
|   
 | |
|   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);
 | |
| 
 | |
|   cursor_win = win;
 | |
|   if (_gdk_fb_pointer_grab_window)
 | |
|     {
 | |
|       GdkWindow *w;
 | |
|       
 | |
|       cursor_win = _gdk_fb_pointer_grab_window;
 | |
|       w = win;
 | |
|       while (w != gdk_parent_root)
 | |
| 	{
 | |
| 	  if (w == _gdk_fb_pointer_grab_window)
 | |
| 	    {
 | |
| 	      cursor_win = win;
 | |
| 	      break;
 | |
| 	    }
 | |
| 	  w = gdk_window_get_parent (w);
 | |
| 	}
 | |
|     }
 | |
|   
 | |
|   gdk_fb_cursor_move (mouse->x, mouse->y, cursor_win);
 | |
| 
 | |
|   event_win = gdk_fb_pointer_event_window (win, GDK_MOTION_NOTIFY);
 | |
| 
 | |
|   if (event_win && (win == old_win))
 | |
|     {
 | |
|       /* Only send motion events in the same window */
 | |
|       gdk_window_get_origin (event_win, &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) |
 | |
| 	gdk_fb_keyboard_modifiers ();
 | |
| 
 | |
|       event = gdk_event_make (event_win, GDK_MOTION_NOTIFY, TRUE);
 | |
|       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 (NULL, win, GDK_CROSSING_NORMAL);
 | |
| }
 | |
| 
 | |
| static void
 | |
| send_button_event (GdkFBMouse *mouse,
 | |
| 		   guint button,
 | |
| 		   gboolean press_event)
 | |
| {
 | |
|   GdkEvent *event;
 | |
|   gint x, y, i;
 | |
|   GdkWindow *mouse_win;
 | |
|   GdkWindow *event_win;
 | |
|   int nbuttons;
 | |
| 
 | |
|   
 | |
|   mouse_win = gdk_window_at_pointer(NULL, NULL);
 | |
|   event_win = gdk_fb_pointer_event_window (mouse_win,
 | |
| 					   press_event ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
 | |
|   
 | |
|   if (event_win)
 | |
|     {
 | |
|       event = gdk_event_make (event_win, press_event ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE, FALSE);
 | |
|       
 | |
|       gdk_window_get_origin (event_win, &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 */ |
 | |
| 	gdk_fb_keyboard_modifiers ();
 | |
|       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 (mouse_win, FALSE,
 | |
| 			   gdk_window_get_events (mouse_win),
 | |
| 			   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 **************
 | |
|  ******************************************************/
 | |
| 
 | |
| /* proto is used to detect the start of the packet:
 | |
|  *   (buf[0]&proto[0]) == proto[1]
 | |
|  * indicates start of packet.
 | |
|  */
 | |
| 
 | |
| struct _GdkFBMouseDevice {
 | |
|   char *name;
 | |
|   gint packet_size;
 | |
|   gboolean (*open)(GdkFBMouse *mouse);
 | |
|   void (*close)(GdkFBMouse *mouse);
 | |
|   gboolean (*parse_packet)(GdkFBMouse *mouse, gboolean *got_motion);
 | |
|   guchar proto[2];
 | |
| };
 | |
| 
 | |
| 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,
 | |
|     { 0xc0, 0x00 }
 | |
|   },
 | |
|   { "imps2",
 | |
|     4,
 | |
|     gdk_fb_mouse_ps2_open,
 | |
|     gdk_fb_mouse_ps2_close,
 | |
|     gdk_fb_mouse_ps2_packet,
 | |
|     { 0xc0, 0x00 }
 | |
|   },
 | |
|   { "ms",
 | |
|     3,
 | |
|     gdk_fb_mouse_ms_open,
 | |
|     gdk_fb_mouse_ms_close,
 | |
|     gdk_fb_mouse_ms_packet,
 | |
|     { 0x40, 0x40 }
 | |
|   },
 | |
|   { "fidmour",
 | |
|     5,
 | |
|     gdk_fb_mouse_fidmour_open,
 | |
|     gdk_fb_mouse_fidmour_close,
 | |
|     gdk_fb_mouse_fidmour_packet,
 | |
|     { 0x00, 0x00 } /* don't know what packet start looks like */
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| 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_MOUSE_TYPE");
 | |
|   if (!mouse_type)
 | |
|     mouse_type = "ps2";
 | |
| 
 | |
|   for (i=0;i<G_N_ELEMENTS(mouse_devs);i++)
 | |
|     {
 | |
|       if (g_strcasecmp(mouse_type, mouse_devs[i].name)==0)
 | |
| 	break;
 | |
|     }
 | |
|   
 | |
|   if (i == G_N_ELEMENTS(mouse_devs))
 | |
|     {
 | |
|       g_warning ("No mouse driver of type %s found", mouse_type);
 | |
|       return FALSE;
 | |
|     }
 | |
| 
 | |
|   device = &mouse_devs[i];
 | |
| 
 | |
|   mouse->dev = device;
 | |
|   
 | |
|   mouse->x = gdk_display->fb_width / 2;
 | |
|   mouse->y = gdk_display->fb_height / 2;
 | |
| 
 | |
|   if (!device->open(mouse))
 | |
|     {
 | |
|       g_warning ("Mouse driver open failed");
 | |
|       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;
 | |
|   guchar *proto = dev->proto;
 | |
|   gboolean got_motion;
 | |
|   gint n, i;
 | |
| 
 | |
|   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;
 | |
| 
 | |
|       /* we just read in what should be the first byte of a packet */
 | |
|       if (mouse->packet_nbytes == 0)
 | |
| 	{
 | |
| 	  /* check to see if we have the first byte of a packet.
 | |
| 	   * if not, throw it away */
 | |
| 	  while ((mouse->mouse_packet[0] & proto[0]) != proto[1] && n > 0)
 | |
| 	    {
 | |
| 	      for (i = 1; i < n; i++)
 | |
| 		mouse->mouse_packet[i-1] = mouse->mouse_packet[i];
 | |
| 	      n--;
 | |
| 	    }
 | |
| 	  /* if none of the bytes read were packet starts, break */
 | |
| 	  if (n <= 0)
 | |
| 	    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/mouse", O_RDWR);
 | |
|   if (fd < 0)
 | |
|     return FALSE;
 | |
|   
 | |
|   while ((i = read (fd, buf, sizeof(buf))) > 0)
 | |
|     g_print ("Got %d bytes of junk from /dev/mouse\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;
 | |
|   static guchar prev = 0;
 | |
| 
 | |
|   buf = mouse->mouse_packet;
 | |
| 
 | |
|   /* handling of third button is adapted from gpm ms driver */
 | |
|   if (buf[0] == 0x40 && !(prev|buf[1]|buf[2]))
 | |
|     {
 | |
|       new_button1 = 0;
 | |
|       new_button2 = 1;
 | |
|       new_button3 = 0;
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       new_button1 = (buf[0] & 0x20) && 1;
 | |
|       new_button2 = 0;
 | |
|       new_button3 = (buf[0] & 0x10) && 1;
 | |
|     }
 | |
|   prev = (new_button1 << 2) | (new_button2 << 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->fb_width)/4096.0;
 | |
|       y *= ((double)gdk_display->fb_height)/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;
 | |
| }
 |