cursor.h

Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2001-2006, William Joseph.
00003  All Rights Reserved.
00004 
00005  This file is part of GtkRadiant.
00006 
00007  GtkRadiant is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation; either version 2 of the License, or
00010  (at your option) any later version.
00011 
00012  GtkRadiant is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with GtkRadiant; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00022 #if !defined(INCLUDED_GTKUTIL_CURSOR_H)
00023 #define INCLUDED_GTKUTIL_CURSOR_H
00024 
00025 #include <glib/gmain.h>
00026 #include <gdk/gdkevents.h>
00027 #include <gtk/gtkwidget.h>
00028 #include <gtk/gtkwindow.h>
00029 
00030 #include "debugging/debugging.h"
00031 
00032 typedef struct _GdkCursor GdkCursor;
00033 typedef struct _GtkWidget GtkWidget;
00034 typedef struct _GtkWindow GtkWindow;
00035 
00036 GdkCursor* create_blank_cursor ();
00037 void Sys_GetCursorPos (GtkWindow* window, int *x, int *y);
00038 void Sys_SetCursorPos (GtkWindow* window, int x, int y);
00039 
00040 class DeferredMotion
00041 {
00042         guint m_handler;
00043         typedef void(*MotionFunction) (gdouble x, gdouble y, guint state, void* data);
00044         MotionFunction m_function;
00045         void* m_data;
00046         gdouble m_x;
00047         gdouble m_y;
00048         guint m_state;
00049 
00050         static gboolean deferred (DeferredMotion* self)
00051         {
00052             self->m_handler = 0;
00053             self->m_function(self->m_x, self->m_y, self->m_state, self->m_data);
00054             return FALSE;
00055         }
00056     public:
00057         DeferredMotion (MotionFunction function, void* data) :
00058             m_handler(0), m_function(function), m_data(data)
00059         {
00060         }
00061         void motion (gdouble x, gdouble y, guint state)
00062         {
00063             m_x = x;
00064             m_y = y;
00065             m_state = state;
00066             if (m_handler == 0) {
00067                 m_handler = g_idle_add((GSourceFunc) deferred, this);
00068             }
00069         }
00070         // greebo: This is the actual callback method that gets connected via to the "motion_notify_event"
00071         static gboolean gtk_motion (GtkWidget *widget, GdkEventMotion *event, DeferredMotion* self)
00072         {
00073             self->motion(event->x, event->y, event->state);
00074             return FALSE;
00075         }
00076 };
00077 
00078 class DeferredMotionDelta
00079 {
00080         int m_delta_x;
00081         int m_delta_y;
00082         guint m_motion_handler;
00083         typedef void (*MotionDeltaFunction) (int x, int y, void* data);
00084         MotionDeltaFunction m_function;
00085         void* m_data;
00086 
00087         static gboolean deferred_motion (gpointer data)
00088         {
00089             reinterpret_cast<DeferredMotionDelta*> (data)->m_function(
00090                     reinterpret_cast<DeferredMotionDelta*> (data)->m_delta_x,
00091                     reinterpret_cast<DeferredMotionDelta*> (data)->m_delta_y,
00092                     reinterpret_cast<DeferredMotionDelta*> (data)->m_data);
00093             reinterpret_cast<DeferredMotionDelta*> (data)->m_motion_handler = 0;
00094             reinterpret_cast<DeferredMotionDelta*> (data)->m_delta_x = 0;
00095             reinterpret_cast<DeferredMotionDelta*> (data)->m_delta_y = 0;
00096             return FALSE;
00097         }
00098     public:
00099         DeferredMotionDelta (MotionDeltaFunction function, void* data) :
00100             m_delta_x(0), m_delta_y(0), m_motion_handler(0), m_function(function), m_data(data)
00101         {
00102         }
00103         void flush ()
00104         {
00105             if (m_motion_handler != 0) {
00106                 g_source_remove(m_motion_handler);
00107                 deferred_motion(this);
00108             }
00109         }
00110         void motion_delta (int x, int y, unsigned int state)
00111         {
00112             m_delta_x += x;
00113             m_delta_y += y;
00114             if (m_motion_handler == 0) {
00115                 m_motion_handler = g_idle_add(deferred_motion, this);
00116             }
00117         }
00118 };
00119 
00120 class FreezePointer
00121 {
00122         unsigned int handle_motion;
00123         int recorded_x, recorded_y;
00124         typedef void (*MotionDeltaFunction) (int x, int y, unsigned int state, void* data);
00125         MotionDeltaFunction m_function;
00126         void* m_data;
00127     public:
00128         FreezePointer () :
00129             handle_motion(0), m_function(0), m_data(0)
00130         {
00131         }
00132         static gboolean motion_delta (GtkWidget *widget, GdkEventMotion *event, FreezePointer* self)
00133         {
00134             int current_x, current_y;
00135             Sys_GetCursorPos(GTK_WINDOW(widget), &current_x, &current_y);
00136             const int dx = current_x - self->recorded_x;
00137             const int dy = current_y - self->recorded_y;
00138             if (dx != 0 || dy != 0) {
00139                 Sys_SetCursorPos(GTK_WINDOW(widget), self->recorded_x, self->recorded_y);
00140                 self->m_function(dx, dy, event->state, self->m_data);
00141             }
00142             return FALSE;
00143         }
00144 
00145         void freeze_pointer (GtkWindow* window, MotionDeltaFunction function, void* data)
00146         {
00147             ASSERT_MESSAGE(m_function == 0, "can't freeze pointer");
00148 
00149             const GdkEventMask mask = static_cast<GdkEventMask> (GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK
00150                     | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK
00151                     | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
00152                     | GDK_VISIBILITY_NOTIFY_MASK);
00153 
00154             GdkCursor* cursor = create_blank_cursor();
00155             //GdkGrabStatus status =
00156             gdk_pointer_grab(GTK_WIDGET(window)->window, TRUE, mask, 0, cursor, GDK_CURRENT_TIME);
00157             gdk_cursor_unref(cursor);
00158 
00159             Sys_GetCursorPos(window, &recorded_x, &recorded_y);
00160 
00161             Sys_SetCursorPos(window, recorded_x, recorded_y);
00162 
00163             m_function = function;
00164             m_data = data;
00165 
00166             handle_motion = g_signal_connect(G_OBJECT(window), "motion_notify_event", G_CALLBACK(motion_delta), this);
00167         }
00168 
00169         void unfreeze_pointer (GtkWindow* window)
00170         {
00171             g_signal_handler_disconnect(G_OBJECT(window), handle_motion);
00172 
00173             m_function = 0;
00174             m_data = 0;
00175 
00176             Sys_SetCursorPos(window, recorded_x, recorded_y);
00177 
00178             gdk_pointer_ungrab(GDK_CURRENT_TIME);
00179         }
00180 };
00181 
00182 #endif

Generated by  doxygen 1.6.2