Re: how to determine if a window has been entered/exited
- From: Brian Cameron <Brian Cameron sun com>
- To: Brian Cameron sun com, sven gimp org
- Cc: gtk-devel-list gnome org
- Subject: Re: how to determine if a window has been entered/exited
- Date: Thu, 8 May 2003 15:41:55 +0100 (BST)
Sven/Oliver:
> Brian Cameron <Brian Cameron sun com> writes:
>
> > 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 think you should be able to differentiate between these events by
> looking at the GdkNotifyType which is part of the GdkCrossing
> structure.
Unfortunately this doesn't seem to be the case. Using a few programs
to check, I notice that the detail is either NotifyVirtual or
NotifyAncestor when I move the mouse into the window. You can see
this using the example GTK_MODULE that I sent in my last email.
Just run gnome-calculator as follows, for example:
gnome-calculator --gtk-module=/path/dwellmouselistener.so
The "detail" value seems to be NotifyAncestor if the mouse is moving
into an area of the screen that is considered a part of the GtkWindow
(like the areas around the calculator buttons). It is NotifyVirtual
otherwise.
Using gnome-calculator for an example, I get "NotifyVirtual" if I
move into the menubar or the numerical display area of the screen
and I get "NotifyAncestor" if I move into the area where the buttons
are located. The difference seems to be that the areas around the
buttons are considered a part of the GtkWindow whereas the menubar
and numerical display area don't have such space around them. I
notice similar behavior with other programs.
I can get other "NotifyAncestor" enter events to happen moving around
within the window. I can't seem to find a situation where I can get
"MotionVirtual" to happen without entering the window from outside
the border. So it doesn't seem that this is the full solution,
unless there is something I am still missing.
I have also tried calling gdk_window_get_frame_extents and comparing
the values with the x_root and y_root that are passed in with the
event. I was hoping that I could use these to help me determine if
the mouse truly entered or left the window. Unfortunately I notice
that this doesn't work either. Sometimes you leave the window and
it tells you that the x_root and y_root are still inside the window.
sigh... The new attachment shows this problem.
So Oliver's suggestion to use NotifyInferior doesn't seem to be
a help, nor do I see how to use this GdkNotifyType in general
to determine the situation either.
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 details.
*
* 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 guint enter_signal_id = 0;
static guint leave_signal_id = 0;
static void create_event_watcher ();
/* using emission-hook */
static gboolean
leave_enter_emission_hook (GSignalInvocationHint *ihint,
guint n_param_values,
const GValue *param_values,
gpointer data)
{
GObject *object;
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))
{
GtkWidget *widget = GTK_WIDGET(object);
GtkWindow *window = GTK_WINDOW(object);
GdkRectangle rect;
int x_root, y_root;
gdk_window_get_frame_extents (widget->window, &rect);
x_root = (int)event->x_root;
y_root = (int)event->y_root;
if (x_root > rect.x && x_root < rect.x + rect.width &&
y_root > rect.y && y_root < rect.y + rect.height)
{
printf ("inside! %d %d %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height, x_root, y_root);
}
else
{
printf ("outside! %d %d %d %d %d %d\n", rect.x, rect.y, rect.width, rect.height, x_root, y_root);
}
/*
printf("%d %d %d %d\n", rect.x, rect.y, rect.width, rect.height);
printf("%f %f\n", event->x_root, event->y_root);
*/
if (ihint->signal_id == enter_signal_id)
printf("enter - ");
else if (ihint->signal_id == leave_signal_id)
printf("leave - ");
else
printf("error - ");
printf("emission-hook: %p %p %p\n", object, event->window, event->subwindow);
}
return TRUE;
}
static void create_event_watcher ()
{
GSList *li;
GdkDisplay *display;
guint signal_id;
display = gdk_display_get_default();
if (!display) {
return;
}
/* set up emission hook */
gtk_type_class (GTK_TYPE_WIDGET);
enter_signal_id = g_signal_lookup("enter-notify-event", GTK_TYPE_WIDGET);
leave_signal_id = g_signal_lookup("leave-notify-event", GTK_TYPE_WIDGET);
g_signal_add_emission_hook(enter_signal_id, 0,
leave_enter_emission_hook, NULL, (GDestroyNotify) NULL);
g_signal_add_emission_hook(leave_signal_id, 0,
leave_enter_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]