Re: how to determine if a window has been entered/exited



Hi Brian,

You may want to check the detail field of the enter/leave notify event
in the event handler; something like this :

    if (event->detail != GDK_NOTIFY_INFERIOR)
    {
         /* Your code here */
    }

Cheers,
-- 
Olivier Fourdan <fourdan xfce org>
http://www.xfce.org

On Thu, 2003-05-08 at 15:31, Brian Cameron wrote:
> Gtk+ experts:
> 
> For accessibility purposes, I am trying to write a GTK_MODULE that will
> detect when the mouse has crossed the border of a window.  In other
> words, when the mouse moves from outside the window border to inside
> the window, or from inside the window to outside the window border.
> 
> I have tried using enter-notify-event and leave-notify-event signals
> on the toplevel GtkWindows, and this does not work.  The problem is 
> easily explained by using the gnome-calculator as an example.  The
> area  around the buttons is considered a part of the GtkWindow, so
> you get window enter events each time you leave a button, and you
> get window leave events each time you enter a button.
> 
> Since the GdkCrossing structure only gives you the x/y location
> at the time that the event was generated, it seems impossible to use
> this to determine if the user entered the window from outside window
> or if the user entered the window from a button (and the similar
> problem for leaving).
> 
> I have attached an example program where I try and use different
> techniques to access the information from the enter/leave events.
> All approaches in this sample have the same issues.
> 
> Is there any way to detect that the mouse has moved from outside the
> window border into the window, or from inside the window border to
> outside the window?
> 
> Brian
> 
> ______________________________________________________________________
> 
> /* GDM - The Gnome Display Manager
>  * Copyright (C) 1999, 2000 Martin K. Petersen <mkp mkp net>
>  *
>  * This file Copyright (c) 2003 Sun Microsystems Inc.
>  *
>  * This program is free software; you can redistribute it and/or modify
>  * it under the terms of the GNU General Public License as published by
>  * the Free Software Foundation; either version 2 of the License, or
>  * (at your option) any later version.
>  *
>  * This program 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 General Public License for more s.
>  *
>  * You should have received a copy of the GNU General Public License
>  * along with this program; if not, write to the Free Software
>  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
>  */
> 
> #include <stdio.h>
> #include <stdlib.h>
> #include <ctype.h>
> #include <string.h>
> 
> #include <X11/Xlib.h>
> #include <X11/Xutil.h>
> #include <X11/keysym.h>
> 
> #include <glib.h>
> #include <gmodule.h>
> #include <gdk/gdk.h>
> #include <gdk/gdkx.h>
> #include <gtk/gtk.h>
> #include <gnome.h>
> /*
> #include <glib-object.h>
> */
> 
> #include <config.h>
> 
> /*
>  * Note that CONFIGFILE will have to be changed to something more generic
>  * if this module is ever moved outside of gdm.
>  */
> 
> #define CONFIGFILE EXPANDED_SYSCONFDIR "/gdm/modules/AccessKeyMouseEvents"
> #define	iseol(ch)	((ch) == '\r' || (ch) == '\f' || (ch) == '\0' || \
> 			(ch) == '\n')
> 
> typedef enum
> {
> 	BINDING_TYPE_KEY	= 1 << 0,
> 	BINDING_TYPE_MOUSE	= 1 << 1
> } BindingType;
> 
> typedef struct {
> 	guint keysym;
> 	GdkModifierType state;
> 	guint keycode;
> } Key;
> 
> typedef struct {
> 	guint number;
> 	GdkModifierType state;
> } Button;
> 
> union Input {
> 	Key key;
> 	Button button;
> };
> 
> typedef struct {
> 	BindingType type;
> 	union Input input;
> 	char *binding_str;
> 	GSList *actions;
> 	guint n_times;
> 	guint duration;
> 	guint timeout;
> } Binding;
> 
> static int lineno = 0;
> static GSList *binding_list = NULL;
> extern char **environ;
> 
> static void create_event_watcher ();
> 			
> /* test using filter */
> 
> GdkFilterReturn
> enter_filter (GdkXEvent *gdk_xevent,
> 		    GdkEvent *event,
> 		    gpointer data)
> {
> 	XEvent *xevent = (XEvent *)gdk_xevent;
> 
> 	if (xevent->type != EnterNotify)
> 	 	return GDK_FILTER_CONTINUE;
> 
>         printf("filter: %p %p\n", xevent->xcrossing.window, xevent->xcrossing.subwindow);
>         printf ("%d %d %d %d - ",
>           xevent->xcrossing.x,
>           xevent->xcrossing.y,
>           xevent->xcrossing.x_root,
>           xevent->xcrossing.y_root);
> 
>         if (xevent->xcrossing.detail == NotifyAncestor)
>         	printf("NotifyAncestor\n");
>         if (xevent->xcrossing.detail == NotifyInferior)
>         	printf("NotifyInferior\n");
>         if (xevent->xcrossing.detail == NotifyVirtual)
>         	printf("NotifyVirtual\n");
>         if (xevent->xcrossing.detail == NotifyNonlinear)
>         	printf("NotifyNonlinear\n");
>         if (xevent->xcrossing.detail == NotifyNonlinearVirtual)
>         	printf("NotifyNonlinearVirtual\n");
> 
> 
> 
>   return GDK_FILTER_CONTINUE;
> }
> 
> /* using emission-hook */
> static gboolean
> enter_emission_hook (GSignalInvocationHint	*ihint,
>                      guint			n_param_values,
>                      const GValue		*param_values,
>                      gpointer			data)
> {
>   GObject *object;
>   GtkWindow *window;
>   GdkEventCrossing *event;
> 
>   object = g_value_get_object (param_values + 0);
>   event = g_value_get_boxed (param_values + 1);
> 
>   if (GTK_IS_WINDOW(object) && GTK_WIDGET_TOPLEVEL(object))
>       printf("window     - emission-hook: %p %p %p\n", object, event->window, event->subwindow);
>   else
>       printf("non-window - emission-hook: %p %p %p\n", object, event->window, event->subwindow);
> 
>   return TRUE;
> }
> 
> /* Using signal-connect */
> 
> gboolean
> signal_connect_enter_cb (GtkWidget *widget,
>           GdkEventCrossing *event,
>           gpointer user_data)
> {
>    if (GTK_IS_WINDOW(widget) && GTK_WIDGET_TOPLEVEL(widget))
>        printf("window     - signal-connect: %p %p %p\n", widget, event->window, event->subwindow);
>    else
>        printf("non-window - signal-connect: %p %p %p\n", widget, event->window, event->subwindow);
> }
> 
> /* this emission hook is used to set up the signal-connect situation.  It connects any
>    window that is shown to the enter-notify-event signal. */
> 
> static gboolean
> show_event_emission_hook (GSignalInvocationHint		*ihint,
> 				  guint			 n_param_values,
> 				  const GValue		*param_values,
> 				  gpointer		 data)
> {
>   GObject *object;
>   GtkWidget *widget;
> 
>   object = g_value_get_object (param_values + 0);
> 
>   if (!GTK_IS_WINDOW (object))
>     return TRUE;
> 
>   widget = GTK_WIDGET(object);
> 
>   g_signal_connect(widget, "enter-notify-event", G_CALLBACK(signal_connect_enter_cb), NULL);
> }
> 
> static void create_event_watcher ()
> {
> 	GSList *li;
> 	GdkDisplay *display;
>         guint signal_id;
> 
> 	display = gdk_display_get_default();
> 	if (!display) {
> 		return;
> 	}
> 
>         /* set up filter */
> 	gdk_window_add_filter (NULL, enter_filter, NULL);
> 
>         gtk_type_class (GTK_TYPE_WIDGET);
> 
>         /* set up emission hook */
>         g_signal_add_emission_hook(
>           g_signal_lookup("enter-notify-event", GTK_TYPE_WIDGET), 0,
>           enter_emission_hook, NULL, (GDestroyNotify) NULL); 
> 
>         /* set up emission hook that will then set up the direct g_connect on the window */
>         gtk_type_class (GTK_TYPE_WINDOW);
> 
>         signal_id  = g_signal_lookup ("show", GTK_TYPE_WINDOW);
>         g_signal_add_emission_hook (signal_id, 0,
>            show_event_emission_hook, NULL, (GDestroyNotify) NULL);
> 
> 	return;
> }
> 
> /* The init function for this gtk module */
> G_MODULE_EXPORT void gtk_module_init(int *argc, char* argv[]);
> 
> void gtk_module_init(int *argc, char* argv[])
> {
> 	create_event_watcher();
> }		
> 
> /* EOF */





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]