/platform/unix/gui/apploop.d
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}