1 namespace gui::drivers;
12 #define _WIN32_WINNT 0x0502
19 #define WIN32_LEAN_AND_MEAN
20 #define Method _Method
23 #define String _String
25 #define Platform _Platform
31 #if defined(ECERE_VANILLA)
32 #define ECERE_NOJOYSTICK
35 #ifndef ECERE_NODINPUT
36 #ifndef ECERE_NOJOYSTICK
37 #define DIRECTINPUT_VERSION 0x700
40 #define DIRECTINPUT_VERSION 0x300
50 #define VK_EQUALS 0xBB
53 #define VK_PERIOD 0xBE
56 #define VK_LBRACKET 0xDB
57 #define VK_BACK_SLASH 0xDC
58 #define VK_RBRACKET 0xDD
62 #define WM_MOUSEWHEEL 0x20A
66 #define IDC_HAND (char *)0x7F89
71 #define LWA_COLORKEY 0x00000001
72 #define LWA_ALPHA 0x00000002
74 #define WS_EX_LAYERED 0x00080000
79 SetLayeredWindowAttributes(
97 #define ECERE_NODINPUT
98 #define ECERE_NOJOYSTICK
99 #define ECERE_NOBLENDING
102 static byte key2VK[256] =
104 0,VK_ESCAPE,'1','2','3','4','5','6','7','8','9','0',VK_MINUS,VK_EQUALS,VK_BACK,VK_TAB,
105 'Q','W','E','R','T','Y','U','I','O','P',VK_LBRACKET,VK_RBRACKET,VK_RETURN,VK_LCONTROL,'A','S',
106 'D','F','G','H','J','K','L',VK_SEMI,VK_QUOTE,VK_TILDE,VK_LSHIFT,VK_BACK_SLASH,'Z','X','C','V',
107 'B','N','M',VK_COMMA,VK_PERIOD,VK_DIVIDE,VK_RSHIFT,VK_MULTIPLY,VK_LMENU,VK_SPACE,VK_CAPITAL,VK_F1,VK_F2,VK_F3,VK_F4,VK_F5,
108 VK_F6,VK_F7,VK_F8,VK_F9,VK_F10,VK_NUMLOCK,VK_SCROLL,VK_NUMPAD7,VK_NUMPAD8,VK_NUMPAD9,VK_SUBTRACT,VK_NUMPAD4,VK_NUMPAD5,VK_NUMPAD6,VK_ADD,VK_NUMPAD1,
109 VK_NUMPAD2,VK_NUMPAD3,VK_NUMPAD0,VK_DELETE,0,0,0,VK_F11,VK_F12,0,0,0,0,0,0,0,
110 0,VK_RCONTROL,0,0,VK_RMENU,0,VK_HOME,VK_UP,VK_PRIOR,VK_LEFT,VK_RIGHT,VK_END,VK_DOWN,VK_NEXT,VK_INSERT,VK_DELETE
112 static const uint16 className[] = L"Ecere Application";
113 static HINSTANCE hInstance;
115 static WPARAM lastBits;
116 static LPARAM lastRes;
118 static DEVMODE devMode;
119 #ifndef ECERE_NODINPUT
120 static HWND acquiredWindow = null;
122 static HCURSOR systemCursors[SystemCursor];
123 static bool fullScreenMode;
124 static int desktopX = 0, desktopY = 0, desktopW = 0, desktopH = 0;
125 static DWORD hiResTimer;
126 // static HWND topWindow;
128 static HWND startBar;
130 #ifndef ECERE_NODINPUT
132 static HMODULE dInputDll = null;
133 static BOOL * (WINAPI * directInputCreate)(HINSTANCE, DWORD, IDirectInput **, void *);
134 static IDirectInput * dInput = null;
135 static IDirectInputDevice * directMouse = null;
136 #ifndef ECERE_NOJOYSTICK
137 static int numJoysticks = 0;
138 static IDirectInputDevice2 * directJoysticks[NUMJOY] = {null,null,null,null};
143 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
144 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp;
145 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
146 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit;
147 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove;
148 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick;
149 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown;
150 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp;
151 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick;
152 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown;
153 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp;
154 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick;
155 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown;
156 extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp;
160 static Box lastMonitorAreas[32];
161 static Box monitorAreas[32];
164 static bool EnumerateMonitors(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
166 MONITORINFO info = { 0 };
167 info.cbSize = sizeof(MONITORINFO);
168 GetMonitorInfo(hMonitor, &info);
169 monitorAreas[monitor] = { info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom };
174 static bool externalDisplayChange;
176 static int taskBarState;
177 static WINDOWPLACEMENT taskBarPlacement;
178 static bool activateApp;
180 static SystemCursor lastCursor = (SystemCursor)-1;
182 static void SmartShowWindow(HWND windowHandle, WindowState state, bool doActivate)
185 if(state == maximized)
186 showCmd = doActivate ? SW_SHOWMAXIMIZED : SW_MAXIMIZE;
187 else if(state == minimized)
188 showCmd = SW_MINIMIZE;
190 showCmd = doActivate ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
191 ShowWindow(windowHandle, showCmd);
194 void AeroSnapPosition(Window window, int x, int y, int w, int h)
196 int oldX = window.absPosition.x;
198 // To prevent having a window < minClientSize with Aero Snap, because we don't receive a WM_SIZING!
199 // The sensible implementation of this is in WM_SIZING
203 window.GetDecorationsSize(&ew, &eh);
211 gw = Max(gw, window.minSize.w);
212 gh = Max(gh, window.minSize.h);
213 gw = Min(gw, window.maxSize.w);
214 gh = Min(gh, window.maxSize.h);
216 if(!window.OnResizing(&gw, &gh))
218 gw = window.clientSize.w;
219 gh = window.clientSize.h;
222 gw = Max(gw, window.skinMinSize.w);
223 gh = Max(gh, window.skinMinSize.h);
228 if(w != gw || h != gh)
231 // Adjust x position if we resized from top or bottom left corner
239 if(window.state == minimized && !window.nativeDecorations && !window.hasMinimize)
241 guiApp.interfaceDriver.PositionRootWindow(window, x, y, w, h, move, true);
244 window.ExternalPosition(x, y, w, h);
247 void Win32UpdateStyle(Window window)
249 DWORD style = GetWindowLong(window.windowHandle, GWL_EXSTYLE);
250 if(window.showInTaskBar)
251 style |= WS_EX_APPWINDOW;
253 style &= ~WS_EX_APPWINDOW;
255 SetWindowLong(window.windowHandle, GWL_EXSTYLE, style);
258 class Win32Interface : Interface
260 class_property(name) = "Win32";
262 void ::RepositionDesktop(bool updateChildren)
265 static double lastTime = 0, time;
268 //static Size lastScreen;
269 //static Point lastScreenPos;
270 static double lastAutoHideCheck = 0;
271 int newTaskBarState = taskBarState;
272 HMONITOR primaryMonitor = 0;
275 if(time - lastTime < 0.1) return;
278 // Every sec, check for the auto hide property
279 if(time - lastAutoHideCheck > 1)
281 APPBARDATA appBarData = { 0 };
282 newTaskBarState = (int)SHAppBarMessage(ABM_GETSTATE, &appBarData);
283 lastAutoHideCheck = time;
287 EnumDisplayMonitors(null, null, EnumerateMonitors, 0);
288 for(c = 0; c<monitor; c++)
290 if(monitorAreas[c].left != lastMonitorAreas[c].left ||
291 monitorAreas[c].top != lastMonitorAreas[c].top ||
292 monitorAreas[c].right != lastMonitorAreas[c].right ||
293 monitorAreas[c].bottom != lastMonitorAreas[c].bottom)
299 memcpy(lastMonitorAreas, monitorAreas, sizeof(monitorAreas));
301 guiApp.virtualScreen =
303 GetSystemMetrics(SM_CXVIRTUALSCREEN),
304 GetSystemMetrics(SM_CYVIRTUALSCREEN)
306 guiApp.virtualScreenPos =
308 x = GetSystemMetrics(SM_XVIRTUALSCREEN),
309 y = GetSystemMetrics(SM_YVIRTUALSCREEN)
313 HMONITOR monitor = MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY);
316 MONITORINFO info = { 0 };
317 info.cbSize = sizeof(MONITORINFO);
318 primaryMonitor = monitor;
319 GetMonitorInfo(monitor, &info);
320 x = info.rcMonitor.left;
321 y = info.rcMonitor.top;
322 w = info.rcMonitor.right - info.rcWork.left;
323 h = info.rcMonitor.bottom - info.rcWork.top;
328 WINDOWPLACEMENT placement = { 0 };
329 placement.length = sizeof(WINDOWPLACEMENT);
331 if(!GetWindowPlacement(startBar, &placement))
333 startBar = FindWindowA("Shell_TrayWnd", null);
334 GetWindowPlacement(startBar, &placement);
337 HMONITOR taskBarMonitor = MonitorFromWindow(startBar, MONITOR_DEFAULTTONEAREST);
338 if(primaryMonitor == taskBarMonitor)
340 if(placement.rcNormalPosition.top <= 0 && placement.rcNormalPosition.bottom >= h - 1)
342 if(placement.rcNormalPosition.left <= 0)
344 x = (taskBarState & ABS_AUTOHIDE) ? 1 : placement.rcNormalPosition.right;
348 w = (taskBarState & ABS_AUTOHIDE) ? (w - 1) : Min(placement.rcNormalPosition.left, w);
350 else if(placement.rcNormalPosition.left <= 0 && placement.rcNormalPosition.right >= w - 1)
352 if(placement.rcNormalPosition.top <= 0)
354 y = (taskBarState & ABS_AUTOHIDE) ? 1 : placement.rcNormalPosition.bottom;
358 h = (taskBarState & ABS_AUTOHIDE) ? (h - 1) : Min(placement.rcNormalPosition.top, h);
364 placement.rcNormalPosition.left != taskBarPlacement.rcNormalPosition.left ||
365 placement.rcNormalPosition.top != taskBarPlacement.rcNormalPosition.top ||
366 placement.rcNormalPosition.right != taskBarPlacement.rcNormalPosition.right ||
367 placement.rcNormalPosition.bottom != taskBarPlacement.rcNormalPosition.bottom ||
368 newTaskBarState != taskBarState)
370 taskBarState = newTaskBarState;
371 guiApp.desktop.size.w = 0;
376 taskBarPlacement = placement;
377 guiApp.SetDesktopPosition(x, y, w, h, updateChildren);
380 //lastScreen = guiApp.virtualScreen;
381 //lastScreenPos = guiApp.virtualScreenPos;
385 /****************************************************************************
386 /// PRIVATE UTILITY FUNCTIONS /////////////
387 ****************************************************************************/
388 // --- Keyboard Input ---
389 bool ::ProcessKeyMessage(Window window, DWORD msg, WPARAM wParam, LPARAM lParam, unichar ch)
395 bool frenchShift = (ch < 0x10000) ? (((VkKeyScan((uint16)ch) >> 8) & 6) == 6) : false;
397 if(msg == WM_CHAR || msg == WM_DEADCHAR)
402 if(msg == WM_MOUSEWHEEL)
403 code = (((short) HIWORD(wParam)) < 0) ? wheelDown : wheelUp;
406 key = (byte)((lParam & 0xFF0000)>>16);
407 if(lParam & 0x1000000)
409 key = Interface::GetExtendedKey(key);
419 if(msg == WM_MOUSEWHEEL)
421 if(::GetAsyncKeyState(VK_SHIFT) & 0x80000)
423 if(::GetAsyncKeyState(VK_CONTROL) & 0x80000)
425 if(::GetAsyncKeyState(VK_MENU) & 0x80000)
428 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code, 0);
432 if(key != leftShift && key != rightShift && ::GetKeyState(VK_SHIFT) & 0x80000)
434 if(key != leftControl && key != rightControl && ::GetKeyState(VK_CONTROL) & 0x80000 && !frenchShift)
436 if(key != leftAlt && key != rightAlt && ::GetKeyState(VK_MENU) & 0x80000 && !frenchShift)
439 byte ch = Interface::TranslateKeykey, code.shift);
440 if(::GetKeyState(VK_CAPITAL))
444 if(msg == WM_KEYUP || msg == WM_SYSKEYUP)
446 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, code, ch);
450 if(!(lParam & 0x40000000))
455 Class * keyClass = eSystem_FindClass(__ecereModule, "Key");
456 code.OnGetString(string, null, null);
457 eSystem_Logf("%s\n", string);
461 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, code, ch);
464 result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code,ch);
471 // --- Window procedure ---
472 DWORD CALLBACK ::ApplicationWindow(HWND windowHandle, UINT msg, WPARAM wParam, LPARAM lParam)
475 Window window = (Window)GetWindowLongPtr(windowHandle, GWLP_USERDATA);
477 Window window = (Window)GetWindowLong(windowHandle, GWL_USERDATA);
479 static Point lastPos;
486 case WM_QUERYNEWPALETTE:
487 case WM_PALETTECHANGED:
489 window.display.RestorePalette();
490 UpdateWindow(windowHandle);
494 if(!fullScreenMode && !guiApp.IsModeSwitching())
498 Window modalRoot = window.FindModal();
500 HWND modalWindow = modalRoot ? modalRoot.windowHandle : null;
502 if(window.creationActivation == flash || window.hasMinimize || window.borderStyle != sizableThin)
504 FLASHWINFO flashInfo = { 0 };
505 flashInfo.cbSize = sizeof(FLASHWINFO);
506 flashInfo.hwnd = window.windowHandle;
507 flashInfo.uCount = 0;
508 flashInfo.dwFlags = FLASHW_STOP;
509 FlashWindowEx((void *)&flashInfo);
512 if(modalWindow && modalWindow != windowHandle)
513 modalRoot.ExternalActivate(true, true, window, null);
515 window.ExternalActivate(true, true, window, null);
522 foreground = GetForegroundWindow();
523 if(foreground == windowHandle && lParam)
524 foreground = (HWND)lParam;
526 GetWindowThreadProcessId(foreground, &id);
529 windowLong = (void*)GetWindowLongPtr(foreground, GWLP_WNDPROC);
531 windowLong = (void*)GetWindowLong(foreground, GWL_WNDPROC);
533 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
534 // The != ApplicationWindow check is for not recognizing the Console window as an Ecere Window
535 // That check causes a problem with the OpenGL driver which seems to popup a window of a different class
536 if(window.displaySystem && window.displaySystem.driver == class(OpenGLDisplayDriver))
537 windowLong = (void *)ApplicationWindow;
539 if(id != GetCurrentProcessId() || windowLong != (void *)ApplicationWindow)
540 window.ExternalActivate(false, true, window, null);
541 // DefWindowProc for WM_NCACTIVATE draws the decorations, make sure it's drawn in the right state
542 return (uint)DefWindowProc(windowHandle, msg, window.active, lParam);
547 for(window = guiApp.desktop.firstChild; window; window = window.next)
548 SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 0,0,0,0,
549 SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE); //|SWP_NOREDRAW);
553 return (uint)DefWindowProc(windowHandle, msg, window ? window.active : wParam, lParam);
556 if(!guiApp.IsModeSwitching())
560 HDC hdc = GetDC(windowHandle);
563 guiApp.SetAppFocus(false);
564 ShowWindow(windowHandle, SW_MINIMIZE);
565 ChangeDisplaySettings(null,0);
566 SetSystemPaletteUse(hdc, SYSPAL_STATIC);
570 ChangeDisplaySettings(&devMode, CDS_FULLSCREEN);
571 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
573 window.display.RestorePalette();
574 ShowWindow(windowHandle, SW_SHOWNORMAL);
575 guiApp.SetAppFocus(true);
577 window.display.Resize(window.clientSize.w, window.clientSize.h);
580 ReleaseDC(windowHandle, hdc);
586 if(wParam && !guiApp.desktop.active /*&& lParam != GetCurrentThreadID()*/)
590 for(window = guiApp.desktop.firstChild; window; window = window.next)
591 SetWindowPos(window.windowHandle, window.style.stayOnTop ? HWND_TOPMOST : HWND_TOP, 0,0,0,0,
592 SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE); //|SWP_NOREDRAW);
595 guiApp.SetAppFocus((bool)wParam);
599 guiApp.SetAppFocus((bool)wParam);
604 if(!window.alphaBlend || window.display.pixelFormat != pixelFormat888)
608 #define ACCESS_ITEM(l, id) \
609 ((FastItem)(((id) == -1) ? null : (((byte *)((l).items)) + (id) * (l).itemSize)))
612 #define ACCESS_ITEM(l, id) \
615 BoxItem item = window.dirtyArea.count ? (BoxItem)ACCESS_ITEM(window.dirtyArea, window.dirtyArea.first) : null;
617 BeginPaint(windowHandle, &ps);
619 // Prevent flickering if we're going to update anyways
621 printf(" Paint message (%d, %d)-(%d, %d)\n",
622 item ? item.box.left : 0,
623 item ? item.box.top : 0,
624 item ? item.box.right : 0,
625 item ? item.box.bottom : 0);
627 // Causes redraw bug...
628 if(!window.manageDisplay || !item ||
631 item.box.right < window.size.w - 1 ||
632 item.box.bottom < window.size.h - 1)
634 Box box { ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-1, ps.rcPaint.bottom-1 };
635 window.UpdateDirty(box);
637 // TODO: Fix precompiler with
638 // window.UpdateDirty((Box *)&ps.rcPaint);
639 EndPaint(windowHandle, &ps);
643 BeginPaint(windowHandle, &ps);
644 EndPaint(windowHandle, &ps);
648 case WM_DISPLAYCHANGE:
650 if(!guiApp.fullScreenMode && (lastBits != wParam || lastRes != lParam))
653 HWND foregroundWindow = GetForegroundWindow();
654 int w = LOWORD(lParam);
655 int h = HIWORD(lParam);
657 GetWindowRect(foregroundWindow, &rect);
658 if(rect.right == w && rect.bottom == h)
664 externalDisplayChange = true;
665 if(guiApp.desktop.DisplayModeChanged())
668 if(!window.style.hidden)
669 SmartShowWindow(window.windowHandle, (window.nativeDecorations && window.state == maximized) ? maximized : normal, false);
670 window.FigureCaption(caption);
671 SetRootWindowCaption(window, caption);
673 externalDisplayChange = false;
686 DWORD min = 0, max = 0;
688 if(msg != WM_CHAR && window.composing)
693 case WM_SYSKEYDOWN: min = max = WM_SYSCHAR; break;
694 case WM_KEYDOWN: min = max = WM_CHAR; break;
695 case WM_SYSKEYUP: min = WM_SYSCHAR; max = WM_SYSDEADCHAR; break;
696 case WM_KEYUP: min = WM_CHAR; max = WM_DEADCHAR; break;
699 // This is very annoying.
700 // PeekMessage somehow invokes this function directly... don't know why.
701 // Only crashes when running through debug mode in visual studio
703 if(msg == WM_CHAR || msg == WM_DEADCHAR || PeekMessage(&charMsg, windowHandle, min, max, PM_REMOVE))
705 ch = (msg == WM_CHAR || msg == WM_DEADCHAR) ? (unichar)wParam : (unichar)charMsg.wParam;
706 // TOCHECK: What is this for again? Fixing some obscure activation status?
707 // -- I believe this was somehow allowing 'unmaximizing', but was causing problems
708 // as there was no way to prevent AltEnter from doing so (e.g. when it is used for a node property)
709 // Worked around by fixing ProcessHotKeys to properly check for sysButtons in parent.parent when sys buttons
710 // are placed inside a menu bar for a document
712 if(msg == WM_SYSKEYDOWN && ch == 13)
714 ShowWindow(window.windowHandle, window.state == maximized ? SW_MAXIMIZE : SW_SHOWNORMAL);
715 // This last line been commented out for a long time:
716 // window.ExternalActivate(true, true, window, null);
719 if(msg == WM_SYSKEYUP || msg == WM_KEYUP)
721 if(!ProcessKeyMessage(window, WM_KEYDOWN, 0x40000000, 0, ch))
727 ProcessKeyMessage(window, msg, wParam, lParam, ch);
728 if(window.composing && msg == WM_CHAR)
730 COMPOSITIONFORM form;
731 Window caretOwner = guiApp.caretOwner;
734 HIMC ctx = ImmGetContext(windowHandle);
735 form.dwStyle = CFS_POINT;
736 form.ptCurrentPos.x = caretOwner.caretPos.x - caretOwner.scroll.x + caretOwner.absPosition.x - window.absPosition.x + 4;
737 form.ptCurrentPos.y = caretOwner.caretPos.y - caretOwner.scroll.x + caretOwner.absPosition.y - window.absPosition.y + 2;
738 window.composing = true;
739 ImmSetCompositionWindow(ctx, &form);
740 ImmReleaseContext(windowHandle, ctx);
743 if(msg != WM_MOUSEWHEEL)
747 case WM_IME_STARTCOMPOSITION:
749 COMPOSITIONFORM form;
750 Window caretOwner = guiApp.caretOwner;
753 HIMC ctx = ImmGetContext(windowHandle);
754 form.dwStyle = CFS_POINT;
755 form.ptCurrentPos.x = caretOwner.caretPos.x - caretOwner.scroll.x + caretOwner.absPosition.x - window.absPosition.x + 4;
756 form.ptCurrentPos.y = caretOwner.caretPos.y - caretOwner.scroll.y + caretOwner.absPosition.y - window.absPosition.y + 2;
758 form.rcArea.left = window.caretPos.x;
759 form.rcArea.top = 250;
760 form.rcArea.right = 500;
761 form.rcArea.bottom = 300;
763 window.composing = true;
764 DefWindowProc(windowHandle, msg, wParam, lParam);
765 ImmSetCompositionWindow(ctx, &form);
766 ImmSetStatusWindowPos(ctx, &form.ptCurrentPos);
768 FontResource res = caretOwner.font;
769 LOGFONT font = { 0 };
771 int pixels = GetDeviceCaps(hdc, LOGPIXELSY);
773 font.lfHeight = -(int)((float)res.size * pixels / 72 + 0.5);
774 font.lfWeight = res.flags.bold ? FW_BOLD : FW_NORMAL;
775 font.lfItalic = res.flags.italic ? TRUE : FALSE,
776 font.lfUnderline = res.flags.underline ? TRUE : FALSE;
777 font.lfCharSet = DEFAULT_CHARSET;
778 font.lfOutPrecision = OUT_DEFAULT_PRECIS;
779 font.lfClipPrecision = CLIP_DEFAULT_PRECIS;
780 font.lfQuality = DEFAULT_QUALITY;
781 font.lfPitchAndFamily = (byte)(DEFAULT_PITCH|FF_DONTCARE); // TODO: Fix compiler 0 | 0 to produce byte, not int
782 UTF8toUTF16Buffer(res.faceName, font.lfFaceName, LF_FACESIZE);
784 ImmSetCompositionFont(ctx, &font);
785 ImmReleaseContext(windowHandle, ctx);
791 case WM_IME_ENDCOMPOSITION:
792 window.composing = false;
793 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
794 /*case WM_IME_COMPOSITION:
795 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
797 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
799 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
801 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
803 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
805 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
806 case WM_IME_SETCONTEXT:
807 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
809 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
811 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
812 case WM_IME_COMPOSITIONFULL:
813 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
816 if(window.nativeDecorations)
817 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
827 case WM_LBUTTONDBLCLK:
829 case WM_RBUTTONDBLCLK:
831 case WM_MBUTTONDBLCLK:
833 x = window.absPosition.x;
834 y = window.absPosition.y;
835 /*case WM_NCLBUTTONUP:
838 case WM_NCLBUTTONDOWN:
839 case WM_NCLBUTTONDBLCLK:
840 case WM_NCRBUTTONDOWN:
841 case WM_NCRBUTTONDBLCLK:
842 case WM_NCMBUTTONDOWN:
843 case WM_NCMBUTTONDBLCLK:*/
847 bool consequential = false;
849 x += (short)LOWORD(lParam);
850 y += (short)HIWORD(lParam);
852 if(window.nativeDecorations && msg != WM_NCMOUSEMOVE)
854 x += window.clientStart.x;
855 y += window.clientStart.y - (window.hasMenuBar ? skinMenuHeight : 0);
858 if(::GetKeyState(VK_SHIFT) & 0x80000) code.shift = true;
859 if(::GetKeyState(VK_CONTROL) & 0x80000) code.ctrl = true;
860 if(::GetKeyState(VK_MENU) & 0x80000) code.alt = true;
861 if(wParam & MK_LBUTTON) code.left = true;
862 if(wParam & MK_MBUTTON) code.middle = true;
863 if(wParam & MK_RBUTTON) code.right = true;
865 if(msg == WM_MOUSEMOVE)
867 if(lastPos.x == x && lastPos.y == y)
868 consequential = true;
878 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x,y,&code, consequential, false);
880 //case WM_NCLBUTTONDBLCLK:
881 case WM_LBUTTONDBLCLK:
882 if(!window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick, x,y,&code, false, true))
884 //case WM_NCLBUTTONDOWN:
886 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown,x,y,&code, false,
887 /*(msg == WM_LBUTTONDBLCLK) ? false: */true);
889 //case WM_NCLBUTTONUP:
890 case WM_LBUTTONUP: window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp, x,y,&code, false, false);break;
891 //case WM_NCMBUTTONDBLCLK:
892 case WM_MBUTTONDBLCLK:
893 if(!window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick, x,y,&code, false, false))
895 //case WM_NCMBUTTONDOWN:
897 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown, x,y,&code, false,
898 (msg == WM_LBUTTONDBLCLK) ? false: true);
900 //case WM_NCMBUTTONUP:
902 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp, x,y,&code, false, false);
904 //case WM_NCRBUTTONDBLCLK:
905 case WM_RBUTTONDBLCLK:
906 if(!window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick, x,y,&code, false, true))
908 //case WM_NCRBUTTONDOWN:
910 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown, x,y,&code, false,
911 (msg == WM_LBUTTONDBLCLK) ? false: true);
913 //case WM_NCRBUTTONUP:
915 window.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp, x,y,&code, false, false);
919 if(msg == WM_NCMOUSEMOVE)
920 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
925 if(window.nativeDecorations)
927 if(DefWindowProc(windowHandle, msg, wParam, lParam))
930 // SetCursor(systemCursors[0]);
931 SetCursor((lastCursor == (SystemCursor)-1) ? null : systemCursors[lastCursor]);
934 case WM_EXITMENULOOP:
935 case WM_EXITSIZEMOVE:
936 // We had some DirectInput stuff in here
938 case WM_ENTERMENULOOP:
939 case WM_ENTERSIZEMOVE:
940 // We had some DirectInput stuff in here
947 /*case WM_GETMINMAXINFO:
949 MINMAXINFO * mmi = (MINMAXINFO *)lParam;
950 if(window.nativeDecorations)
952 WINDOWPLACEMENT place = { 0 };
953 place.length = sizeof(WINDOWPLACEMENT);
954 GetWindowPlacement(windowHandle, &place);
955 if((place.showCmd & SW_SHOWMAXIMIZED) && window.state != maximized)
956 window.state = maximized;
957 else if((place.showCmd & SW_SHOWMINIMIZED) && window.state != minimized)
958 window.state = minimized;
959 else if((place.showCmd & SW_SHOWNORMAL) && window.state != normal && window.visible)
960 window.state = normal;
963 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
967 case WM_WINDOWPOSCHANGED:
969 if(window.nativeDecorations)
972 WINDOWPOS * pos = (WINDOWPOS *)lParam;
973 //if((pos->flags & SWP_SHOWWINDOW))
975 if((pos->flags & 0x800)) // SWP_STATECHANGED
977 WINDOWPLACEMENT place = { 0 };
978 place.length = sizeof(WINDOWPLACEMENT);
979 GetWindowPlacement(windowHandle, &place);
980 printf("WM_WINDOWPOSCHANGED: ");
981 printf("SWP_STATECHANGED (");
982 if((place.showCmd & SW_SHOWMAXIMIZED))
984 else if((place.showCmd & SW_SHOWMINIMIZED))
986 else if((place.showCmd & SW_SHOWNORMAL))
990 /*if((place.showCmd & SW_SHOWMAXIMIZED) && window.state != maximized)
991 window.state = maximized;
992 else if((place.showCmd & SW_SHOWMINIMIZED) && window.state != minimized)
993 window.state = minimized;
994 else if((place.showCmd & SW_SHOWNORMAL) && window.state != normal && window.visible)
995 window.state = normal;*/
999 if(!(pos->flags & SWP_NOMOVE) || !(pos->flags & SWP_NOSIZE))
1002 //GetWindowRect(windowHandle, &rcWindow);
1003 WINDOWPLACEMENT place = { 0 };
1004 place.length = sizeof(WINDOWPLACEMENT);
1005 GetWindowPlacement(windowHandle, &place);
1006 printf("WM_WINDOWPOSCHANGED: ");
1007 printf("!SWP_NOMOVE || !SWP_NOSIZE (");
1009 if(wParam == SIZE_MAXIMIZED && window.state != maximized)
1010 window.state = maximized;
1011 else if(wParam == SIZE_MINIMIZED && window.state != minimized)
1012 window.state = minimized;
1013 else if(wParam == SIZE_RESTORED && window.state != normal && window.visible)
1014 window.state = normal;
1016 /*if((place.showCmd & SW_MAXIMIZE) && window.state != maximized)
1017 window.state = maximized;
1018 else if((place.showCmd & SW_MINIMIZE) && window.state != minimized)
1019 window.state = minimized;
1020 else if((place.showCmd & SW_RESTORE) && window.state != normal && window.visible)
1021 window.state = normal;*/
1023 //x = rcWindow.left - desktopX;
1024 //y = rcWindow.top - desktopY;
1025 //w = rcWindow.right - rcWindow.left;
1026 //h = rcWindow.bottom - rcWindow.top;
1027 x = pos->x - desktopX;
1028 y = pos->y - desktopY;
1031 printf("%d, %d, %d, %d) ", x, y, w, h);
1033 AeroSnapPosition(window, x, y, w, h);
1034 if(!(pos->flags & SWP_NOSIZE) && !guiApp.modeSwitching)
1035 window.UpdateVisual(null);
1040 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
1047 //WINDOWPLACEMENT place = { 0 };
1049 //place.length = sizeof(WINDOWPLACEMENT);
1050 //GetWindowPlacement(windowHandle, &place);
1051 GetWindowRect(windowHandle, &rcWindow);
1054 if((place.showCmd & SW_SHOWMAXIMIZED) && window.state != maximized)
1055 window.state = maximized;
1056 else if((place.showCmd & SW_SHOWMINIMIZED) && window.state != minimized)
1057 window.state = minimized;
1058 else if((place.showCmd & SW_SHOWNORMAL) && window.state != normal && window.visible)
1059 window.state = normal;
1062 x = rcWindow.left - desktopX;
1063 y = rcWindow.top - desktopY;
1064 w = rcWindow.right - rcWindow.left;
1065 h = rcWindow.bottom - rcWindow.top;
1067 //printf("WM_MOVE - (%d,%d) (%dx%d) (%s) \n", x, y, w, h,
1068 // window.state == maximized ? "maximized" : window.state == minimized ? "minimized" : window.state == normal ? "normal" : "BAD");
1070 AeroSnapPosition(window, x, y, w, h);
1077 RECT * rect = (RECT *)lParam;
1081 window.GetDecorationsSize(&ew, &eh);
1083 w = rect->right - rect->left;
1084 h = rect->bottom - rect->top;
1092 w = Max(w, window.minSize.w);
1093 h = Max(h, window.minSize.h);
1094 w = Min(w, window.maxSize.w);
1095 h = Min(h, window.maxSize.h);
1097 if(!window.OnResizing(&w, &h))
1099 w = window.clientSize.w;
1100 h = window.clientSize.h;
1103 w = Max(w, window.skinMinSize.w);
1104 h = Max(h, window.skinMinSize.h);
1109 if(wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT)
1110 rect->left = rect->right - w;
1112 rect->right = rect->left + w;
1114 if(wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOP || wParam == WMSZ_TOPRIGHT)
1115 rect->top = rect->bottom - h;
1117 rect->bottom = rect->top + h;
1123 if(window.nativeDecorations)
1127 GetWindowRect(windowHandle, &rcWindow);
1129 if(wParam == SIZE_MAXIMIZED && window.state != maximized)
1130 window.state = maximized;
1131 else if(wParam == SIZE_MINIMIZED && window.state != minimized)
1132 window.state = minimized;
1133 else if(wParam == SIZE_RESTORED && window.state != normal && window.visible)
1134 window.state = normal;
1136 x = rcWindow.left - desktopX;
1137 y = rcWindow.top - desktopY;
1138 w = rcWindow.right - rcWindow.left;
1139 h = rcWindow.bottom - rcWindow.top;
1141 //printf("WM_SIZE - (%d,%d) (%dx%d) (%s) \n", x, y, w, h,
1142 // wParam == SIZE_MAXIMIZED ? "SIZE_MAXIMIZED" : wParam == SIZE_MINIMIZED ? "SIZE_MINIMIZED" : wParam == SIZE_RESTORED ? "SIZE_RESTORED" : "BAD");
1144 AeroSnapPosition(window, x, y, w, h);
1145 if(!guiApp.modeSwitching)
1146 window.UpdateVisual(null);
1149 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
1153 return (uint)DefWindowProc(windowHandle, msg, wParam, lParam);
1157 return (uint)DefMDIChildProc(windowHandle, msg, wParam, lParam);
1158 // return DefWindowProc(windowHandle, msg, wParam, lParam);
1162 // --- DirectInput ---
1164 #ifndef ECERE_NODINPUT
1166 #ifndef ECERE_NOJOYSTICK
1167 bool CALLBACK ::JoystickCallback( const DIDEVICEINSTANCE* pdidInstance, void * context )
1169 if(!dInput->lpVtbl->CreateDevice(dInput, &GUID_Joystick,
1170 (IDirectInputDevice **)&directJoysticks[numJoysticks], null ))
1172 return DIENUM_CONTINUE;
1175 bool CALLBACK ::JoystickAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, void * context )
1178 IDirectInputDevice2 * curJoy = (IDirectInputDevice2 *)context;
1180 diprg.diph.dwSize = sizeof(DIPROPRANGE);
1181 diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
1182 diprg.diph.dwHow = DIPH_BYOFFSET;
1183 diprg.diph.dwObj = pdidoi->dwOfs;
1186 if(curJoy->lpVtbl->SetProperty(curJoy, DIPROP_RANGE, &diprg.diph))
1188 return DIENUM_CONTINUE;
1192 void ::TerminateDirectInput()
1197 directMouse->lpVtbl->Unacquire(directMouse);
1198 directMouse->lpVtbl->Release(directMouse);
1201 #ifndef ECERE_NOJOYSTICK
1202 for(j=0; j<numJoysticks; j++)
1204 if (directJoysticks[j])
1206 directJoysticks[j]->lpVtbl->Unacquire(directJoysticks[j]);
1207 directJoysticks[j]->lpVtbl->Release(directJoysticks[j]);
1208 directJoysticks[j] = null;
1215 dInput->lpVtbl->Release(dInput);
1219 directInputCreate = null;
1223 FreeLibrary(dInputDll);
1228 bool ::InitDirectInput()
1230 bool result = false;
1232 dInputDll = LoadLibraryA("dinput.dll");
1235 if((directInputCreate = (void *)GetProcAddress(dInputDll, "DirectInputCreateA")))
1237 if(!directInputCreate( hInstance, DIRECTINPUT_VERSION, &dInput, null ))
1242 if(!dInput->lpVtbl->CreateDevice(dInput, &GUID_SysMouse, &directMouse, null ))
1243 directMouse->lpVtbl->SetDataFormat(directMouse, &c_dfDIMouse );
1245 #ifndef ECERE_NOJOYSTICK
1247 dInput->lpVtbl->EnumDevices(dInput, DIDEVTYPE_JOYSTICK, JoystickCallback, null, DIEDFL_ATTACHEDONLY );
1248 for(j=0; j<NUMJOY; j++)
1249 if(directJoysticks[j])
1250 if(!directJoysticks[j]->lpVtbl->SetDataFormat(directJoysticks[j], &c_dfDIJoystick ))
1251 directJoysticks[j]->lpVtbl->EnumObjects(directJoysticks[j], JoystickAxesCallback, directJoysticks[j], DIDFT_AXIS );
1260 void ::AcquireDirectInput(HWND windowHandle, bool state)
1262 if((state && !acquiredWindow) || (!state && acquiredWindow == windowHandle))
1269 directMouse->lpVtbl->SetCooperativeLevel(directMouse, /*fullScreenMode ? */windowHandle /*: HWND_DESKTOP*/, DISCL_EXCLUSIVE|DISCL_FOREGROUND);
1270 directMouse->lpVtbl->Acquire(directMouse);
1273 directMouse->lpVtbl->Unacquire(directMouse);
1275 #ifndef ECERE_NOJOYSTICK
1276 for(j = 0; j<NUMJOY; j++)
1277 if(directJoysticks[j])
1281 directJoysticks[j]->lpVtbl->SetCooperativeLevel(directJoysticks[j], /*fullScreenMode ? */windowHandle /*: HWND_DESKTOP*/, DISCL_EXCLUSIVE|DISCL_FOREGROUND);
1282 directJoysticks[j]->lpVtbl->Acquire(directJoysticks[j]);
1285 directJoysticks[j]->lpVtbl->Unacquire(directJoysticks[j]);
1288 acquiredWindow = state ? windowHandle : null;
1293 /****************************************************************************
1294 /// INTEGRATION FUNCTIONALITY /////////////
1295 ****************************************************************************/
1296 bool eisWIN32ProcessKey(Window window, DWORD msg, DWORD wParam, DWORD lParam, byte ch)
1298 return ProcessKeyMessage(window, msg, wParam, lParam, ch);
1301 HWND eisWIN32GetWindowHandle(Window window)
1303 return window.windowHandle ? window.windowHandle : window.rootWindow.windowHandle;
1306 /****************************************************************************
1307 /// DRIVER IMPLEMENTATION /////////////
1308 ****************************************************************************/
1311 void CALLBACK ::TimerProc(UINT uTimerID, UINT uMsg, uint64 dwUser, uint64 dw1, uint64 dw2)
1313 void CALLBACK ::TimerProc(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
1316 guiApp.SignalEvent();
1319 // --- User Interface System ---
1324 CS_DBLCLKS, ApplicationWindow, 0L, 0L, 0,
1325 LoadIcon(null, IDI_APPLICATION),
1332 lastRes = MAKELPARAM(GetSystemMetrics(SM_CYSCREEN), GetSystemMetrics(SM_CXSCREEN));
1333 lastBits = (WPARAM)GetDeviceCaps(hdc, BITSPIXEL);
1337 wcl.hInstance = hInstance = GetModuleHandle(null);
1338 RegisterClass(&wcl);
1340 // Move that in reposition desktop
1341 startBar = FindWindowA("Shell_TrayWnd", null);
1343 systemCursors[arrow] = LoadCursor(null, IDC_ARROW);
1344 systemCursors[iBeam] = LoadCursor(null, IDC_IBEAM);
1345 systemCursors[cross] = LoadCursor(null, IDC_CROSS);
1346 systemCursors[moving] = LoadCursor(null, IDC_SIZEALL);
1347 systemCursors[sizeNESW] = LoadCursor(null, IDC_SIZENESW);
1348 systemCursors[sizeNS ] = LoadCursor(null, IDC_SIZENS);
1349 systemCursors[sizeNWSE] = LoadCursor(null, IDC_SIZENWSE);
1350 systemCursors[sizeWE ] = LoadCursor(null, IDC_SIZEWE);
1351 systemCursors[hand ] = LoadCursor(null, IDC_HAND);
1353 SetTimer(null, 0, (DWORD)(1000.0 / 18.2), null);
1354 //SetTimer(null, 0, 1, null);
1358 hiResTimer = timeSetEvent(
1361 TimerProc,0,TIME_PERIODIC);
1364 hiResTimer = timeSetEvent(
1367 TimerProc,0,TIME_PERIODIC);
1371 topWindow = CreateWindowEx(0, className, "",WS_POPUP,0,0,1,1,HWND_DESKTOP,
1372 null, hInstance, null);
1379 if(hiResTimer) timeKillEvent(hiResTimer);
1380 #ifndef ECERE_NODINPUT
1381 TerminateDirectInput();
1385 void SetTimerResolution(uint hertz)
1387 if(hiResTimer) timeKillEvent(hiResTimer);
1389 hiResTimer = timeSetEvent(1000 / hertz, 1000 / hertz, TimerProc, 0, TIME_PERIODIC);
1392 bool ProcessInput(bool processAll)
1396 RepositionDesktop(true);
1397 if(PeekMessage(&msg,0,0,0,PM_NOREMOVE))
1399 while(PeekMessage(&msg,0,0,0,PM_REMOVE))
1401 TranslateMessage(&msg);
1402 DispatchMessage(&msg);
1403 // printf("%d\n", msg.message);
1404 if(!processAll || msg.message == WM_TIMER) break;
1413 MsgWaitForMultipleObjects(1, (void **)guiApp.semaphore, FALSE, (uint)(1000 / 18.2) /*INFINITE*/, QS_ALLINPUT);
1416 void Lock(Window window)
1421 void Unlock(Window window)
1426 const char ** GraphicsDrivers(int * numDrivers)
1428 static const char *graphicsDrivers[] = { "GDI", "DirectDraw", "OpenGL", "Direct3D", "Direct3D8", "Direct3D9" };
1429 *numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
1430 return (const char **)graphicsDrivers;
1433 void GetCurrentMode(bool * fullScreen, Resolution * resolution, PixelFormat * colorDepth, int * refreshRate)
1435 *fullScreen = fullScreenMode;
1439 for(c = 0; c<Resolution::enumSize; c++)
1440 if(GetResolutionWidth(c) == devMode.dmPelsWidth && GetResolutionHeight(c) == devMode.dmPelsHeight)
1445 switch(devMode.dmBitsPerPel)
1447 case 8: *colorDepth = pixelFormat8; break;
1448 case 16: *colorDepth = pixelFormat555; break;
1449 default: *colorDepth = pixelFormat888; break;
1451 * refreshRate = devMode.dmDisplayFrequency;
1455 void EnsureFullScreen(bool *fullScreen)
1460 bool ScreenMode(bool fullScreen, Resolution resolution, PixelFormat colorDepth, int refreshRate, bool * textMode)
1465 fullScreenMode = fullScreen;
1469 FillBytes(&devMode, 0, sizeof(DEVMODE));
1470 devMode.dmSize = (uint16)sizeof(devMode);
1471 devMode.dmFields |=DM_BITSPERPEL;
1472 devMode.dmFields |=DM_PELSWIDTH|DM_PELSHEIGHT;
1473 devMode.dmFields |= DM_DISPLAYFREQUENCY;
1474 devMode.dmBitsPerPel = colorDepth ? GetDepthBits(colorDepth) : GetDeviceCaps(hdc, BITSPIXEL);
1475 devMode.dmPelsWidth = resolution ? GetResolutionWidth(resolution) : GetSystemMetrics(SM_CXSCREEN);
1476 devMode.dmPelsHeight = resolution ? GetResolutionHeight(resolution) : GetSystemMetrics(SM_CYSCREEN);
1477 devMode.dmDisplayFrequency = refreshRate ? refreshRate : GetDeviceCaps(hdc, VREFRESH);
1478 if(ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
1482 SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
1483 guiApp.SetDesktopPosition(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), false);
1488 static bool firstTime = true;
1490 ChangeDisplaySettings(null, 0);
1492 SetSystemPaletteUse(hdc, SYSPAL_STATIC);
1493 desktopX = desktopY = desktopW = desktopH = 0;
1495 RepositionDesktop(false);
1502 // --- Window Creation ---
1503 void * CreateRootWindow(Window window)
1506 uint16 * text = UTF8toUTF16(window.text, null);
1509 windowHandle = CreateWindowEx(0, className, text,
1511 0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),
1513 null, hInstance, null);
1514 ShowWindow(windowHandle, SW_SHOWNORMAL);
1516 else if(window.systemParent)
1517 windowHandle = CreateWindowEx(0, className, text,
1518 WS_CHILD,0,0,1,1, window.systemParent, null, hInstance, null);
1523 HWND parentWindow = null; //HWND_DESKTOP; // we get different behaviors with desktop...
1524 Window master = window.master, rootWindow = (master && master != guiApp.desktop) ? master.rootWindow : null;
1525 if(window.style.stayOnTop)
1526 exStyle |= WS_EX_TOPMOST;
1528 if(rootWindow && (window._isModal || window.style.interim || (window.style.thin && !window.style.showInTaskBar)))
1529 parentWindow = rootWindow.is3D ? rootWindow.parent.windowHandle : rootWindow.windowHandle;
1531 if(window.alphaBlend)
1532 // if(window.background.a < 255) //&& window.style & ES_REDRAW) Not needed anymore?
1533 exStyle |= WS_EX_LAYERED; // | WS_EX_TRANSPARENT;
1535 // Toolwindow will disappear if they don't have AppWindow set
1536 if(window.style.showInTaskBar) // Took this out as a way to prevent sticky notes from showing in task bar... ( added flag to Communicator ) || (!parentWindow && window.style.thin))
1538 exStyle |= WS_EX_APPWINDOW;
1539 parentWindow = null;
1542 if(window.style.thin)
1543 exStyle |= WS_EX_TOOLWINDOW;
1545 if(window.windowHandle)
1546 windowHandle = window.windowHandle;
1549 if(window.nativeDecorations)
1551 BorderBits borderStyle = window.borderStyle; // FIXME!
1552 style = WS_OVERLAPPED;
1553 if(borderStyle.fixed)
1554 style |= WS_CAPTION;
1556 style |= WS_SYSMENU;
1557 if(borderStyle.sizable)
1558 style |= WS_THICKFRAME;
1559 if(window.hasMinimize)
1560 style |= WS_MINIMIZEBOX;
1561 if(window.hasMaximize)
1562 style |= WS_MAXIMIZEBOX;
1564 windowHandle = CreateWindowEx(
1567 style | (window.systemParent ? WS_CHILD :
1568 (WS_POPUP | (window.style.hasMinimize ? WS_MINIMIZEBOX : 0))),
1569 0,0,1,1, parentWindow, null, hInstance, null);
1571 if(exStyle & WS_EX_LAYERED)
1572 SetLayeredWindowAttributes(windowHandle, 0, 255 /*A(window.background)*/, LWA_ALPHA);
1578 SetWindowLongPtr(windowHandle, GWLP_USERDATA, (int64)window);
1580 SetWindowLong(windowHandle, GWL_USERDATA, (DWORD)window);
1583 return windowHandle;
1586 void DestroyRootWindow(Window window)
1589 int c, lockCount = guiApp.lockMutex.lockCount;
1590 for(c = 0; c < lockCount; c++)
1591 guiApp.lockMutex.Release();
1593 oldIcon = (HICON)SendMessage(window.windowHandle, WM_GETICON, ICON_BIG, 0);
1595 if(oldIcon && oldIcon != (HICON)GetClassLongPtr(window.windowHandle, GCLP_HICON))
1597 if(oldIcon && oldIcon != (HICON)GetClassLong(window.windowHandle, GCL_HICON))
1599 DestroyIcon(oldIcon);
1601 ShowWindow(window.windowHandle, SW_HIDE);
1604 SetWindowLongPtr(window.windowHandle, GWLP_USERDATA, (int64)null);
1606 SetWindowLong(window.windowHandle, GWL_USERDATA, 0);
1608 DestroyWindow(window.windowHandle);
1610 for(c = 0; c < lockCount; c++)
1611 guiApp.lockMutex.Wait();
1613 window.windowHandle = null;
1616 // -- Window manipulation ---
1618 void SetRootWindowCaption(Window window, const char * name)
1620 uint16 * text = UTF8toUTF16(name, null);
1622 SetWindowText(window.windowHandle, text);
1627 void PositionRootWindow(Window window, int x, int y, int w, int h, bool move, bool resize)
1629 int flags = SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS;
1631 if(!window.systemParent && !fullScreenMode)
1637 if(!move) flags |= SWP_NOMOVE;
1638 if(!resize) flags |= SWP_NOSIZE;
1640 /*if(move && resize)
1642 flags |= SWP_NOMOVE;
1643 SetWindowPos(window.windowHandle, null, x, y, w, h, flags);
1644 flags &=~SWP_NOMOVE;
1645 flags |= SWP_NOSIZE;
1647 if(!window.nativeDecorations || window.state != maximized || !window.visible || guiApp.modeSwitching)
1648 SetWindowPos(window.windowHandle, null, x, y, w, h, flags);
1651 void OrderRootWindow(Window window, bool topMost)
1653 SetWindowPos(window.windowHandle, topMost ? HWND_TOPMOST : HWND_NOTOPMOST, 0,0,0,0,
1654 SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW);
1657 void SetRootWindowColor(Window window)
1659 if(window.alphaBlend && window.display.pixelFormat == pixelFormat888)
1661 /*if(A(window.background) == 255)
1663 if((style & WS_EX_LAYERED) == WS_EX_LAYERED)
1664 SetWindowLong(window.windowHandle, GWL_EXSTYLE, style &~WS_EX_LAYERED);
1668 #ifndef ECERE_NOBLENDING
1669 DWORD style = GetWindowLong(window.windowHandle, GWL_EXSTYLE);
1670 if((style & WS_EX_LAYERED) != WS_EX_LAYERED)
1671 SetWindowLong(window.windowHandle, GWL_EXSTYLE, style | WS_EX_LAYERED);
1673 // SetLayeredWindowAttributes(window.windowHandle, 0, 255 /*Max(A(window.background),1)*/, LWA_ALPHA);
1678 void OffsetWindow(Window window, int * x, int * y)
1680 if(window.systemParent)
1682 POINT point = {*x,*y};
1683 ClientToScreen(GetParent(window.windowHandle), &point);
1689 void UpdateRootWindow(Window window)
1691 UpdateWindow(window.windowHandle);
1694 void SetRootWindowState(Window window, WindowState state, bool visible)
1698 WindowState curState = window.state;
1699 *&window.state = state;
1704 SmartShowWindow(window.windowHandle, window.nativeDecorations ? state : normal, (window.active || window.creationActivation == activate) && !externalDisplayChange);
1707 ShowWindow(window.windowHandle, SW_MINIMIZE);
1710 *&window.state = curState;
1714 ShowWindow(window.windowHandle, SW_HIDE);
1718 void ActivateRootWindow(Window window)
1720 if(!externalDisplayChange)
1721 SetForegroundWindow(window.windowHandle);
1724 void FlashRootWindow(Window window)
1726 HWND hwnd = window.windowHandle;
1727 FLASHWINFO flashInfo = { 0 };
1728 Window master = window.master, rootWindow = (master && master != guiApp.desktop) ? master.rootWindow : null;
1729 if(!window.style.showInTaskBar && rootWindow && (window._isModal || window.style.interim))
1730 hwnd = rootWindow.windowHandle;
1732 flashInfo.cbSize = sizeof(FLASHWINFO);
1733 flashInfo.hwnd = hwnd;
1734 flashInfo.uCount = 1;
1735 flashInfo.dwFlags = FLASHW_TRAY; // FLASHW_ALL;
1737 FlashWindowEx((void *)&flashInfo);
1741 // --- Mouse-based window movement ---
1742 void StartMoving(Window window, int x, int y, bool fromKeyBoard)
1744 if(!fullScreenMode && !window.systemParent)
1745 // Commented out for Chess game because AI thread takes over the moving of main window... Still required?
1746 //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
1747 ; //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
1750 SetWindowPos(window.windowHandle, HWND_TOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
1751 mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0);
1752 if(!window.stayOnTop)
1753 SetWindowPos(window.windowHandle, HWND_NOTOPMOST, 0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
1757 void StopMoving(Window window)
1759 if(!fullScreenMode && !window.systemParent)
1760 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
1763 // -- Mouse manipulation ---
1765 void GetMousePosition(int *x, int *y)
1768 GetCursorPos(&point);
1773 void SetMousePosition(int x, int y)
1778 void SetMouseRange(Window window, Box box)
1780 ClipCursor((RECT *) box);
1783 void SetMouseCapture(Window window)
1786 SetCapture(window.windowHandle);
1791 // -- Mouse cursor ---
1793 void SetMouseCursor(Window window, SystemCursor cursor)
1795 if(lastCursor != cursor)
1797 lastCursor = cursor;
1798 SetCursor((cursor == (SystemCursor)-1) ? null : systemCursors[cursor]);
1804 void SetCaret(int x, int y, int size)
1809 // --- Clipboard manipulation ---
1811 void ClearClipboard()
1813 if(OpenClipboard(null))
1820 bool AllocateClipboard(ClipBoard clipBoard, uint size)
1822 bool result = false;
1823 clipBoard.text = new byte[size];
1828 bool SaveClipboard(ClipBoard clipBoard)
1830 bool result = false;
1834 uint16 * u16text = UTF8toUTF16(clipBoard.text, &wordCount);
1836 clipBoard.handle = GlobalAlloc(GHND | GMEM_DDESHARE, wordCount * 2);
1837 if(clipBoard.handle)
1839 uint16 * text = GlobalLock(clipBoard.handle);
1842 memcpy(text, u16text, wordCount * 2);
1843 GlobalUnlock(clipBoard.handle);
1844 if(OpenClipboard(null))
1847 if(SetClipboardData(CF_UNICODETEXT, clipBoard.handle))
1855 GlobalFree(clipBoard.handle);
1862 bool LoadClipboard(ClipBoard clipBoard)
1864 bool result = false;
1865 if(OpenClipboard(null))
1867 if((clipBoard.handle = GetClipboardData(CF_UNICODETEXT)))
1869 uint16 * u16text = GlobalLock(clipBoard.handle);
1872 clipBoard.text = UTF16toUTF8(u16text);
1874 GlobalUnlock(clipBoard.handle);
1882 void UnloadClipboard(ClipBoard clipBoard)
1884 delete clipBoard.text;
1887 // --- State based input ---
1889 bool AcquireInput(Window window, bool state)
1891 #ifndef ECERE_NODINPUT
1892 if(dInput || InitDirectInput())
1894 AcquireDirectInput(window.windowHandle, state);
1901 bool GetMouseState(MouseButtons * buttons, int * x, int * y)
1903 bool result = false;
1904 #ifndef ECERE_NODINPUT
1905 DIMOUSESTATE dims = {0};
1907 if(acquiredWindow && directMouse)
1909 if(directMouse->lpVtbl->GetDeviceState(directMouse, sizeof(DIMOUSESTATE), &dims ))
1911 FillBytes(&dims, 0, sizeof(dims));
1912 directMouse->lpVtbl->Acquire(directMouse);
1916 /* We don't really want this...
1919 if(GetAsyncKeyState(VK_LBUTTON))
1920 dims.rgbButtons[0] |= 0x80;
1921 if(GetAsyncKeyState(VK_RBUTTON))
1922 dims.rgbButtons[1] |= 0x80;
1923 if(GetAsyncKeyState(VK_MBUTTON))
1924 dims.rgbButtons[2] |= 0x80;
1933 Window window = (Window)GetWindowLongPtr(acquiredWindow, GWLP_USERDATA);
1935 Window window = (Window)GetWindowLong(acquiredWindow, GWL_USERDATA);
1937 ProcessKeyMessage(window, WM_MOUSEWHEEL, ((uint16)(short)dims.lZ) << 16, 0, 0);
1941 *buttons = MouseButtons {
1942 left = (dims.rgbButtons[0] & 0x80) ? true : false,
1943 right = (dims.rgbButtons[1] & 0x80) ? true : false,
1944 middle = (dims.rgbButtons[2] & 0x80) ? true : false };
1951 bool GetJoystickState(int device, Joystick joystick)
1953 bool result = false;
1954 #ifndef ECERE_NODINPUT
1955 if(joystick != null)
1957 DIJOYSTATE dijs = {0};
1958 #ifndef ECERE_NOJOYSTICK
1959 if(acquiredWindow && device < numJoysticks)
1961 if(directJoysticks[device])
1963 directJoysticks[device]->lpVtbl->Poll(directJoysticks[device]);
1964 if(directJoysticks[device]->lpVtbl->GetDeviceState(directJoysticks[device], sizeof(DIJOYSTATE), &dijs ))
1965 directJoysticks[device]->lpVtbl->Acquire(directJoysticks[device]);
1970 joystick.x = dijs.lX;
1971 joystick.y = dijs.lY;
1972 joystick.z = dijs.lZ;
1973 joystick.rx = dijs.lRx;
1974 joystick.ry = dijs.lRy;
1975 joystick.rz = dijs.lRz;
1977 ((dijs.rgbButtons[0] & 0x80) ? JOY_BUTTON1 : 0)
1978 | ((dijs.rgbButtons[1] & 0x80) ? JOY_BUTTON2 : 0)
1979 | ((dijs.rgbButtons[2] & 0x80) ? JOY_BUTTON3 : 0)
1980 | ((dijs.rgbButtons[3] & 0x80) ? JOY_BUTTON4 : 0);
1986 bool GetKeyState(Key key)
1988 bool keyState = false;
1989 if(key < 256 || key == alt || key == shift || key == control)
1993 ks = GetAsyncKeyState(VK_MENU);
1994 else if(key == control)
1995 ks = GetAsyncKeyState(VK_CONTROL);
1996 else if(key == shift)
1997 ks = GetAsyncKeyState(VK_SHIFT);
1998 else if(key2VK[key])
1999 ks = GetAsyncKeyState(key2VK[key]);
2000 keyState = (ks & 0x80000) ? true : false;
2002 else if(key == capsState)
2003 keyState = (::GetKeyState(VK_CAPITAL) & 0x00000001) != 0;
2004 else if(key == numState)
2005 keyState = (::GetKeyState(VK_NUMLOCK) & 0x00000001) != 0;
2006 else if(key == scrollState)
2007 keyState = (::GetKeyState(VK_SCROLL) & 0x00000001) != 0;
2011 bool SetIcon(Window window, BitmapResource resource)
2014 HICON oldIcon = (HICON)SendMessage(window.windowHandle, WM_GETICON, ICON_BIG, 0);
2016 // Dialogs Inherit master's icon if none set
2017 if(!window.style.showInTaskBar && window.hasClose)
2019 Window master = window.master;
2020 while(master && !resource)
2022 Window rootWindow = (master && master != guiApp.desktop) ? master.rootWindow : null;
2023 if(rootWindow && rootWindow.icon)
2024 resource = rootWindow.icon;
2026 master = master.master;
2030 // WARNING -- putting this here as it is right after CreateRootWindow
2031 // Take out Layered flag if we're not in 24 bit
2033 if(window.alphaBlend && window.display.pixelFormat != pixelFormat888)
2035 #ifndef ECERE_NOBLENDING
2036 DWORD style = GetWindowLong(window.windowHandle, GWL_EXSTYLE);
2037 style &= ~WS_EX_LAYERED;
2038 SetWindowLong(window.windowHandle, GWL_EXSTYLE, style);
2044 if(oldIcon && oldIcon != (HICON)GetClassLongPtr(window.windowHandle, GCLP_HICON))
2046 if(oldIcon && oldIcon != (HICON)GetClassLong(window.windowHandle, GCL_HICON))
2049 DestroyIcon(oldIcon);
2055 if(bitmap.Load(resource.fileName, null, null))
2058 PixelFormat format = window.display.pixelFormat;
2059 int bits = GetDepthBits(format);
2062 bitmap.Convert(null, pixelFormat888, null);
2063 and.Allocate(null, (bitmap.width+7/8), bitmap.height, 0, pixelFormat8, false);
2065 blend = bits == 32 || bitmap.pixelFormat != pixelFormat888;
2068 byte * picture = and.picture;
2071 uint size = bitmap.height * bitmap.width;
2076 while(m < 8 && c < size)
2079 mask |= blend ? (!((ColorAlpha *)bitmap.picture)[c].a) : (((ColorAlpha *)bitmap.picture)[c].a <= 192);
2083 picture[b++] = mask;
2088 ColorAlpha color = ((ColorAlpha *)bitmap.picture)[c];
2089 if(blend ? (!color.a) : (color.a <= 192))
2091 color.color = { 0, 0, 0 };
2092 ((ColorAlpha *)bitmap.picture)[c] = color;
2097 if(bits == 15) { bits = 16; format = pixelFormat565; };
2098 bitmap.Convert(null, format, null);
2100 icon = CreateIcon(hInstance, bitmap.width, bitmap.height, 1, (byte)bits, and.picture, bitmap.picture);
2105 SendMessage(window.windowHandle, WM_SETICON, ICON_BIG, (LPARAM)icon);
2106 SendMessage(window.windowHandle, WM_SETICON, ICON_SMALL, (LPARAM)icon);
2110 void ::GetScreenArea(Window window, Box box)
2112 HMONITOR monitor = MonitorFromWindow(window.windowHandle, MONITOR_DEFAULTTONEAREST);
2113 HMONITOR taskBarMonitor = MonitorFromWindow(startBar, MONITOR_DEFAULTTONEAREST);
2116 MONITORINFO info = { 0 };
2117 info.cbSize = sizeof(MONITORINFO);
2118 GetMonitorInfo(monitor, &info);
2119 // box = { info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom };
2120 box = { info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right-1, info.rcMonitor.bottom-1 };
2122 if(taskBarMonitor == monitor)
2124 if(taskBarPlacement.rcNormalPosition.top <= box.top && taskBarPlacement.rcNormalPosition.bottom >= box.bottom)
2126 if(taskBarPlacement.rcNormalPosition.left <= box.left)
2128 if(taskBarState & ABS_AUTOHIDE)
2131 box.left = taskBarPlacement.rcNormalPosition.right;
2133 else if(taskBarState & ABS_AUTOHIDE)
2136 box.right = taskBarPlacement.rcNormalPosition.left;
2138 else if(taskBarPlacement.rcNormalPosition.left <= box.left && taskBarPlacement.rcNormalPosition.right >= box.right)
2140 if(taskBarPlacement.rcNormalPosition.top <= box.top)
2142 if(taskBarState & ABS_AUTOHIDE)
2145 box.top = taskBarPlacement.rcNormalPosition.bottom;
2147 else if(taskBarState & ABS_AUTOHIDE)
2150 box.bottom = taskBarPlacement.rcNormalPosition.top;
2154 box.left -= desktopX;
2155 box.top -= desktopY;
2156 box.right -= desktopX;
2157 box.bottom -= desktopY;