1 /* 2 Copyright (C) 2001-2006, William Joseph. 3 All Rights Reserved. 4 5 This file is part of GtkRadiant. 6 7 GtkRadiant is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 GtkRadiant is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GtkRadiant; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #if !defined(INCLUDED_GTKUTIL_CURSOR_H) 23 #define INCLUDED_GTKUTIL_CURSOR_H 24 25 #include <glib.h> 26 #include <gdk/gdkevents.h> 27 #include <gtk/gtkwidget.h> 28 #include <gtk/gtkwindow.h> 29 30 #include "debugging/debugging.h" 31 32 typedef struct _GdkCursor GdkCursor; 33 typedef struct _GtkWidget GtkWidget; 34 typedef struct _GtkWindow GtkWindow; 35 36 GdkCursor* create_blank_cursor(); 37 void blank_cursor(GtkWidget* widget); 38 void default_cursor(GtkWidget* widget); 39 void Sys_GetCursorPos(GtkWindow* window, int *x, int *y); 40 void Sys_SetCursorPos(GtkWindow* window, int x, int y); 41 42 43 44 class DeferredMotion 45 { 46 guint m_handler; 47 typedef void(*MotionFunction)(gdouble x, gdouble y, guint state, void* data); 48 MotionFunction m_function; 49 void* m_data; 50 gdouble m_x; 51 gdouble m_y; 52 guint m_state; 53 deferred(DeferredMotion * self)54 static gboolean deferred(DeferredMotion* self) 55 { 56 self->m_handler = 0; 57 self->m_function(self->m_x, self->m_y, self->m_state, self->m_data); 58 return FALSE; 59 } 60 public: DeferredMotion(MotionFunction function,void * data)61 DeferredMotion(MotionFunction function, void* data) : m_handler(0), m_function(function), m_data(data) 62 { 63 } motion(gdouble x,gdouble y,guint state)64 void motion(gdouble x, gdouble y, guint state) 65 { 66 m_x = x; 67 m_y = y; 68 m_state = state; 69 if(m_handler == 0) 70 { 71 m_handler = g_idle_add((GSourceFunc)deferred, this); 72 } 73 } gtk_motion(GtkWidget * widget,GdkEventMotion * event,DeferredMotion * self)74 static gboolean gtk_motion(GtkWidget *widget, GdkEventMotion *event, DeferredMotion* self) 75 { 76 self->motion(event->x, event->y, event->state); 77 return FALSE; 78 } 79 }; 80 81 class DeferredMotionDelta 82 { 83 int m_delta_x; 84 int m_delta_y; 85 guint m_motion_handler; 86 typedef void (*MotionDeltaFunction)(int x, int y, void* data); 87 MotionDeltaFunction m_function; 88 void* m_data; 89 deferred_motion(gpointer data)90 static gboolean deferred_motion(gpointer data) 91 { 92 reinterpret_cast<DeferredMotionDelta*>(data)->m_function( 93 reinterpret_cast<DeferredMotionDelta*>(data)->m_delta_x, 94 reinterpret_cast<DeferredMotionDelta*>(data)->m_delta_y, 95 reinterpret_cast<DeferredMotionDelta*>(data)->m_data 96 ); 97 reinterpret_cast<DeferredMotionDelta*>(data)->m_motion_handler = 0; 98 reinterpret_cast<DeferredMotionDelta*>(data)->m_delta_x = 0; 99 reinterpret_cast<DeferredMotionDelta*>(data)->m_delta_y = 0; 100 return FALSE; 101 } 102 public: DeferredMotionDelta(MotionDeltaFunction function,void * data)103 DeferredMotionDelta(MotionDeltaFunction function, void* data) : m_delta_x(0), m_delta_y(0), m_motion_handler(0), m_function(function), m_data(data) 104 { 105 } flush()106 void flush() 107 { 108 if(m_motion_handler != 0) 109 { 110 g_source_remove(m_motion_handler); 111 deferred_motion(this); 112 } 113 } motion_delta(int x,int y,unsigned int state)114 void motion_delta(int x, int y, unsigned int state) 115 { 116 m_delta_x += x; 117 m_delta_y += y; 118 if(m_motion_handler == 0) 119 { 120 m_motion_handler = g_idle_add(deferred_motion, this); 121 } 122 } 123 }; 124 125 class FreezePointer 126 { 127 unsigned int handle_motion; 128 int recorded_x, recorded_y; 129 typedef void (*MotionDeltaFunction)(int x, int y, unsigned int state, void* data); 130 MotionDeltaFunction m_function; 131 void* m_data; 132 public: FreezePointer()133 FreezePointer() : handle_motion(0), m_function(0), m_data(0) 134 { 135 } motion_delta(GtkWidget * widget,GdkEventMotion * event,FreezePointer * self)136 static gboolean motion_delta(GtkWidget *widget, GdkEventMotion *event, FreezePointer* self) 137 { 138 int current_x, current_y; 139 Sys_GetCursorPos(GTK_WINDOW(widget), ¤t_x, ¤t_y); 140 int dx = current_x - self->recorded_x; 141 int dy = current_y - self->recorded_y; 142 if(dx != 0 || dy != 0) 143 { 144 //globalOutputStream() << "motion x: " << dx << ", y: " << dy << "\n"; 145 Sys_SetCursorPos(GTK_WINDOW(widget), self->recorded_x, self->recorded_y); 146 self->m_function(dx, dy, event->state, self->m_data); 147 } 148 return FALSE; 149 } 150 freeze_pointer(GtkWindow * window,MotionDeltaFunction function,void * data)151 void freeze_pointer(GtkWindow* window, MotionDeltaFunction function, void* data) 152 { 153 ASSERT_MESSAGE(m_function == 0, "can't freeze pointer"); 154 155 const GdkEventMask mask = static_cast<GdkEventMask>(GDK_POINTER_MOTION_MASK 156 | GDK_POINTER_MOTION_HINT_MASK 157 | GDK_BUTTON_MOTION_MASK 158 | GDK_BUTTON1_MOTION_MASK 159 | GDK_BUTTON2_MOTION_MASK 160 | GDK_BUTTON3_MOTION_MASK 161 | GDK_BUTTON_PRESS_MASK 162 | GDK_BUTTON_RELEASE_MASK 163 | GDK_VISIBILITY_NOTIFY_MASK); 164 165 GdkCursor* cursor = create_blank_cursor(); 166 //GdkGrabStatus status = 167 gdk_pointer_grab(GTK_WIDGET(window)->window, TRUE, mask, 0, cursor, GDK_CURRENT_TIME); 168 gdk_cursor_unref(cursor); 169 170 Sys_GetCursorPos(window, &recorded_x, &recorded_y); 171 172 Sys_SetCursorPos(window, recorded_x, recorded_y); 173 174 m_function = function; 175 m_data = data; 176 177 handle_motion = g_signal_connect(G_OBJECT(window), "motion_notify_event", G_CALLBACK(motion_delta), this); 178 } 179 unfreeze_pointer(GtkWindow * window)180 void unfreeze_pointer(GtkWindow* window) 181 { 182 g_signal_handler_disconnect(G_OBJECT(window), handle_motion); 183 184 m_function = 0; 185 m_data = 0; 186 187 Sys_SetCursorPos(window, recorded_x, recorded_y); 188 189 gdk_pointer_ungrab(GDK_CURRENT_TIME); 190 } 191 }; 192 193 #endif 194