gnome-control-center/gnome-settings-daemon/gnome-settings-locate-pointer.c
Jonathan Blandford 09a24e9d5d Patch from Anders Carlsson to special case "both-horiz".
Thu Jul 31 14:22:38 2003  Jonathan Blandford  <jrb@redhat.com>

        * gnome-settings-xsettings.c (translate_string_string_toolbar):
        Patch from Anders Carlsson to special case "both-horiz".

Thu Jul 31 14:06:51 2003  Jonathan Blandford  <jrb@redhat.com>

        * gnome-settings-mouse.c: Patch from Satyajit Kanungo
        <satyajit.kanungo@wipro.com> to make locate pointer work in
        a multi-screen environment.
2003-07-31 18:27:44 +00:00

227 lines
5.2 KiB
C

#include <gtk/gtk.h>
#include "gnome-settings-locate-pointer.h"
#include "gnome-settings-daemon.h"
#define LARGE_SIZE 101
#define SMALL_SIZE 51
typedef enum {
STAGE_ONE,
STAGE_TWO,
STAGE_THREE,
STAGE_FOUR,
STAGE_DONE
} LocatePointerStage;
static LocatePointerStage stage;
static GdkWindow *window = NULL;
static gint cursor_x, cursor_y;
static guint locate_pointer_id = 0;
static gint
locate_pointer_expose (GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
gint size;
GdkPoint points[4];
if (event->window != window)
return FALSE;
switch (stage)
{
case STAGE_ONE:
case STAGE_TWO:
size = LARGE_SIZE;
break;
case STAGE_THREE:
case STAGE_FOUR:
size = SMALL_SIZE;
break;
default:
return FALSE;
}
gdk_draw_rectangle (event->window,
widget->style->black_gc,
TRUE,
0, 0, size, size);
switch (stage)
{
case STAGE_ONE:
case STAGE_THREE:
gdk_draw_rectangle (event->window,
widget->style->white_gc,
FALSE,
1, 1, size - 3, size - 3);
break;
case STAGE_TWO:
case STAGE_FOUR:
points[0].x = size/2;
points[0].y = 0 + 1;
points[1].x = size - 2;
points[1].y = size/2;
points[2].x = size/2;
points[2].y = size - 2;
points[3].x = 0 + 1;
points[3].y = size/2;
gdk_draw_polygon (event->window,
widget->style->white_gc,
FALSE, points, 4);
break;
default:
g_assert_not_reached ();
}
return TRUE;
}
static void
setup_window (void)
{
gint size;
GdkBitmap *mask;
GdkGC *gc;
GdkColor col;
GdkPoint points[4];
gdk_window_hide (window);
switch (stage)
{
case STAGE_ONE:
case STAGE_TWO:
size = LARGE_SIZE;
break;
case STAGE_THREE:
case STAGE_FOUR:
size = SMALL_SIZE;
break;
default:
return;
}
gdk_window_move_resize (window,
cursor_x - size/2,
cursor_y - size/2,
size, size);
mask = gdk_pixmap_new (window, size, size, 1);
gc = gdk_gc_new (mask);
switch (stage)
{
case STAGE_ONE:
case STAGE_THREE:
col.pixel = 1;
gdk_gc_set_foreground (gc, &col);
gdk_draw_rectangle (mask, gc, TRUE, 0, 0, size, size);
col.pixel = 0;
gdk_gc_set_foreground (gc, &col);
gdk_draw_rectangle (mask, gc, TRUE, 3, 3, size - 6, size - 6);
break;
case STAGE_TWO:
case STAGE_FOUR:
col.pixel = 0;
gdk_gc_set_foreground (gc, &col);
gdk_draw_rectangle (mask, gc, TRUE, 0, 0, size, size);
col.pixel = 1;
gdk_gc_set_foreground (gc, &col);
points[0].x = size/2;
points[0].y = 0;
points[1].x = size - 1;
points[1].y = size/2;
points[2].x = size/2;
points[2].y = size - 1;
points[3].x = 0;
points[3].y = size/2;
gdk_draw_polygon (mask, gc, FALSE, points, 4);
points[0].x = size/2;
points[0].y = 0 + 1;
points[1].x = size - 2;
points[1].y = size/2;
points[2].x = size/2;
points[2].y = size - 2;
points[3].x = 0 + 1;
points[3].y = size/2;
gdk_draw_polygon (mask, gc, FALSE, points, 4);
points[0].x = size/2;
points[0].y = 0 + 2;
points[1].x = size - 3;
points[1].y = size/2;
points[2].x = size/2;
points[2].y = size - 3;
points[3].x = 0 + 2;
points[3].y = size/2;
gdk_draw_polygon (mask, gc, FALSE, points, 4);
break;
default:
g_assert_not_reached ();
}
gdk_window_shape_combine_mask (window, mask, 0, 0);
g_object_unref (G_OBJECT (gc));
g_object_unref (G_OBJECT (mask));
gdk_window_show (window);
}
static void
create_window (GdkScreen *screen)
{
GdkWindowAttr attributes;
GtkWidget *invisible;
invisible = gtk_invisible_new_for_screen (screen);
attributes.window_type = GDK_WINDOW_TEMP;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.visual = gtk_widget_get_visual (invisible);
attributes.colormap = gtk_widget_get_colormap (invisible);
attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK;
attributes.width = 1;
attributes.height = 1;
window = gdk_window_new (gdk_screen_get_root_window (screen),
&attributes,
GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP);
gdk_window_set_user_data (window, invisible);
g_signal_connect (G_OBJECT (invisible),
"expose_event",
(GCallback) locate_pointer_expose,
NULL);
}
static gboolean
locate_pointer_timeout (gpointer data)
{
stage++;
if (stage == STAGE_DONE)
{
gdk_window_hide (window);
locate_pointer_id = 0;
return FALSE;
}
setup_window ();
return TRUE;
}
void
gnome_settings_locate_pointer (GdkScreen *screen)
{
gdk_window_get_pointer (gdk_screen_get_root_window (screen), &cursor_x, &cursor_y, NULL);
if (locate_pointer_id)
gtk_timeout_remove (locate_pointer_id);
/* Create the window if it is not created OR if it is not for the
* current screen.
*/
if (window == NULL)
create_window (screen);
else if( gdk_screen_get_number (screen) != gdk_screen_get_number (gdk_drawable_get_screen (window)))
create_window (screen);
stage = STAGE_ONE;
setup_window ();
gdk_window_show (window);
locate_pointer_id = gtk_timeout_add (100, locate_pointer_timeout, NULL);
}