PageRenderTime 89ms CodeModel.GetById 23ms app.highlight 59ms RepoModel.GetById 1ms app.codeStats 0ms

/platform/win/gui/apploop.d

http://github.com/wilkie/djehuty
D | 1156 lines | 647 code | 313 blank | 196 comment | 96 complexity | 7d22a65c6cdd7ff1182eae896ecaa9f7 MD5 | raw file
   1/*
   2 * apploop.d
   3 *
   4 * This is the Windows GUI apploop.
   5 *
   6 * Author: Dave Wilkinson
   7 * Originated: July 20th, 2009
   8 *
   9 */
  10
  11module gui.apploop;
  12
  13pragma(lib, "comctl32.lib");
  14
  15import binding.win32.windef;
  16import binding.win32.winnt;
  17import binding.win32.winbase;
  18import binding.win32.wingdi;
  19import binding.win32.winuser;
  20import binding.win32.winerror;
  21
  22import Gdiplus = binding.win32.gdiplus;
  23
  24import binding.win32.uxtheme;
  25
  26import platform.win.widget;
  27import platform.win.main;
  28
  29import scaffold.console;
  30
  31import platform.application;
  32
  33import platform.vars.window;
  34import platform.vars.font;
  35import platform.vars.view;
  36
  37import gui.application;
  38import gui.window;
  39
  40import resource.menu;
  41
  42import opengl.window;
  43
  44import graphics.view;
  45import graphics.font;
  46
  47import core.application;
  48import core.definitions;
  49
  50import io.console;
  51
  52class GuiApplicationController {
  53
  54	// The initial entry for the gui application
  55	this() {
  56		// Initialize GDI+
  57		Gdiplus.GdiplusStartupInput gdiplusStartupInput;
  58		Gdiplus.GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, null);
  59	}
  60
  61	void start() {
  62
  63		// Register the class that a window will be created with
  64		registerWindowClass();
  65
  66		// Recognize theme information
  67		loadThemingData();
  68
  69		// Hooks
  70
  71		ubyte* bleh; uint dontcare;
  72
  73		//Hook("USER32.DLL\0"c.ptr, "BeginPaint\0"c.ptr, syscall_BeginPaint, bleh, cast(void*)&HookBeginPaint);
  74		//pBeginPaint = cast(BeginPaintFunc)bleh;
  75		//Hook("USER32.DLL\0"c.ptr, "EndPaint\0"c.ptr, syscall_EndPaint, bleh, cast(void*)&HookEndPaint);
  76		//pEndPaint = cast(EndPaintFunc)bleh;
  77		//Hook("USER32.DLL\0"c.ptr, "IsWindowVisible\0"c.ptr, syscall_IsWindowVisible, bleh, cast(void*)&HookIsWindowVisible);
  78		//pIsWindowVisible = cast(IsWindowVisibleFunc)bleh;
  79
  80		//Hook("USER32.DLL\0"c.ptr, "WindowFromPoint\0"c.ptr, dontcare, bleh, cast(void*)&HookWindowFromPoint);
  81		//Hook("USER32.DLL\0"c.ptr, "GetWindowRect\0"c.ptr, dontcare, bleh, cast(void*)&HookGetWindowRect);
  82		//Hook("USER32.DLL\0"c.ptr, "GetClientRect\0"c.ptr, dontcare, bleh, cast(void*)&HookGetClientRect);
  83
  84		Hook("UXTHEME.DLL\0"c.ptr, "BufferedPaintRenderAnimation\0"c.ptr, dontcare, bleh, cast(void*)&HookBufferedPaintRenderAnimation);
  85		pBufferedPaintRenderAnimation = cast(void*)bleh;
  86		/*Hook("UXTHEME.DLL\0"c.ptr, "BeginBufferedPaint\0"c.ptr, dontcare, bleh, cast(void*)&HookBeginBufferedPaint);
  87		pBeginBufferedPaint = cast(void*)bleh;
  88		Hook("UXTHEME.DLL\0"c.ptr, "EndBufferedAnimation\0"c.ptr, dontcare, bleh, cast(void*)&HookEndBufferedAnimation);
  89		pEndBufferedAnimation = cast(void*)bleh;
  90		Hook("UXTHEME.DLL\0"c.ptr, "BeginBufferedAnimation\0"c.ptr, dontcare, bleh, cast(void*)&HookBeginBufferedAnimation);
  91		pBeginBufferedAnimation = cast(void*)bleh;*/
  92
  93		mainloop();
  94	}
  95
  96	void end(uint code) {
  97		Gdiplus.GdiplusShutdown(gdiplusToken);
  98
  99		_appEnd = true;
 100
 101		ApplicationController.instance.exitCode = code;
 102	}
 103
 104private:
 105
 106	// GDI+ Instance
 107	ULONG_PTR gdiplusToken;
 108
 109	bool _appEnd = false;
 110
 111	const int WM_MOUSECAPTURE = 0xffff;
 112
 113	const wchar[] djehutyClassName = "djehutyApp\0"w;
 114
 115	void registerWindowClass() {
 116		WNDCLASSW wc;
 117		wc.lpszClassName = djehutyClassName.ptr;
 118		wc.style = CS_PARENTDC;//CS_OWNDC;//| CS_HREDRAW | CS_VREDRAW;
 119		wc.lpfnWndProc = &DefaultProc;
 120		wc.hInstance = null;
 121		wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
 122		wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
 123		wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
 124		wc.lpszMenuName = null;
 125		wc.cbClsExtra = wc.cbWndExtra = 0;
 126		auto a = RegisterClassW(&wc);
 127		assert(a);
 128	}
 129
 130	void mainloop() {
 131
 132		// HOW AWFUL IS THIS: ?!
 133
 134		while(!_appEnd) {
 135			Sleep(1);
 136		}
 137
 138		// THIS CODE PRINTS TO THE CONSOLE WINDOW USING GDI
 139
 140		/*HWND hwndConsole = GetConsoleWindow();
 141		HDC dc = GetDC(hwndConsole);
 142
 143		CONSOLE_FONT_INFO cfi ;
 144		COORD fsize ;
 145		HANDLE hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
 146
 147		GetCurrentConsoleFont(hConsoleOut, FALSE, &cfi);
 148
 149		Font fnt = new Font("Terminal", 10, 400, false, false, false);
 150		FontPlatformVars* fvars = FontGetPlatformVars(fnt);
 151
 152		SetBkMode(dc, OPAQUE);
 153		SetBkColor(dc, 0x339933);
 154		SetTextColor(dc, 0xf800f8);
 155
 156		SelectObject(dc, fvars.fontHandle);
 157*/
 158		ConsoleUninit();
 159
 160		ApplicationController.instance.end;
 161	}
 162
 163static:
 164
 165	int win_osVersion = -1;
 166
 167	alias extern(C) HDC function(HWND, LPPAINTSTRUCT) BeginPaintFunc;
 168	BeginPaintFunc pBeginPaint;
 169	uint syscall_BeginPaint;
 170	
 171	alias extern(C) BOOL function(HWND, LPPAINTSTRUCT) EndPaintFunc;
 172	EndPaintFunc pEndPaint;
 173	uint syscall_EndPaint;
 174	
 175	alias extern(C) BOOL function(HWND) IsWindowVisibleFunc;
 176	IsWindowVisibleFunc pIsWindowVisible;
 177	uint syscall_IsWindowVisible;
 178
 179	void* pBufferedPaintRenderAnimation;
 180	void* pBeginBufferedPaint;
 181	void* pEndBufferedAnimation;
 182	void* pBeginBufferedAnimation;
 183
 184	bool Hook(char* mod, char* proc, ref uint syscall_id, ref ubyte* pProc, void* pNewProc) {
 185	    HINSTANCE hMod = GetModuleHandleA(mod);
 186
 187	    if (hMod is null) {
 188			hMod = LoadLibraryA(mod);
 189			Console.putln("not loaded");
 190		    if (hMod is null) {
 191				Console.putln("bad");
 192				return false;
 193			}
 194		}
 195
 196	    pProc = cast(ubyte*)GetProcAddress(hMod, proc);
 197
 198	    if (pProc is null) {
 199			Console.putln("procnotfound");
 200			return false;
 201	    }
 202
 203	    ubyte[5] oldCode;
 204	    oldCode[0..5] = pProc[0..5];
 205
 206	    if ( true || pProc[0] == 0xB8 ) {
 207	        syscall_id = *cast(uint*)(pProc + 1);
 208
 209	        DWORD flOldProtect;
 210
 211	        VirtualProtect(pProc, 5, PAGE_EXECUTE_READWRITE, & flOldProtect);
 212
 213	        pProc[0] = 0xE9;
 214	        *cast(uint*)(pProc+1) = cast(uint)pNewProc - cast(uint)(pProc+5);
 215
 216	        pProc += 5;
 217
 218	        VirtualProtect(pProc, 5, flOldProtect, & flOldProtect);
 219
 220	        return true;
 221	    }
 222	    else {
 223	        return false;
 224		}
 225	}
 226
 227	extern(C) HDC HookBeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint) {
 228
 229		HDC ret;
 230
 231		// normal operations:
 232
 233		// abnormal operations:
 234/*		if (hWnd != button_hWnd) {
 235			asm {
 236		        mov     EAX, syscall_BeginPaint;
 237		        push    lpPaint;
 238		        push    hWnd;
 239				call    pBeginPaint;
 240		        mov		ret, EAX;
 241			}
 242			return ret;
 243		}*/
 244
 245		lpPaint.fErase = 0;
 246		
 247		lpPaint.rcPaint.left = 0;
 248//		lpPaint.rcPaint.right = button_width;
 249		lpPaint.rcPaint.top = 0;
 250	//	lpPaint.rcPaint.bottom = button_height;
 251
 252		lpPaint.fIncUpdate = 0;
 253		lpPaint.fRestore = 0;
 254
 255//		lpPaint.hdc = button_hdc;
 256
 257		return null; //button_hdc;
 258	}
 259	
 260	extern(C) BOOL HookIsWindowVisible() {	
 261		asm {
 262			naked;
 263			mov EAX, 1;
 264			ret 4;
 265		}	
 266	}
 267	
 268	extern(C) BOOL HookWindowFromPoint(POINT pnt) {
 269		asm {
 270			naked;
 271//			mov EAX, button_hWnd;
 272			ret 8;
 273		}
 274	}
 275	
 276	extern(C) BOOL HookGetWindowRect(HWND hWnd, RECT* rt) {
 277		Console.putln("GetWindowRect ", hWnd);
 278		if (rt !is null) {
 279//			rt.left = button_x;
 280//			rt.right = button_x + button_width;
 281			rt.top = 299;
 282	//		rt.bottom = 299 + button_height;
 283		}
 284		
 285		asm {
 286			mov EAX, 1;
 287		}
 288		
 289		return 1;
 290	}
 291	
 292	extern(C) BOOL HookGetClientRect(HWND hWnd, RECT* rt) {
 293		asm {
 294			naked;
 295			mov EAX, 1;
 296			ret 8;
 297		}
 298	}
 299
 300	void HookBeginPaintImpl() {
 301		asm {
 302			mov EAX, syscall_BeginPaint;
 303			call pBeginPaint;
 304			ret;
 305		}
 306	}
 307
 308	template UXThemePrologue() {
 309		const char[] UXThemePrologue =
 310		`
 311			asm {
 312				naked;
 313
 314				mov		EDI,EDI;
 315				push	EBP;
 316				mov		EBP,ESP;
 317			}
 318			`;
 319	}
 320
 321	extern(C) void HookBeginBufferedPaint() {
 322
 323		mixin(UXThemePrologue!());
 324		//Console.putln("BeginBufferedPaint");
 325
 326		asm {
 327	        jmp		pBeginBufferedPaint;
 328		}
 329
 330		return;
 331	}
 332
 333	extern(C) void HookBeginBufferedAnimation() {
 334
 335		mixin(UXThemePrologue!());
 336
 337		//Console.putln("BeginBufferedAnimation");
 338		asm {
 339			//mov EAX, button_hdc;
 340			//mov [EBP+12], EAX;
 341		}
 342
 343		asm {
 344	        jmp		pBeginBufferedAnimation;
 345		}
 346
 347		return;
 348	}
 349
 350	extern(C) void HookEndBufferedAnimation() {
 351
 352		mixin(UXThemePrologue!());
 353
 354		//Console.putln("EndBufferedAnimation");
 355
 356		asm {
 357	        jmp		pEndBufferedAnimation;
 358		}
 359
 360		return;
 361	}
 362
 363	extern(C) void HookBufferedPaintRenderAnimation(HWND hWnd, HDC hdcTarget) {
 364
 365		mixin(UXThemePrologue!());
 366
 367		void* ctrl_in = cast(void*)GetWindowLongW(hWnd, GWLP_USERDATA);
 368
 369		if (ctrl_in !is null) {
 370			WinWidget _ctrlvars = cast(WinWidget)ctrl_in;
 371			hdcTarget = GetBaseDC(_ctrlvars);
 372		}
 373
 374	//	asm {
 375	//			mov EAX, button_hdc;
 376	//			mov [EBP+12], EAX;
 377	//	}
 378
 379		asm {
 380	        jmp		pBufferedPaintRenderAnimation;
 381		}
 382
 383		return;
 384	}
 385
 386	extern(C) BOOL HookEndPaint(HWND hWnd, LPPAINTSTRUCT lpPaint) {
 387		// abnormal operations:
 388//		if (hWnd == button_hWnd) {
 389			//Console.putln("End Paint");
 390	//		return true;
 391	//	}
 392
 393		// normal operations:
 394		asm {
 395	        mov     EAX, syscall_EndPaint;
 396	        push    lpPaint;
 397	        push    hWnd;
 398	        call    pEndPaint;
 399		}
 400	}
 401
 402	extern(Windows)
 403	int DefaultProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
 404	//			Console.putln("def proc");
 405		CREATESTRUCTW* cs = cast(CREATESTRUCTW*)lParam;
 406
 407		if (uMsg == WM_CREATE) {
 408			Window w = cast(Window)cs.lpCreateParams;
 409
 410			SetWindowLongW(hWnd, GWLP_WNDPROC, cast(LONG)&WindowProc);
 411			SetWindowLongW(hWnd, GWLP_USERDATA, cast(LONG)cs.lpCreateParams);
 412
 413			return 0;
 414		}
 415		else if (uMsg == WM_UNICHAR) {
 416			return 1;
 417		}
 418
 419		return DefWindowProcW(hWnd, uMsg, wParam, lParam);
 420	}
 421
 422	extern(Windows)
 423	int CtrlProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
 424	//			Console.putln("ctrl proc");
 425		void* ctrl_in = cast(void*)GetWindowLongW(hWnd, GWLP_USERDATA);
 426
 427		if (ctrl_in !is null) {
 428			WinWidget _ctrlvars = cast(WinWidget)ctrl_in;
 429
 430			return CallAppLoopMessage(_ctrlvars, uMsg, wParam, lParam);
 431		}
 432
 433		return 0;
 434	}
 435
 436	void _TestNumberOfClicks(ref Window w, ref WindowPlatformVars* windowVars, int x, int y, int clickType) {
 437		//check for double click first and within close proximity
 438		//of the last click
 439
 440		if (windowVars.doubleClickTimerSet != 0) {
 441			KillTimer(windowVars.hWnd, 1);
 442		}
 443
 444		// checks whether within tolerance region
 445		if ( (windowVars.doubleClickTimerSet == clickType) &&
 446			(x <= windowVars.doubleClickX + 1) &&
 447			(x >= windowVars.doubleClickX - 1) &&
 448			(y <= windowVars.doubleClickY + 1) &&
 449			(y >= windowVars.doubleClickY - 1) ) {
 450
 451			// disable timer, inside tolerance
 452			windowVars.doubleClickAmount++;
 453
 454			KillTimer(windowVars.hWnd, 1);
 455		}
 456		else {
 457			//reset timer stats, start over with one click
 458			windowVars.doubleClickTimerSet = clickType;
 459			windowVars.doubleClickAmount = 1;
 460		}
 461
 462		//set up double click tolerance region
 463		windowVars.doubleClickX = x;
 464		windowVars.doubleClickY = y;
 465
 466		SetTimer(windowVars.hWnd, 1, GetDoubleClickTime(), null);
 467
 468		w.mouseProps.clicks = windowVars.doubleClickAmount;
 469	}
 470
 471	void _TestNumberOfClicksUp(ref Window w, ref WindowPlatformVars* windowVars, int clickType) {
 472
 473		if (windowVars.doubleClickTimerSet == clickType) {
 474			//double click may have occured
 475			w.mouseProps.clicks = windowVars.doubleClickAmount;
 476		}
 477		else {
 478			w.mouseProps.clicks = 1;
 479		}
 480	}
 481
 482	bool win_hasVisualStyles = false;
 483	HFONT win_button_font;
 484
 485	HMODULE win_uxThemeMod;
 486
 487	// Theming Libraries
 488	extern (Windows) alias HTHEME (*OpenThemeDataFunc)(HWND, LPCWSTR);
 489	extern (Windows) alias HRESULT (*GetThemeSysFontFunc)(HTHEME, int, LOGFONTW*);
 490	extern (Windows) alias HRESULT (*CloseThemeDataFunc)(HTHEME);
 491
 492	OpenThemeDataFunc OpenThemeDataDLL;
 493	GetThemeSysFontFunc GetThemeSysFontDLL;
 494	CloseThemeDataFunc CloseThemeDataDLL;
 495
 496	void loadThemingData() {
 497		const int TMT_MSGBOXFONT = 805;
 498
 499		// Do we have visual styles?
 500		// Load the theming library: uxTheme, if applicable
 501
 502		if (win_osVersion >= OsVersionWindowsXp) {
 503			//using visual styles
 504			//look up uxTheme.dll
 505
 506			win_uxThemeMod = LoadLibraryW("UxTheme.DLL");
 507
 508			if (win_uxThemeMod == null) {
 509				//does not exist...
 510				win_hasVisualStyles = false;
 511			}
 512			else {
 513				//get proc addresses of important functions
 514				OpenThemeDataDLL = cast(OpenThemeDataFunc)GetProcAddress(win_uxThemeMod, "OpenThemeData");
 515				CloseThemeDataDLL = cast(CloseThemeDataFunc)GetProcAddress(win_uxThemeMod, "CloseThemeData");
 516				GetThemeSysFontDLL = cast(GetThemeSysFontFunc)GetProcAddress(win_uxThemeMod, "GetThemeSysFont");
 517
 518				//apply visual styles if the application is allowed
 519				win_hasVisualStyles = true;
 520			}
 521		}
 522		else {
 523			//no visual styles
 524			win_uxThemeMod = null;
 525
 526			win_hasVisualStyles = false;
 527		}
 528
 529		HDC dcz = GetDC(null);
 530
 531		if (win_hasVisualStyles) {
 532			HTHEME hTheme;
 533			hTheme = OpenThemeDataDLL(null, "WINDOW");
 534
 535			LOGFONTW lfnt = { 0 };
 536
 537			HRESULT hr = GetThemeSysFontDLL(hTheme, TMT_MSGBOXFONT, &lfnt);
 538
 539			if (hr != S_OK) {
 540				win_button_font = CreateFontW(-MulDiv(8, GetDeviceCaps(dcz, 90), 72), 0, 0, 0, 400, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH, "Microsoft Sans Serif");
 541			}
 542			else {
 543				win_button_font = CreateFontIndirectW(&lfnt);
 544			}
 545
 546			CloseThemeDataDLL(hTheme);
 547		}
 548		else {
 549			win_button_font = CreateFontW(-MulDiv(8, GetDeviceCaps(dcz, 90), 72),0,0,0, 400, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, DEFAULT_PITCH, "MS Sans Serif");
 550		}
 551
 552		ReleaseDC(null, dcz);
 553	}
 554
 555	extern(Windows)
 556	static int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam) {
 557
 558		// resolve the window class reference:
 559		void* wind_in = cast(void*)GetWindowLongW(hWnd, GWLP_USERDATA);
 560		Window w = cast(Window)(wind_in);
 561
 562		WindowPlatformVars* windowVars = &w._pfvars;
 563
 564		Window viewW;
 565
 566		int ret = IsWindowUnicode(windowVars.hWnd);
 567
 568		if (true) {
 569			viewW = cast(Window)w;
 570		}
 571		else {
 572			viewW = null;
 573		}
 574
 575		switch (uMsg) {
 576
 577			// FOR CONTROLS AND MENUS //
 578
 579			case WM_VSCROLL:
 580			case WM_HSCROLL:
 581			case WM_COMMAND:
 582
 583				if (lParam == 0) {
 584					// menu
 585
 586					Menu mnuNow = cast(Menu)cast(void*)wParam;
 587
 588					if (viewW !is null) {
 589						viewW.onMenu(mnuNow);
 590					}
 591				}
 592				else {
 593					// native control
 594
 595					wind_in = cast(void*)GetWindowLongW(cast(HWND)lParam, GWLP_USERDATA);
 596
 597					WinWidget ctrl = cast(WinWidget)wind_in;
 598
 599					wParam &= 0xFFFF;
 600
 601	//				ctrl._AppLoopMessage(uMsg, wParam, lParam);
 602					return CallAppLoopMessage(ctrl, uMsg, wParam, lParam);
 603				}
 604
 605				break;
 606
 607			case WM_CTLCOLORDLG:
 608			case WM_CTLCOLORBTN:
 609			case WM_CTLCOLORSTATIC:
 610
 611			/*	Console.putln("ctrl back");
 612
 613				wind_in = cast(void*)GetWindowLongW(cast(HWND)lParam, GWLP_USERDATA);
 614
 615				WinWidget ctrl = cast(WinWidget)wind_in;
 616
 617				// SET FOREGROUND AND BACKGROUND COLORS FOR CONTROLS HERE:
 618				// TO SUPPORT BACKGROUND AND FOREGROUND CHANGES
 619
 620		        SetBkMode(cast(HDC)wParam, TRANSPARENT);
 621
 622				// Lock Display
 623
 624				int x, y, width, height;
 625
 626				View ctrl_view = CallReturnView(ctrl,x,y,width,height); //ctrl._ReturnView(x, y, width, height);
 627
 628				if (!indraw) {
 629					ctrl_view.lockDisplay();
 630				}
 631
 632				ViewPlatformVars* viewVars = ViewGetPlatformVars(ctrl_view);
 633
 634				BitBlt(
 635					cast(HDC)wParam,
 636					0, 0,
 637					width, height,
 638					viewVars.dc,
 639					x, y,
 640					SRCCOPY);
 641
 642				if (!indraw) {
 643					ctrl_view.unlockDisplay();
 644				}*/
 645
 646		        return cast(LRESULT)GetStockObject(NULL_BRUSH);
 647
 648			case WM_DRAWITEM:
 649				DRAWITEMSTRUCT* pDIS = cast(DRAWITEMSTRUCT*)lParam;
 650
 651				View view = w._view;
 652				ViewPlatformVars* viewVars = w._viewVars;
 653				
 654				RECT rt;
 655				GetClientRect(pDIS.hwndItem, &rt);
 656				BitBlt(pDIS.hDC, 0, 0, w.width, w.height, viewVars.dc, 0, 0, SRCCOPY);
 657				//Rectangle(pDIS.hDC, 0, 0, rt.right, rt.bottom);
 658				break;
 659				
 660			case WM_ERASEBKGND:
 661
 662				break;
 663
 664			case WM_PAINT:
 665
 666				View view = w._view;
 667				ViewPlatformVars* viewVars = w._viewVars;
 668
 669				viewW.onDraw();
 670
 671				view.lock();
 672				PAINTSTRUCT ps;
 673				HDC dc = BeginPaint(hWnd, &ps);
 674
 675				BitBlt(ps.hdc, 0, 0, w.width, w.height, viewVars.dc, 0, 0, SRCCOPY);
 676
 677				EndPaint(hWnd, &ps);
 678
 679				view.unlock();
 680
 681				break;
 682
 683		    case WM_DESTROY:
 684
 685				w.uninitialize();
 686				break;
 687
 688		/* FOCUS */
 689
 690			case WM_ACTIVATE:
 691				int x, y;
 692				//activation type
 693				x = wParam & 0xffff;
 694				//minimization status
 695				y = (wParam >> 16) & 0xffff;
 696
 697				if (x == WA_INACTIVE) {
 698					//losing focus
 699					w.onLostFocus();
 700				}
 701				else if (x == WA_ACTIVE || x == WA_CLICKACTIVE) {
 702					//gaining focus
 703					w.onGotFocus();
 704				}
 705
 706				if (y != 0) {
 707					//minimized
 708				}
 709				break;
 710
 711			case WM_INPUT:
 712				break;
 713
 714			case WM_CAPTURECHANGED:
 715				break;
 716
 717			case WM_LBUTTONDOWN:
 718
 719				SetFocus(hWnd);
 720				SetCapture(hWnd);
 721
 722				//uint lp = GetMessageExtraInfo();
 723				//if ((lp & SIGNATURE_MASK) == MI_WP_SIGNATURE) {
 724					//writefln("pen");
 725				//}
 726
 727				//writefln("down : ", lp, " ... ", lp & SIGNATURE_MASK, " == ", MI_WP_SIGNATURE);
 728
 729				// FILL THE MOUSEPROPERTIES STRUCTURE FOR THE WINDOW
 730
 731				//w.mouseProps.rightDown = 1;
 732
 733				//check bounds for the controls
 734
 735				int x, y;
 736				x = lParam & 0xffff;
 737				w.mouseProps.x = x;
 738				y = (lParam >> 16) & 0xffff;
 739				w.mouseProps.y = y;
 740
 741				w.mouseProps.leftDown = true;
 742				w.mouseProps.rightDown = ((wParam & MK_RBUTTON) > 0);
 743				w.mouseProps.middleDown = ((wParam & MK_MBUTTON) > 0);
 744
 745				_TestNumberOfClicks(w,windowVars,x,y,1);
 746
 747				w.onPrimaryMouseDown();
 748				break;
 749
 750			case WM_LBUTTONUP:
 751
 752				ReleaseCapture();
 753
 754				//window.mouseProps.rightDown = 0;
 755
 756				//check for double click first
 757				_TestNumberOfClicksUp(w,windowVars,1);
 758
 759				//fill _mouseProps
 760				int x, y;
 761				x = lParam & 0xffff;
 762				w.mouseProps.x = x;
 763				y = (lParam >> 16) & 0xffff;
 764				w.mouseProps.y = y;
 765
 766				w.mouseProps.leftDown = false;
 767				w.mouseProps.rightDown = ((wParam & MK_RBUTTON) > 0);
 768				w.mouseProps.middleDown = ((wParam & MK_MBUTTON) > 0);
 769
 770				w.onPrimaryMouseUp();
 771				break;
 772
 773			case WM_RBUTTONDOWN:
 774
 775				SetFocus(hWnd);
 776				SetCapture(hWnd);
 777
 778				// FILL THE MOUSEPROPERTIES STRUCTURE FOR THE WINDOW
 779
 780				//w.mouseProps.rightDown = 1;
 781
 782				//check bounds for the controls
 783
 784				int x, y;
 785				x = lParam & 0xffff;
 786				w.mouseProps.x = x;
 787				y = (lParam >> 16) & 0xffff;
 788				w.mouseProps.y = y;
 789
 790				w.mouseProps.leftDown = ((wParam & MK_LBUTTON) > 0);
 791				w.mouseProps.rightDown = true;
 792				w.mouseProps.middleDown = ((wParam & MK_MBUTTON) > 0);
 793
 794				_TestNumberOfClicks(w,windowVars,x,y,2);
 795
 796				w.onSecondaryMouseDown();
 797				break;
 798
 799			case WM_RBUTTONUP:
 800
 801				ReleaseCapture();
 802				//window.mouseProps.rightDown = 0;
 803
 804				//check for double click first
 805				_TestNumberOfClicksUp(w,windowVars,2);
 806
 807				//fill _mouseProps
 808				int x, y;
 809				x = lParam & 0xffff;
 810				w.mouseProps.x = x;
 811				y = (lParam >> 16) & 0xffff;
 812				w.mouseProps.y = y;
 813
 814				w.mouseProps.leftDown = ((wParam & MK_LBUTTON) > 0);
 815				w.mouseProps.rightDown = false;
 816				w.mouseProps.middleDown = ((wParam & MK_MBUTTON) > 0);
 817
 818				w.onSecondaryMouseUp();
 819				break;
 820
 821			case WM_MBUTTONDOWN:
 822
 823				SetFocus(hWnd);
 824				SetCapture(hWnd);
 825
 826				// FILL THE MOUSEPROPERTIES STRUCTURE FOR THE WINDOW
 827
 828				//w.mouseProps.rightDown = 1;
 829
 830				//check bounds for the controls
 831
 832				int x, y;
 833				x = lParam & 0xffff;
 834				w.mouseProps.x = x;
 835				y = (lParam >> 16) & 0xffff;
 836				w.mouseProps.y = y;
 837
 838				w.mouseProps.leftDown = ((wParam & MK_LBUTTON) > 0);
 839				w.mouseProps.rightDown = ((wParam & MK_RBUTTON) > 0);
 840				w.mouseProps.middleDown = true;
 841
 842				_TestNumberOfClicks(w,windowVars,x,y,3);
 843
 844				w.onTertiaryMouseDown();
 845				break;
 846
 847			case WM_MBUTTONUP:
 848
 849				ReleaseCapture();
 850				//window.mouseProps.rightDown = 0;
 851
 852				//check for double click first
 853				_TestNumberOfClicksUp(w,windowVars,3);
 854
 855				//fill _mouseProps
 856				int x, y;
 857				x = lParam & 0xffff;
 858				w.mouseProps.x = x;
 859				y = (lParam >> 16) & 0xffff;
 860				w.mouseProps.y = y;
 861
 862				w.mouseProps.leftDown = ((wParam & MK_LBUTTON) > 0);
 863				w.mouseProps.rightDown = ((wParam & MK_RBUTTON) > 0);
 864				w.mouseProps.middleDown = false;
 865
 866				w.onTertiaryMouseUp();
 867				break;
 868
 869			case WM_XBUTTONDOWN:
 870
 871				SetFocus(hWnd);
 872				SetCapture(hWnd);
 873
 874				// FILL THE MOUSEPROPERTIES STRUCTURE FOR THE WINDOW
 875
 876				//w.mouseProps.rightDown = 1;
 877
 878				//check bounds for the controls
 879
 880				int x, y;
 881				x = lParam & 0xffff;
 882				w.mouseProps.x = x;
 883				y = (lParam >> 16) & 0xffff;
 884				w.mouseProps.y = y;
 885
 886				wParam >>= 16;
 887				if (wParam) {
 888					wParam--;
 889
 890					_TestNumberOfClicks(w,windowVars,x,y,4 + cast(uint)wParam);
 891
 892					w.onOtherMouseDown(cast(uint)wParam);
 893				}
 894				break;
 895
 896			case WM_XBUTTONUP:
 897
 898				ReleaseCapture();
 899				//window.mouseProps.rightDown = 0;
 900
 901				//fill _mouseProps
 902				int x, y;
 903				x = lParam & 0xffff;
 904				w.mouseProps.x = x;
 905				y = (lParam >> 16) & 0xffff;
 906				w.mouseProps.y = y;
 907
 908				wParam >>= 16;
 909				if (wParam) {
 910					wParam--;
 911
 912					//check for double click
 913					_TestNumberOfClicksUp(w,windowVars,4 + cast(uint)wParam);
 914
 915					w.onOtherMouseUp(cast(uint)wParam);
 916				}
 917				break;
 918
 919			case WM_MOUSEHWHEEL:
 920
 921				w.onMouseWheelX(0);
 922				break;
 923
 924			case WM_MOUSEWHEEL:
 925	
 926				w.onMouseWheelY(0);
 927				break;
 928
 929			case WM_MOUSEMOVE:
 930
 931				int x, y;
 932				x = lParam & 0xffff;
 933				w.mouseProps.x = x;
 934				y = (lParam >> 16) & 0xffff;
 935				w.mouseProps.y = y;
 936			//	Console.putln("mouse move window! x:", x, "y:", y);
 937
 938				w.mouseProps.leftDown = ((wParam & MK_LBUTTON) > 0);
 939				w.mouseProps.rightDown = ((wParam & MK_RBUTTON) > 0);
 940				w.mouseProps.middleDown = ((wParam & MK_MBUTTON) > 0);
 941
 942				if (windowVars.hoverTimerSet==0) {
 943					SetTimer(hWnd, 0, 55, null);
 944					windowVars.hoverTimerSet = 1;
 945				}
 946
 947				w.onMouseMove();
 948				break;
 949
 950				// Internal Timing Functions
 951			case WM_MOUSELEAVE:
 952				w.onMouseLeave();
 953				break;
 954
 955			case WM_MOUSECAPTURE: //made up event
 956				if (windowVars.hoverTimerSet == 1) {
 957					KillTimer(hWnd, 0);
 958					windowVars.hoverTimerSet = 0;
 959				}
 960
 961				SetCapture(hWnd);
 962				break;
 963
 964			case WM_MOVE:
 965
 966				RECT rt;
 967				GetWindowRect(hWnd, &rt);
 968
 969				if (!windowVars.supress_WM_MOVE) {
 970					w._x = rt.left;
 971					w._y = rt.top;
 972
 973					w.onMove();
 974					windowVars.supress_WM_MOVE = false;
 975				}
 976				break;
 977
 978			case WM_KEYDOWN:
 979
 980				Key key;
 981				key.code = cast(uint)wParam;
 982				w.onKeyDown(key);
 983
 984				break;
 985
 986				//might have to translate these keys
 987
 988			case WM_CHAR:
 989
 990				if ((wParam == Key.Backspace)
 991					|| (wParam == Key.Return)
 992					|| (wParam == Key.Tab)) {
 993					break;
 994				}
 995
 996				ushort stuff[2] = (cast(ushort*)&wParam)[0 .. 2];
 997
 998				//printf("%x %x", stuff[0], stuff[1]);
 999
1000				w.onKeyChar(cast(dchar)wParam);
1001
1002				break;
1003
1004			case WM_DEADCHAR:
1005
1006				ushort stuff[2] = (cast(ushort*)&wParam)[0 .. 2];
1007
1008				//printf("%x %x", stuff[0], stuff[1]);
1009
1010				break;
1011
1012			case WM_UNICHAR:
1013
1014				if (wParam == 0xFFFF) {
1015					return 1;
1016				}
1017
1018				ushort stuff[2] = (cast(ushort*)&wParam)[0 .. 2];
1019
1020				//printf("%x %x", stuff[0], stuff[1]);
1021
1022				w.onKeyChar(cast(dchar)wParam);
1023
1024				break;
1025
1026			case WM_KEYUP:
1027
1028				Key key;
1029				key.code = cast(uint)wParam;
1030				w.onKeyUp(key);
1031
1032				break;
1033
1034			case WM_SIZE:
1035
1036				RECT rt;
1037				GetClientRect(hWnd, &rt);
1038
1039				if (!windowVars.supress_WM_SIZE) {
1040					w._width = rt.right;
1041					w._height = rt.bottom;
1042
1043					w.onResize();
1044
1045					if (cast(GLWindow)w !is null) {
1046						windowVars.gameLoopCallResize();
1047					}
1048
1049					windowVars.supress_WM_SIZE = false;
1050				}
1051
1052				// was it minimized? maximized?
1053
1054				if (w.state != WindowState.Fullscreen) {
1055					if (wParam == SIZE_MAXIMIZED && w.state != WindowState.Minimized) {
1056						if (!windowVars.supress_WM_SIZE_state) {
1057							w.state = WindowState.Maximized;
1058							w.onStateChange();
1059							windowVars.supress_WM_SIZE_state = false;
1060						}
1061					}
1062					else if (wParam == SIZE_MINIMIZED && w.state != WindowState.Maximized) {
1063						if (!windowVars.supress_WM_SIZE_state) {
1064							w.state = WindowState.Minimized;
1065							w.onStateChange();
1066							windowVars.supress_WM_SIZE_state = false;
1067						}
1068					}
1069					else if (wParam == SIZE_RESTORED && w.state != WindowState.Normal) {
1070						if (!windowVars.supress_WM_SIZE_state) {
1071							w.state = WindowState.Normal;
1072							w.onStateChange();
1073							windowVars.supress_WM_SIZE_state = false;
1074						}
1075					}
1076				}
1077	
1078				break;
1079	
1080			case WM_TIMER:
1081	
1082				if (wParam == 0) {
1083					//Internal Timer (mouse hover)
1084
1085					POINT pt;
1086
1087					GetCursorPos(&pt);
1088
1089					if (WindowFromPoint(pt) != hWnd) {
1090						KillTimer(hWnd, 0);
1091						windowVars.hoverTimerSet = 0;
1092
1093						SendMessageW(hWnd, WM_MOUSELEAVE, 0,0);
1094					}
1095					else {
1096						POINT pnt[2];
1097	
1098						pnt[0].x = 0;
1099						pnt[0].y = 0;
1100						pnt[1].x = w.width-1;
1101						pnt[1].y = w.height-1;
1102
1103						ClientToScreen(hWnd, &pnt[0]);
1104						ClientToScreen(hWnd, &pnt[1]);
1105	
1106						if (pt.x < pnt[0].x || pt.y < pnt[0].y || pt.x > pnt[1].x || pt.y > pnt[1].y) {
1107							KillTimer(hWnd,0);
1108	
1109							windowVars.hoverTimerSet = 0;
1110	
1111							SendMessageW(hWnd, WM_MOUSELEAVE, 0, 0);
1112						}
1113					}
1114					//KillTimer(hWnd, 0);
1115				}
1116				else if (wParam == 1) {
1117					//Internal Timer (double click test)
1118					//kill the timer
1119					windowVars.doubleClickTimerSet = -windowVars.doubleClickTimerSet;
1120					KillTimer(hWnd, 1);
1121				}
1122	
1123				break;
1124
1125				// These are Djehuty Protocol Requests
1126				// They do not belong in the final release
1127
1128			case WM_USER + 0xff00:
1129
1130				SendMessageW(cast(HWND)lParam, WM_USER+0xf000, 0,0);
1131				break;
1132
1133			case WM_USER + 0xff01:
1134
1135			// create window 1
1136
1137			// p1 : width
1138			// p2 : height
1139				break;
1140
1141			case WM_USER + 0xff02:
1142
1143			// create window 2
1144
1145			// p1: x
1146			// p2: y
1147				break;
1148
1149			default:
1150
1151				return DefWindowProcW(hWnd, uMsg, wParam, lParam);
1152		}
1153
1154		return 0;
1155	}
1156}