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