PageRenderTime 44ms CodeModel.GetById 21ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/platform/unix/gui/apploop.d

http://github.com/wilkie/djehuty
D | 433 lines | 274 code | 114 blank | 45 comment | 52 complexity | dce9d4054f71f9495d0c701219a9953a MD5 | raw file
  1/*
  2 * apploop.d
  3 *
  4 * This is the Gui Application entry point for Linux.
  5 *
  6 * Author: Dave Wilkinson
  7 * Originated: July 25th, 2009
  8 *
  9 */
 10
 11module gui.apploop;
 12
 13import platform.unix.main;
 14
 15import platform.vars.window;
 16import platform.vars.view;
 17
 18import platform.unix.common;
 19
 20import X = binding.x.Xlib;
 21
 22import gui.window;
 23import gui.application;
 24
 25import graphics.view;
 26
 27import core.main;
 28import core.definitions;
 29
 30import io.console;
 31
 32class GuiApplicationController {
 33
 34	// The initial entry for the gui application
 35	this() {
 36		// this code is executed at initialization of the application
 37		auto foo = X.XInitThreads();
 38		_pfvars.running = true;
 39
 40		//ATTEMPT TO USE GTK
 41		//int argc = 0;
 42		//char* argv[] = ("", null);
 43
 44		//char** argv_ptr = &argv;
 45
 46		//use X11
 47		_pfvars.display = X.XOpenDisplay(null);
 48
 49		_pfvars.screen = X.XDefaultScreen(_pfvars.display);
 50		_pfvars.visual = X.XDefaultVisual(_pfvars.display, _pfvars.screen);
 51
 52		//set up click timer
 53		_pfvars.clickTimerevp.sigev_notify = SIGEV_THREAD;
 54		_pfvars.clickTimerevp._sigev_un._sigev_thread._function = &mousetimerproc;
 55
 56		//get Atoms
 57		_pfvars.wm_destroy_window = X.XInternAtom(_pfvars.display, "WM_DELETE_WINDOW\0"c.ptr, X.Bool.True);
 58		_pfvars.private_data = X.XInternAtom(_pfvars.display, "DJEHUTY_PRIVATE_DATA\0"c.ptr, X.Bool.True);
 59		_pfvars.x_settings = X.XInternAtom(_pfvars.display, "_XSETTINGS_SETTINGS\0"c.ptr, X.Bool.False);
 60
 61		//	_pfvars.utf8string = X.XInternAtom(_pfvars.display, "UTF8_STRING\0"c.ptr, X.Bool.True);
 62
 63	}
 64
 65	void start() {
 66		mainloop();
 67	}
 68
 69	void end(uint code) {
 70		_pfvars.running = false;
 71	}
 72
 73private:
 74
 75	void mainloop() {
 76
 77		// for the iterator
 78
 79		Window window_test;
 80		Window window;
 81		Window viewWindow;
 82
 83		WindowPlatformVars* windowVars;
 84
 85		// poll for events
 86		X.XEvent event;
 87
 88		uint i;
 89
 90		GuiApplication app = cast(GuiApplication)Djehuty.app;
 91
 92		X.XLockDisplay(_pfvars.display);
 93		while(_pfvars.running) {
 94
 95			// will block until an event is received
 96
 97			X.XUnlockDisplay(_pfvars.display);
 98			X.XNextEvent(_pfvars.display, &event);
 99			X.XLockDisplay(_pfvars.display);
100
101			// Find which window spawned this event
102
103			window_test = app.firstWindow();
104			window = null;
105
106			if (window_test !is null) {
107				do {
108					windowVars = &window_test._pfvars;
109					if (windowVars.window == event.xany.window) {
110						window = window_test;
111						break;
112					}
113					window_test = window_test.nextWindow();
114				} while (window_test !is app.firstWindow())
115			}
116
117			if (window is null) {
118				if (event.type == X.EventType.CreateNotify) {
119				}
120				if (event.type == X.EventType.ReparentNotify) {
121				}
122				continue;
123			}
124
125			if (windowVars.destroy_called) {
126				// Window is destroyed...
127				// Typically by window manager
128				if (event.type == X.EventType.DestroyNotify) {
129					window.uninitialize();
130				}
131				continue;
132			}
133
134			// Interpret Event
135
136			switch (event.type) {
137
138				// Client Messages
139
140				case X.EventType.ClientMessage:
141
142					if (event.xclient.data.l[0] == _pfvars.wm_destroy_window) {
143						window.remove();
144					}
145					break;
146
147				// Expose
148
149				case X.EventType.Expose:
150					if (event.xexpose.count == 0) {
151						View view = window._view;
152						ViewPlatformVars* viewVars = window._viewVars;
153
154						window.onDraw();
155
156						view.lock();
157
158						X.XCopyArea(_pfvars.display, viewVars.pixmap, windowVars.window,
159								viewVars.gc, 0, 0, window.width, window.height, 0, 0);
160
161						view.unlock();
162					}
163					break;
164
165				case X.EventType.CreateNotify:
166
167					break;
168				
169				case X.EventType.PropertyNotify:
170
171					break;
172
173					// This is for window managers that will reparent your window inside
174					// a decorated frame. This way, we can reposition the window relative
175					// to this frame.
176				case X.EventType.ReparentNotify:
177					windowVars.wm_parent = event.xreparent.event;
178					windowVars.wm_x = event.xreparent.x;
179					windowVars.wm_y = event.xreparent.y;
180
181					// reposition
182					uint w_x;
183					uint w_y;
184
185					w_x = window.x;
186					w_y = window.y;
187
188					if (window.position == WindowPosition.Center) {
189						uint d_width = X.XDisplayWidth(_pfvars.display, _pfvars.screen);
190						uint d_height = X.XDisplayHeight(_pfvars.display, _pfvars.screen);
191
192						w_x = d_width - window.width;
193						w_y = d_height - window.height;
194
195						w_x >>= 1;
196						w_y >>= 1;
197					}
198
199					if (window.position != WindowPosition.Default) {
200						X.XMoveWindow(_pfvars.display, windowVars.wm_parent, w_x, w_y);
201					}
202
203					break;
204
205				case X.EventType.ConfigureNotify:
206
207					// Resize
208					if (window.width != event.xconfigure.width ||
209						window.height != event.xconfigure.height) {
210
211						// Window was resized
212						window._width = event.xconfigure.width;
213						window._height = event.xconfigure.height;
214						window.onResize;
215					}
216					else {
217						// Window was moved
218					}
219					break;
220
221				// Focus
222
223				case X.EventType.FocusIn:
224
225					// Window received focus
226
227					if (event.xfocus.mode == X.NotifyModes.NotifyNormal) {
228						window.onGotFocus();
229					}
230					break;
231
232				case X.EventType.FocusOut:
233
234					// Window loses focus
235
236					if (event.xfocus.mode == X.NotifyModes.NotifyNormal) {
237						window.onLostFocus();
238					}
239					break;
240
241				// Mouse
242
243				case X.EventType.ButtonPress:
244
245					window.mouseProps.x = event.xbutton.x;
246					window.mouseProps.y = event.xbutton.y;
247
248					window.mouseProps.leftDown = 0;
249					window.mouseProps.rightDown = 0;
250					window.mouseProps.middleDown = 0;
251
252					switch (event.xbutton.button) {
253						case X.ButtonName.Button1: // Primary
254							window.mouseProps.leftDown = 1;
255							break;
256						case X.ButtonName.Button2: // Middle
257							window.mouseProps.middleDown = 1;
258							break;
259						case X.ButtonName.Button3: // Secondary
260							window.mouseProps.rightDown = 1;
261							break;
262						case X.ButtonName.Button4: // Other
263							break;
264						case X.ButtonName.Button5: // Other
265							break;
266					}
267
268					if (event.xbutton.state & X.ButtonMask.Button1Mask) {
269						window.mouseProps.leftDown = 1;
270					}
271
272					if (event.xbutton.state & X.ButtonMask.Button2Mask) {
273						window.mouseProps.middleDown = 1;
274					}
275
276					if (event.xbutton.state & X.ButtonMask.Button3Mask) {
277						window.mouseProps.rightDown = 1;
278					}
279
280					switch (event.xbutton.button) {
281						case X.ButtonName.Button1:
282							window.onPrimaryMouseDown();
283							break;
284						case X.ButtonName.Button2:
285							window.onTertiaryMouseDown();
286							break;
287						case X.ButtonName.Button3:
288							window.onSecondaryMouseDown();
289							break;
290						case X.ButtonName.Button4:
291							window.onOtherMouseDown(0);
292							break;
293						case X.ButtonName.Button5:
294							window.onOtherMouseDown(1);
295							break;
296					}
297
298					break;
299
300				case X.EventType.ButtonRelease:
301
302					window.mouseProps.x = event.xbutton.x;
303					window.mouseProps.y = event.xbutton.y;
304
305					window.mouseProps.leftDown = 0;
306					window.mouseProps.rightDown = 0;
307					window.mouseProps.middleDown = 0;
308
309					if (event.xbutton.state & X.ButtonMask.Button1Mask) {
310						window.mouseProps.leftDown = 1;
311					}
312
313					if (event.xbutton.state & X.ButtonMask.Button2Mask) {
314						window.mouseProps.rightDown = 1;
315					}
316
317					if (event.xbutton.state & X.ButtonMask.Button3Mask) {
318						window.mouseProps.middleDown = 1;
319					}
320
321					switch (event.xbutton.button) {
322						case X.ButtonName.Button1:
323							window.mouseProps.leftDown = 0;
324							window.onPrimaryMouseUp();
325							break;
326						case X.ButtonName.Button2:
327							window.mouseProps.middleDown = 0;
328							window.onTertiaryMouseUp();
329							break;
330						case X.ButtonName.Button3:
331							window.mouseProps.rightDown = 0;
332							window.onSecondaryMouseUp();
333							break;
334						case X.ButtonName.Button4:
335							window.onOtherMouseUp(0);
336							break;
337						case X.ButtonName.Button5:
338							window.onOtherMouseUp(1);
339							break;
340					}
341
342					if (_pfvars.clickTimerId) {
343						timer_delete(_pfvars.clickTimerId);
344					}
345
346					_pfvars.clickTimerevp.sigev_value.sival_ptr = &window.mouseProps;
347
348					timer_create(CLOCK_REALTIME, &_pfvars.clickTimerevp,
349						&_pfvars.clickTimerId);
350
351					timer_settime(_pfvars.clickTimerId, 0,
352						&_pfvars.clickTimertime, null);
353
354					window.mouseProps.clicks++;
355					break;
356
357				// Mouse Movement
358
359				case X.EventType.MotionNotify:
360
361					if (event.xmotion.state & X.ButtonMask.Button1Mask) {
362						window.mouseProps.leftDown = 1;
363					}
364
365					if (event.xmotion.state & X.ButtonMask.Button2Mask) {
366						window.mouseProps.rightDown = 1;
367					}
368
369					if (event.xmotion.state & X.ButtonMask.Button3Mask) {
370						window.mouseProps.middleDown = 1;
371					}
372
373					window.mouseProps.x = event.xmotion.x;
374					window.mouseProps.y = event.xmotion.y;
375
376					window.onMouseMove();
377
378					break;
379
380				case X.EventType.EnterNotify:
381
382					// Mouse enters the client area of the window
383					break;
384
385				case X.EventType.LeaveNotify:
386
387					// Mouse leaves the client area of the window
388					window.onMouseLeave();
389					break;
390
391				// Keyboard
392
393				case X.EventType.KeyPress:
394
395					X.KeySym ksym;
396					ksym = X.XLookupKeysym(&event.xkey, 0);
397
398					//interpret the keysymbol...is it a character?
399					//convert to unicode character...
400					int keyCounter;
401					for (keyCounter = 0; keyCounter<_pfvars.numSysKeys; keyCounter++) {
402						if (ksym == _pfvars.sysKey[keyCounter]) {
403							break;
404						}
405					}
406
407					if (keyCounter != _pfvars.numSysKeys) {
408					}
409					else {
410						if (ksym >= 'a' && ksym <= 'z' || ksym == ' ') {
411							window.onKeyChar(cast(char)ksym);
412						}
413					}
414
415					break;
416
417				case X.EventType.KeyRelease:
418
419					X.KeySym ksym2;
420					ksym2 = X.XLookupKeysym(&event.xkey, 0);
421
422					Key key;
423					key.code = ksym2;
424					window.onKeyUp(key);
425					break;
426
427				default:
428					break;
429			}
430		}
431		X.XCloseDisplay(_pfvars.display);
432	}
433}