root/trunk/luigi/adapters/gld.d

Revision 48, 10.2 kB (checked in by baxissimo, 2 years ago)

Finally fixed it so that the GUI can steal mouse clicks and the user can listen for everything else.

Line 
1 //---------------------------------------------------------------------
2 /*
3   luigi/adapter/gld.d
4      -- GLD input adapter for the 'Luigi' user interface library.
5      GLD is a port of GLFW to D.
6      It can be obtained from http://dsource.org/projects/schooner/
7
8   Copyright (C) 2006 William V. Baxter III
9
10   This software is provided 'as-is', without any express or implied
11   warranty.  In no event will the authors be held liable for any
12   damages arising from the use of this software.
13
14   Permission is granted to anyone to use this software for any
15   purpose, including commercial applications, and to alter it and
16   redistribute it freely, subject to the following restrictions:
17
18   1. The origin of this software must not be misrepresented; you must
19      not claim that you wrote the original software. If you use this
20      software in a product, an acknowledgment in the product
21      documentation would be appreciated but is not required.
22   2. Altered source versions must be plainly marked as such, and must
23      not be misrepresented as being the original software.
24   3. This notice may not be removed or altered from any source distribution.
25
26   William Baxter wbaxter@gmail.com
27 */
28 module luigi.adapters.gld;
29
30 import luigi.base;
31 import luigi.event;
32 import luigi.adapter;
33 private import gld;
34 import luigi.signalobj;
35
36 import std.stdio : writefln;
37
38 int translate_key(int gldkey)
39 {
40     if (gldkey<Key.Special) { return gldkey; }
41     switch(gldkey) {
42     case GLD_KEY_SPACE: return Key.Space;
43     case GLD_KEY_ESC: return Key.Escape;
44     case GLD_KEY_F1: return Key.F1;
45     case GLD_KEY_F2: return Key.F2;
46     case GLD_KEY_F3: return Key.F3;
47     case GLD_KEY_F4: return Key.F4;
48     case GLD_KEY_F5: return Key.F5;
49     case GLD_KEY_F6: return Key.F6;
50     case GLD_KEY_F7: return Key.F7;
51     case GLD_KEY_F8: return Key.F8;
52     case GLD_KEY_F9: return Key.F9;
53     case GLD_KEY_F10: return Key.F10;
54     case GLD_KEY_F11: return Key.F11;
55     case GLD_KEY_F12: return Key.F12;
56     case GLD_KEY_F13: return Key.F13;
57     case GLD_KEY_F14: return Key.F14;
58     case GLD_KEY_F15: return Key.F15;
59     case GLD_KEY_F16: return Key.F16;
60     case GLD_KEY_F17: return Key.F17;
61     case GLD_KEY_F18: return Key.F18;
62     case GLD_KEY_F19: return Key.F19;
63     case GLD_KEY_F20: return Key.F20;
64     case GLD_KEY_F21: return Key.F21;
65     case GLD_KEY_F22: return Key.F22;
66     case GLD_KEY_F23: return Key.F23;
67     case GLD_KEY_F24: return Key.F24;
68     case GLD_KEY_F25: return Key.F25;
69     case GLD_KEY_UP: return Key.Up;
70     case GLD_KEY_DOWN: return Key.Down;
71     case GLD_KEY_LEFT: return Key.Left;
72     case GLD_KEY_RIGHT: return Key.Right;
73     case GLD_KEY_LSHIFT: return Key.LShift;
74     case GLD_KEY_RSHIFT: return Key.RShift;
75     case GLD_KEY_LCTRL: return Key.LCtrl;
76     case GLD_KEY_RCTRL: return Key.        RCtrl;
77     case GLD_KEY_LALT: return Key.LAlt;
78     case GLD_KEY_RALT: return Key.RAlt;
79     case GLD_KEY_TAB: return Key.Tab;
80     case GLD_KEY_ENTER: return Key.Enter;
81     case GLD_KEY_BACKSPACE: return Key.Backspace;
82     case GLD_KEY_INSERT: return Key.Insert;
83     case GLD_KEY_DEL: return Key.Delete;
84     case GLD_KEY_PAGEUP: return Key.PageUp;
85     case GLD_KEY_PAGEDOWN: return Key.PageDown;
86     case GLD_KEY_HOME: return Key.Home;
87     case GLD_KEY_END: return Key.End;
88     case GLD_KEY_KP_0: return Key.KP0;
89     case GLD_KEY_KP_1: return Key.KP1;
90     case GLD_KEY_KP_2: return Key.KP2;
91     case GLD_KEY_KP_3: return Key.KP3;
92     case GLD_KEY_KP_4: return Key.KP4;
93     case GLD_KEY_KP_5: return Key.KP5;
94     case GLD_KEY_KP_6: return Key.KP6;
95     case GLD_KEY_KP_7: return Key.KP7;
96     case GLD_KEY_KP_8: return Key.KP8;
97     case GLD_KEY_KP_9: return Key.KP9;
98     case GLD_KEY_KP_DIVIDE: return Key.KP_Divide;
99     case GLD_KEY_KP_MULTIPLY: return Key.KP_Multiply;
100     case GLD_KEY_KP_SUBTRACT: return Key.KP_Subtract;
101     case GLD_KEY_KP_ADD: return Key.KP_Add;
102     case GLD_KEY_KP_DECIMAL: return Key.KP_Decimal;
103     case GLD_KEY_KP_EQUAL: return Key.KP_Equals;
104     case GLD_KEY_KP_ENTER: return Key.KP_Enter;
105     default:
106         return Key.Unknown;
107     }
108 }
109
110
111 class GLDAdapter : InputAdapter
112 {
113     // Singleton access via static opCall GLDAdapter()
114     static GLDAdapter opCall() {
115         static GLDAdapter myinstance = null;
116         if (!myinstance) {
117             myinstance = new GLDAdapter;
118             myinstance.init();
119         }
120         return myinstance;
121     }
122     // Singleton access via 'inst' property
123     static GLDAdapter inst() {
124         return GLDAdapter();
125     }
126
127     Size get_window_size(WindowHandle win) {
128         // only one window in GLD to query the size of
129         int w,h;
130         gldGetWindowSize(&w, &h);
131         return Size(w,h);
132     }
133
134
135 private:
136     int m_lastWheelPos = 0;
137     static int m_lastKey = Key.Unknown;
138
139     MouseButtons _getButtons() {
140         alias MouseButtons M;
141         MouseButtons m = M.None;
142         if (gldGetMouseButton(GLD_MOUSE_BUTTON_LEFT)) m|=M.Left;
143         if (gldGetMouseButton(GLD_MOUSE_BUTTON_RIGHT)) m|=M.Right;
144         if (gldGetMouseButton(GLD_MOUSE_BUTTON_MIDDLE)) m|=M.Middle;
145         return m;
146     }
147     KeyMods _getMods() {
148         alias KeyMods M;
149         KeyMods m = M.None;
150         if (gldGetKey(GLD_KEY_LCTRL) || gldGetKey(GLD_KEY_RCTRL))   m|= M.Ctrl;
151         if (gldGetKey(GLD_KEY_LSHIFT) || gldGetKey(GLD_KEY_RSHIFT)) m|= M.Shift;
152         if (gldGetKey(GLD_KEY_LALT) || gldGetKey(GLD_KEY_RALT))     m|= M.Alt;
153         return m;
154     }
155
156     // All of our GLD callbacks
157     static void keyCallbackC(int k, int action)
158     {
159         _KeyEvent ev;
160         void _initEvent() {
161             ev.key = translate_key(k);
162             m_lastKey = ev.key;
163             ev.ch = 0;
164             ev.is_press  = (action==GLD_PRESS);
165             ev.mods = inst._getMods();
166             ev.is_key = true;
167             ev.is_char = false;
168         }
169         _initEvent();
170         inst.sig.sysKey.emit(&ev);
171         if (ev.alive) {
172             _initEvent();
173             inst.sig.key.emit(&ev);
174         }
175     }
176     static void charCallbackC(int ch, int action)
177     {
178         _KeyEvent ev;
179         // In practice it seems that char callbacks always come _after_
180         // key callbacks. (That's probably the case for any sane operating system).
181         // Also, you only get one char for one key.  This isn't
182         // necessarily the case in general with fancy input methods
183         // (e.g. european and asian) but it seems to be the case with GLD.
184         // Not every key has a char, but every char has a key in GLD
185         void _initEvent() {
186             ev.key = m_lastKey;
187             ev.ch = ch;
188             ev.is_press  = (action==GLD_PRESS);
189             ev.mods = inst._getMods();
190             ev.is_key = false;
191             ev.is_char = true;
192         }
193         _initEvent();
194         inst.sig.sysKey.emit(&ev);
195         if (ev.alive) {
196             _initEvent();
197             inst.sig.key.emit(&ev);
198         }
199     }
200     static void mouseButtonCallbackC(int button, int action)
201     {
202         _MouseButtonEvent ev;
203         int x,y;
204         gldGetMousePos(&x, &y);
205         void _initEvent() {
206             ev.x = ev.winx = x;
207             ev.y = ev.winy = y;
208             ev.is_press  = (action==GLD_PRESS);
209             ev.mods = inst._getMods();
210             ev.pressed = inst._getButtons();
211             if      (button == GLD_MOUSE_BUTTON_LEFT) ev.button = MouseButtons.Left;
212             else if (button == GLD_MOUSE_BUTTON_RIGHT) ev.button = MouseButtons.Right;
213             else if (button == GLD_MOUSE_BUTTON_MIDDLE) ev.button = MouseButtons.Middle;
214         }       
215         _initEvent();
216         inst.sig.sysMouseButton.emit(&ev);
217         if (ev.alive) {
218             // reinit because GUI might much with it
219             _initEvent();
220             inst.sig.mouseButton.emit(&ev);
221         }
222     }
223     static void mousePosCallbackC(int x, int y)
224     {
225         _MouseMoveEvent ev;
226         ev.x = ev.winx = x;
227         ev.y = ev.winy = y;
228         ev.pressed = inst._getButtons();
229         ev.mods = inst._getMods();
230
231         inst.sig.mouseMove.emit(&ev);
232     }
233     static void mouseWheelCallbackC(int pos)
234     {
235         _MouseWheelEvent ev;
236         int x,y;
237         gldGetMousePos(&x, &y);
238         ev.x = ev.winx = x;
239         ev.y = ev.winy = y;
240         ev.delta = pos - inst.m_lastWheelPos;
241         ev.pressed = inst._getButtons();
242         ev.mods = inst._getMods();
243         inst.m_lastWheelPos = pos;
244
245         inst.sig.mouseWheel.emit(&ev);
246     }
247     static void windowSizeCallbackC(int width, int height)
248     {
249         _WindowSizeEvent ev;
250         ev.w = width;
251         ev.h = height;
252         inst.sig.windowSize.emit(&ev);
253     }
254     static int  windowCloseCallbackC()
255     {
256         _WindowCloseEvent ev;
257         inst.sig.windowClose.emit(&ev);
258         return true;
259     }
260     static void windowRefreshCallbackC()
261     {
262         //WindowRefreshEvent ev;
263     }
264
265     void setCallbacks() {
266         // Note: a window has to be open for these to work!
267         gldSetKeyCallback( &keyCallbackC );
268         gldSetCharCallback( &charCallbackC );
269         gldSetMouseButtonCallback( &mouseButtonCallbackC );
270         gldSetMousePosCallback( &mousePosCallbackC );
271         gldSetMouseWheelCallback( &mouseWheelCallbackC );
272         gldSetWindowSizeCallback( &windowSizeCallbackC );
273         gldSetWindowCloseCallback( &windowCloseCallbackC );
274         gldSetWindowRefreshCallback( &windowRefreshCallbackC );
275     }
276     void clearCallbacks() {
277         gldSetKeyCallback(null);
278         gldSetCharCallback(null);
279         gldSetMouseButtonCallback(null);
280         gldSetMousePosCallback(null);
281         gldSetMouseWheelCallback(null);
282         gldSetWindowSizeCallback(null);
283         gldSetWindowCloseCallback(null);
284         gldSetWindowRefreshCallback(null);
285     }
286
287     // Singleton, so constructor is private
288     this() {
289         initInputAdapter();
290     }
291     void init() {
292         // These can't be in the constructor because they trigger callbacks
293         // and the callbacks want to call inst().
294         // gldInit();
295         setCallbacks();
296     }
297     ~this() {
298         clearCallbacks();
299     }
300
301 public:
302     mixin InputAdapterMix;
303
304 }
305
306
307 alias GLDAdapter DefaultAdapter;
Note: See TracBrowser for help on using the browser.