7 import "GuiApplication"
28 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
32 #if !defined(ECERE_VANILLA) && !defined(ECERE_NOTRUETYPE)
41 // Had to define this here for native decorations support, because the menu bar is part of total decoration's size, but not part of the system decorations
42 define skinMenuHeight = 25;
43 define statusBarHeight = 18;
45 default extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
47 public enum DialogResult { cancel, yes, no, ok };
49 public class MouseButtons
52 bool left:1, right:1, middle:1;
55 public struct SizeAnchor
58 bool isClientW, isClientH;
63 #define SNAPDOWN(x, d) \
66 if(x < 0) x -= ((d) - Abs(x) % (d)); else x -= x % (d); \
69 #define SNAPUP(x, d) \
72 if(x > 0) x += ((d) - Abs(x) % (d)); else x += x % (d); \
75 /*static */define MAX_DIRTY_BACK = 10;
77 /////////////////////////////////////////////////////////////////////////////
78 ////////// EXTENT MANIPULATION //////////////////////////////////////////////
79 /////////////////////////////////////////////////////////////////////////////
81 #define ACCESS_ITEM(l, id) \
84 #define FASTLIST_LOOP(l, v) \
85 for(v = (BoxItem)l.first; v; v = (BoxItem)v.next)
87 #define FASTLIST_LOOPN(l, v, n) \
88 for(v = (BoxItem)l.first, n = (BoxItem)(v ? v.next : null); v; v = (BoxItem)next, n = (BoxItem)(v ? v.next : null))
91 #define ACCESS_ITEM(l, id) \
92 ((FastItem)(((id) == -1) ? null : (((byte *)((l).items)) + (id) * (l).itemSize)))
94 #define FASTLIST_LOOP(l, v) \
95 for(v = (void *)ACCESS_ITEM((l), (l).first); v; v = (void *)ACCESS_ITEM((l), v.next))
97 #define FASTLIST_LOOPN(l, v, n) \
98 for( v = (void *)ACCESS_ITEM((l), (l).first), \
99 n = v ? ((void *)ACCESS_ITEM((l), v.next)): null; \
100 v; v = n, n = n ? (void *)ACCESS_ITEM((l), n.next) : null)
103 private class FastItem : struct
108 private struct FastList
113 int count, size, itemSize;
120 first = last = free = -1;
128 // FASTLIST_LOOPN(this, item, next) { Delete(item); };
131 FastItem Add(uint itemSize)
134 if(free == -1 || !size)
141 newSize = (size + (size >> 1));
142 items = (FastItem)renew items byte[newSize * itemSize];
147 this.itemSize = itemSize;
148 items = (FastItem)new byte[newSize * itemSize];
151 for(c = size; c<newSize-1; c++)
153 ACCESS_ITEM(this, c).prev = -1;
154 ACCESS_ITEM(this, c).next = c+1;
156 ACCESS_ITEM(this, c).prev = -1;
157 ACCESS_ITEM(this, c).next = -1;
161 item = ACCESS_ITEM(this, free);
164 ACCESS_ITEM(this, item.prev).next = free;
174 void Delete(FastItem item)
177 ACCESS_ITEM(this, item.prev).next = item.next;
179 ACCESS_ITEM(this, item.next).prev = item.prev;
181 if(ACCESS_ITEM(this, first) == item)
183 if(ACCESS_ITEM(this, last) == item)
188 free = ((byte *)item - (byte *)items) / itemSize;
196 free = first = last = -1;
200 private class BoxItem : Item //FastItem
205 public /*private */struct Extent : OldList //FastList
214 //BoxItem extentBox = (BoxItem)Add(sizeof(class BoxItem));
215 Add(BoxItem { box = box });
218 void Copy(Extent source)
224 //FASTLIST_LOOP(source, extentBox)
225 for(extentBox = (BoxItem)source.first; extentBox; extentBox = (BoxItem)extentBox.next)
226 AddBox(extentBox.box);
229 void IntersectBox(Box box)
231 // Clip all boxes of extent against inside of the new box
232 BoxItem extentBox, next;
234 //FASTLIST_LOOPN(this, extentBox, next) // Macros still mess up the parser!
235 for(extentBox = (BoxItem)this.first; extentBox; extentBox = next)
237 next = (BoxItem)extentBox.next;
238 if(box.left > extentBox.box.left) extentBox.box.left = box.left;
239 if(box.top > extentBox.box.top) extentBox.box.top = box.top;
240 if(box.right < extentBox.box.right) extentBox.box.right = box.right;
241 if(box.bottom < extentBox.box.bottom) extentBox.box.bottom = box.bottom;
242 if(extentBox.box.right < extentBox.box.left || extentBox.box.bottom < extentBox.box.top)
247 void ExcludeBox(Box box, Extent temp)
254 for(extentBox = (BoxItem)temp.first; extentBox; extentBox = (BoxItem)extentBox.next)
256 if(extentBox.box.left < box.right && extentBox.box.right > box.left &&
257 extentBox.box.top < box.bottom && extentBox.box.bottom > box.top)
260 if(extentBox.box.top < box.top && extentBox.box.bottom >= box.top)
264 extentBox.box.left, extentBox.box.top,
265 extentBox.box.right, Min(extentBox.box.bottom, box.top -1)
271 if(extentBox.box.bottom > box.bottom && extentBox.box.top <= box.bottom)
275 extentBox.box.left, Max(extentBox.box.top,box.bottom +1),
276 extentBox.box.right, extentBox.box.bottom
282 if(extentBox.box.bottom >= box.top && extentBox.box.top <= box.bottom)
285 if(extentBox.box.left < box.left && extentBox.box.right >= box.left)
289 extentBox.box.left, Max(extentBox.box.top, box.top),
290 Min(extentBox.box.right, box.left-1), Min(extentBox.box.bottom, box.bottom)
296 if(extentBox.box.right > box.right && extentBox.box.left <= box.right)
300 Max(extentBox.box.left, box.right+1), Max(extentBox.box.top, box.top),
301 extentBox.box.right, Min(extentBox.box.bottom, box.bottom)
309 AddBox(extentBox.box);
315 void UnionBox(Box box, Extent temp)
317 BoxItem extentBox, next;
319 // First pass: check if this box is not already covered by one of the extent's box
320 for(extentBox = (BoxItem)this.first; extentBox; extentBox = (BoxItem)extentBox.next)
322 if(extentBox.box.left <= box.left && extentBox.box.right >= box.right &&
323 extentBox.box.top <= box.top && extentBox.box.bottom >= box.bottom)
330 // Second pass: only keep boxes not completely covered in the new box
331 for(extentBox = (BoxItem)this.first; extentBox; extentBox = next)
333 next = (BoxItem)extentBox.next;
334 if(extentBox.box.left >= box.left && extentBox.box.right <= box.right &&
335 extentBox.box.top >= box.top && extentBox.box.bottom <= box.bottom)
339 // Add the exclusion to the extent
340 ExcludeBox(box, temp);
343 if(box.bottom >= box.top && box.right >= box.left)
345 // Optimization: if the resulting boxes touch, add them smarter
346 for(extentBox = (BoxItem)this.first; extentBox; extentBox = (BoxItem)extentBox.next)
348 if(box.top == extentBox.box.top && box.bottom == extentBox.box.bottom)
350 if(Abs(box.right - extentBox.box.left) <= 1)
352 extentBox.box.left = box.left;
355 else if(Abs(box.left - extentBox.box.right) <= 1)
357 extentBox.box.right = box.right;
361 else if(box.left == extentBox.box.left && box.right == extentBox.box.right)
363 if(Abs(box.bottom - extentBox.box.top) <= 1)
365 extentBox.box.top = box.top;
368 else if(Abs(box.top - extentBox.box.bottom) <= 1)
370 extentBox.box.bottom = box.bottom;
382 void Union(Extent b, Extent temp)
386 for(extentBox = (BoxItem)b.first; extentBox; extentBox = (BoxItem)extentBox.next)
387 UnionBox(extentBox.box, temp);
390 void Intersection(Extent b, Extent temp, Extent temp2, Extent temp3)
397 for(extentBox = (BoxItem)b.first; extentBox; extentBox = (BoxItem)extentBox.next)
400 temp2.IntersectBox(extentBox.box);
407 void Exclusion(Extent b, Extent temp)
410 for(extentBox = (BoxItem)b.first; extentBox; extentBox = (BoxItem)extentBox.next)
411 ExcludeBox(extentBox.box, temp);
414 void Offset(int x, int y)
417 for(extentBox = (BoxItem)this.first; extentBox; extentBox = (BoxItem)extentBox.next)
419 extentBox.box.left += x;
420 extentBox.box.top += y;
421 extentBox.box.right += x;
422 extentBox.box.bottom += y;
427 private define MINIMIZED_WIDTH = 160;
428 private define CASCADE_SPACE = 16;
430 // namespace Windows;
432 private class ScrollFlags
434 bool snapX:1, snapY:1, dontHide:1;
437 public class BorderBits { public: bool contour:1, fixed:1, sizable:1, deep:1, bevel:1, thin:1; };
439 class WindowBits : BorderBits
441 BorderBits borderBits:6:0;
442 bool hidden:1, isActiveClient:1, hasHorzScroll:1, hasVertScroll:1, stayOnTop:1, modal:1, isDefault:1, inactive:1, isRemote:1, drawBehind:1;
443 bool interim:1, tabCycle:1, noCycle:1, dontScrollHorz:1, dontScrollVert:1, hasMaximize:1, hasMinimize:1, hasClose:1;
444 bool embedded:1, hasMenuBar:1, isDocument:1, showInTaskBar:1, hasStatusBar:1, nonClient:1, clickThrough:1;
447 public enum BorderStyle : BorderBits
450 contour = BorderBits { contour = true },
451 fixed = BorderBits { fixed = true } | contour,
452 sizable = BorderBits { sizable = true } | fixed,
453 thin = BorderBits { fixed = true, thin = true } | contour,
454 sizableThin = BorderBits { sizable = true } | thin,
455 deep = BorderBits { deep = true },
456 bevel = BorderBits { bevel = true },
457 sizableDeep = sizable|deep,
458 sizableBevel = sizable|bevel,
459 fixedDeep = fixed|deep,
460 fixedBevel = fixed|bevel,
461 deepContour = deep|contour
464 public enum CreationActivationOption
466 activate, flash, doNothing
469 public enum WindowState { normal, minimized, maximized };
471 private class ResPtr : struct
478 private class HotKeySlot : struct
480 HotKeySlot prev, next;
488 class_data char * icon;
490 class_default_property caption;
491 // class_initialize GuiApplication::Initialize;
492 class_designer FormDesigner;
493 class_property char * icon
495 set { class_data(icon) = value; }
496 get { return class_data(icon); }
501 if(guiApp) guiApp.Initialize(true);
503 if(guiApp && guiApp.currentSkin && ((subclass(Window))_class).pureVTbl)
505 if(_vTbl == ((subclass(Window))_class).pureVTbl)
507 _vTbl = _class._vTbl;
509 else if(_vTbl != _class._vTbl)
512 for(m = 0; m < _class.vTblSize; m++)
514 if(_vTbl[m] == ((subclass(Window))_class).pureVTbl[m])
515 _vTbl[m] = _class._vTbl[m];
520 //tempExtents[0] = { /*first = -1, last = -1, free = -1*/ };
521 //tempExtents[1] = { /*first = -1, last = -1, free = -1*/ };
522 //tempExtents[2] = { /*first = -1, last = -1, free = -1*/ };
523 //tempExtents[3] = { /*first = -1, last = -1, free = -1*/ };
527 // caption = CopyString(class.name);
529 children.offset = (byte*)&prev - (byte*)this;
530 childrenOrder.circ = true;
531 childrenCycle.circ = true;
533 maxSize = Size { MAXINT, MAXINT };
537 //style.isActiveClient = true;
540 modifyVirtArea = true;
541 manageDisplay = true;
542 nativeDecorations = true;
544 // scrollFlags = ScrollFlags { snapX = true, snapY = true };
545 sbStep.x = sbStep.y = 8;
547 if(guiApp) // dynamic_cast<GuiApplication>(thisModule)
549 cursor = guiApp.GetCursor(arrow);
550 property::parent = guiApp.desktop;
562 stopwatching(parent, font);
563 if(parent.activeChild == this)
564 parent.activeChild = null;
565 if(parent.activeClient == this)
566 parent.activeClient = null;
571 // Prevent destructor from being called again...
577 /////////////////////////////////
580 OldLink slave = master.slaves.FindLink(this);
581 master.slaves.Delete(slave);
588 parent.childrenCycle.Remove(cycle);
590 parent.childrenOrder.Remove(order);
591 parent.children.Remove(this);
596 /////////////////////////////////
598 while(ptr = resources.first)
601 resources.Delete(ptr);
608 for(child = children.first; child; child = child.next)
610 // child.stopwatching(this, font);
612 eInstance_StopWatching(this, __ecereProp___ecereNameSpace__ecere__gui__Window_font, child);
613 // Don't want property here
614 *&child.parent = null;
617 while(slave = slaves.first)
619 // Don't want property here
620 *&((Window)slave.data).master = null;
621 slaves.Delete(slave);
624 // Because we do a decref in DestroyEx...
632 // Why was this commented?
633 //if(this != guiApp.desktop)
646 if(((subclass(Window))_class).pureVTbl)
648 if(_vTbl == _class._vTbl)
650 _vTbl = ((subclass(Window))_class).pureVTbl;
655 for(m = 0; m < _class.vTblSize; m++)
657 if(_vTbl[m] == _class._vTbl[m])
658 _vTbl[m] = ((subclass(Window))_class).pureVTbl[m];
662 if(_vTbl == ((subclass(Window))_class).pureVTbl || _vTbl == _class._vTbl)
665 dirtyArea.Free(null);
666 renderArea.Free(null);
667 overRenderArea.Free(null);
668 clipExtent.Free(null);
669 scrollExtent.Free(null);
670 dirtyBack.Free(null);
674 tempExtents[0].Free(null);
675 tempExtents[1].Free(null);
676 tempExtents[2].Free(null);
677 tempExtents[3].Free(null);
682 //#if !defined(ECERE_VANILLA)
683 char * OnGetString(char * stringOutput, void * fieldData, bool * needClass)
685 if(this == activeDesigner)
689 char * name = property::name;
690 return name ? name : "";
695 #if !defined(ECERE_VANILLA) && !defined(ECERE_NOTRUETYPE)
696 bool OnGetDataFromString(char * string)
698 FormDesigner designer = (FormDesigner)activeDesigner.classDesigner;
701 if(!strcmp(string, "this") || !strcmp(string, designer.form.name))
702 this = designer.form;
703 else if(!strcmpi(string, "(Desktop)"))
704 this = activeDesigner;
706 return activeDesigner.FindObject(&this, string);
712 // --- Window updates system ---
714 // Setup a bitmap for Redrawing on client area of Window
715 Surface Redraw(Box box)
717 Surface surface = null;
719 Box clientArea = this.clientArea;
723 mox.left -= clientStart.x;
724 mox.top -= clientStart.y;
725 mox.right -= clientStart.x;
726 mox.bottom -= clientStart.y;
728 mox.Clip(clientArea);
729 // mox.ClipOffset(against, scrolledPos.x, scrolledPos.y);
731 if((!guiApp.fullScreenMode || guiApp.desktop.active) && display && mox.right >= mox.left && mox.bottom >= mox.top)
733 int x = absPosition.x + clientStart.x;
734 int y = absPosition.y + clientStart.y;
735 if(rootWindow.nativeDecorations)
737 x -= rootWindow.clientStart.x;
738 y -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
740 if(!guiApp.fullScreenMode || is3D)
742 x -= rootWindow.absPosition.x;
743 y -= rootWindow.absPosition.y;
747 x += rootWindow.parent.clientStart.x;
748 y += rootWindow.parent.clientStart.y;
750 mox.left += rootWindow.parent.clientStart.x;
751 mox.top += rootWindow.parent.clientStart.y;
752 mox.right += rootWindow.parent.clientStart.x;
753 mox.bottom += rootWindow.parent.clientStart.y;
758 surface = display.GetSurface(x, y, mox);
761 surface.width = clientSize.w;
762 surface.height = clientSize.h;
768 // Setup a bitmap for Redrawing on full Window
769 Surface RedrawFull(Box box)
771 Surface surface = null;
779 if((!guiApp.fullScreenMode || guiApp.desktop.active) && display && box.right >= box.left && box.bottom >= box.top)
781 int x = absPosition.x;
782 int y = absPosition.y;
783 if(rootWindow.nativeDecorations)
785 x -= rootWindow.clientStart.x;
786 y -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
788 if(!guiApp.fullScreenMode || is3D)
790 x -= rootWindow.absPosition.x;
791 y -= rootWindow.absPosition.y;
794 x += rootWindow.parent.clientStart.x;
795 y += rootWindow.parent.clientStart.y;
797 mox.left += rootWindow.parent.clientStart.x;
798 mox.top += rootWindow.parent.clientStart.y;
799 mox.right += rootWindow.parent.clientStart.x;
800 mox.bottom += rootWindow.parent.clientStart.y;
805 surface = display.GetSurface(x, y, mox);
808 surface.width = size.w;
809 surface.height = size.h;
815 void FigureCaption(char * caption)
817 Window activeClient = null;
821 strcpy(caption, this.caption);
822 if(style.isDocument || fileName)
824 if(caption[0]) strcat(caption, " - ");
826 strcat(caption, fileName);
830 sprintf(title, "Untitled %d", documentID);
831 strcat(caption, title);
834 strcat(caption, " *");
839 for(activeClient = this.activeClient; activeClient && !((BorderBits)activeClient.borderStyle).fixed; activeClient = activeClient.activeClient);
841 if(activeClient && activeClient.state == maximized)
843 if(activeClient.caption)
845 if(caption[0]) strcat(caption, " - ");
846 strcat(caption, activeClient.caption);
848 if(activeClient.style.isDocument || activeClient.fileName)
850 if(caption[0]) strcat(caption, " - ");
851 strcat(caption, "[");
852 if(activeClient.fileName)
853 strcat(caption, activeClient.fileName);
857 sprintf(title, "Untitled %d", activeClient.documentID);
858 strcat(caption, title);
860 if(activeClient.modifiedDocument)
861 strcat(caption, " *");
862 strcat(caption, "]");
867 // Code for returning dirty from ScrollDisplay:
869 for(d = 0; d<scrollExtent.count; d++)
871 Box * box = &scrollExtent.boxes[d];
877 Min(box.right, box.left-scroll.x),box.bottom
879 dirtyArea.UnionBox(update);
885 Max(box.left, box.right-scroll.x), box.top,
886 box.right, box.bottom
888 dirtyArea.UnionBox(update);
896 box.right, Min(box.bottom, box.top-scroll.y),
898 dirtyArea.UnionBox(update);
904 box.left, Max(box.top, box.bottom-scroll.y),
905 box.right, box.bottom
907 dirtyArea.UnionBox(update);
912 void UpdateDecorations(void)
914 // TODO: *** TEMPORARY HACK ***
921 Update({ -clientStart.x, -clientStart.y, -clientStart.x + size.w-1, 0 });
923 Update({ -clientStart.x, clientSize.h, -clientStart.x + size.w-1, -clientStart.y + size.h-1 });
925 Update({ -clientStart.x,0, -1, clientSize.h-1 });
927 Update({ clientSize.w, 0, -clientStart.x + size.w-1, clientSize.h-1 });
930 // Returns w & h for Position
931 void ComputeAnchors(Anchor anchor, SizeAnchor sizeAnchor, int *ox, int *oy, int *ow, int *oh)
933 Window parent = this.parent ? this.parent : guiApp.desktop;
934 int vpw = parent ? parent.clientSize.w : 0;
935 int vph = parent ? parent.clientSize.h : 0;
936 int pw = parent ? parent.clientSize.w : 0;
937 int ph = parent ? parent.clientSize.h : 0;
938 int w = sizeAnchor.size.w, h = sizeAnchor.size.h;
939 int x = anchor.left.distance, y = anchor.top.distance;
941 MinMaxValue ew = 0, eh = 0;
943 float cascadeW, cascadeH;
945 int tilingW, tilingH, tilingSplit, tilingLastH;
946 int addX = 0, addY = 0;
948 if(parent && rootWindow == this && guiApp && guiApp.interfaceDriver)
950 Window masterWindow = this;
951 Box box { addX, addY, addX + vpw - 1, addY + vph - 1 };
954 if(master == guiApp.desktop)
955 masterWindow = guiApp.desktop.activeChild;
957 masterWindow = master.rootWindow;
958 if(!masterWindow) masterWindow = this;
960 guiApp.interfaceDriver.GetScreenArea(masterWindow, box);
961 if((anchor.left.type == offset && anchor.right.type == offset) || anchor.left.type == none)
964 pw = vpw = box.right - box.left + 1;
966 if((anchor.top.type == offset && anchor.bottom.type == offset) || anchor.top.type == none)
969 ph = vph = box.bottom - box.top + 1;
985 vpw = pw = parent.size.w;
986 vph = ph = parent.size.h;
988 else if(!style.fixed /*|| style.isDocument*/)
990 if(!style.dontScrollHorz && parent.scrollArea.w) vpw = parent.scrollArea.w;
991 if(!style.dontScrollVert && parent.scrollArea.h) vph = parent.scrollArea.h;
993 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
996 Desktop3D_FixSize(&pw, &ph);
997 Desktop3D_FixSize(&vpw, &vph);
1000 if(pw < skinMinSize.w) pw = skinMinSize.w;
1001 if(ph < skinMinSize.h) ph = skinMinSize.h;
1002 if(vpw < skinMinSize.w) vpw = skinMinSize.w;
1003 if(vph < skinMinSize.h) vph = skinMinSize.h;
1005 // TODO: Must fix what we're snapping
1008 if(anchor.left.type)
1010 SNAPUP(x, textCellW);
1012 else if(anchor.right.type)
1014 SNAPDOWN(x, textCellW);
1019 SNAPUP(y, textCellH);
1021 else if(anchor.bottom.type)
1023 SNAPDOWN(y, textCellH);
1027 // This is required to get proper initial decoration size using native decorations on Windows
1028 if(nativeDecorations && guiApp && guiApp.interfaceDriver && !visible)
1029 guiApp.interfaceDriver.PositionRootWindow(this, x, y, Max(1, size.w), Max(1, size.h), true, true);
1030 GetDecorationsSize(&ew, &eh);
1032 if(anchor.left.type >= cascade && (state == normal /*|| state == Hidden*/))
1034 if(parent.sbv && !parent.sbv.style.hidden)
1035 pw += guiApp.currentSkin.VerticalSBW();
1036 if(parent.sbh && !parent.sbh.style.hidden)
1037 ph += guiApp.currentSkin.HorizontalSBH();
1039 if(anchor.left.type == cascade)
1041 w = (int)(pw * 0.80);
1042 h = (int)(ph * 0.80);
1044 else if(anchor.left.type >= vTiled)
1049 numTiling = parent.numPositions - parent.numIcons;
1050 if(parent.numIcons) ph -= guiApp.textMode ? 16 : 24;
1051 if(anchor.left.type == vTiled)
1053 tilingH = (int)sqrt(numTiling);
1054 tilingW = numTiling / tilingH;
1058 tilingW = (int)sqrt(numTiling);
1059 tilingH = numTiling / tilingW;
1062 leftOver = numTiling - tilingH * tilingW;
1065 tilingSplit = (tilingW - leftOver) * tilingH;
1066 tilingLastH = tilingH+1;
1069 tilingSplit = numTiling;
1071 if(positionID >= tilingSplit)
1073 x = pw * (tilingSplit / tilingH + (positionID - tilingSplit) / tilingLastH)/tilingW;
1074 y = ph * ((positionID - tilingSplit) % tilingLastH) / tilingLastH;
1075 x2 = pw * (tilingSplit/tilingH + (positionID - tilingSplit) / tilingLastH + 1)/tilingW;
1076 y2 = ph * (((positionID - tilingSplit) % tilingLastH) + 1) / tilingLastH;
1080 x = pw * (positionID / tilingH) / tilingW;
1081 y = ph * (positionID % tilingH) / tilingH;
1082 x2 = pw * (positionID / tilingH + 1) / tilingW;
1083 y2 = ph * ((positionID % tilingH) + 1) / tilingH;
1087 SNAPDOWN(x, textCellW);
1088 SNAPDOWN(y, textCellH);
1089 SNAPDOWN(x2, textCellW);
1090 SNAPDOWN(y2, textCellH);
1098 if(sizeAnchor.isClientW) w += ew;
1099 if(sizeAnchor.isClientH) h += eh;
1101 if(anchor.left.type == offset)
1102 x = anchor.left.distance;
1103 else if(anchor.left.type == relative)
1104 x = (anchor.left.percent < 0) ? ((int)(vpw * anchor.left.percent - 0.5)) : (int)(vpw * anchor.left.percent + 0.5);
1105 else if(anchor.right.type == relative)
1106 // ex = (anchor.right.percent < 0) ? ((int)(vpw * anchor.right.percent + 0)) : ((int)(vpw * anchor.right.percent + 0));
1107 ex = (anchor.right.percent < 0) ? ((int)(vpw * (1.0-anchor.right.percent) + 0)) : ((int)(vpw * (1.0-anchor.right.percent) + 0));
1108 else if(anchor.right.type == offset)
1109 ex = vpw - anchor.right.distance;
1111 if(anchor.top.type == offset)
1112 y = anchor.top.distance;
1113 else if(anchor.top.type == relative)
1114 y = (anchor.top.percent < 0) ? ((int)(vph * anchor.top.percent - 0.5)) : ((int)(vph * anchor.top.percent + 0.5));
1115 else if(anchor.bottom.type == relative)
1116 //ey = (anchor.bottom.percent < 0) ? ((int)(vph * anchor.bottom.percent + 0)) : ((int)(vph * anchor.bottom.percent + 0));
1117 ey = (anchor.bottom.percent < 0) ? ((int)(vph * (1.0-anchor.bottom.percent) + 0)) : ((int)(vph * (1.0-anchor.bottom.percent) + 0));
1118 else if(anchor.bottom.type == offset)
1119 ey = vph - anchor.bottom.distance;
1121 if(anchor.left.type && anchor.right.type)
1123 switch(anchor.right.type)
1126 ex = pw * (1.0f-anchor.right.percent);
1127 w = Max((int)(ex + 0.5) - x, 0);
1130 ex = vpw - anchor.right.distance;
1131 w = Max((int)(ex + 0.5) - x, 0);
1135 if(anchor.top.type && anchor.bottom.type)
1137 switch(anchor.bottom.type)
1140 ey = ph * (1.0f-anchor.bottom.percent);
1141 h = Max((int)(ey + 0.5) - y, 0);
1144 ey = vph - anchor.bottom.distance;
1145 h = Max((int)(ey + 0.5) - y, 0);
1154 if(state == normal /*|| state == Hidden*/)
1156 bool addSbV = false, addSbH = false;
1158 if(sizeAnchor.isClientW || (anchor.left.type && anchor.right.type)) w = Max(w, 1); else w = Max(w, 0);
1159 if(sizeAnchor.isClientH || (anchor.top.type && anchor.bottom.type)) h = Max(h, 1); else h = Max(h, 0);
1161 w = Max(w, minSize.w);
1162 h = Max(h, minSize.h);
1163 w = Min(w, maxSize.w);
1164 h = Min(h, maxSize.h);
1166 if((sizeAnchor.isClientW || !w || (anchor.left.type && anchor.right.type)) && reqScrollArea.h > h /*&& w*/ && sbv)
1168 if(w) w -= guiApp.currentSkin.VerticalSBW();
1171 if((sizeAnchor.isClientH || !h || (anchor.top.type && anchor.bottom.type)) && reqScrollArea.w > w /*&& h*/ && sbh)
1173 if(h) h -= guiApp.currentSkin.HorizontalSBH();
1177 if(!OnResizing(&w, &h))
1183 if((addSbV)) // || reqScrollArea.h > h) && sbv)
1184 w += guiApp.currentSkin.VerticalSBW();
1185 if((addSbH)) // || reqScrollArea.w > w) && sbh)
1186 h += guiApp.currentSkin.HorizontalSBH();
1188 w = Max(w, skinMinSize.w);
1189 h = Max(h, skinMinSize.h);
1202 SNAPDOWN(w, textCellW);
1203 SNAPDOWN(h, textCellH);
1206 if(anchor.left.type == cascade && (state == normal /*|| state == Hidden*/))
1208 if(parent.numIcons) ph -= guiApp.textMode ? 16 : 24;
1211 (pw - w) / CASCADE_SPACE,
1212 (ph - h) / CASCADE_SPACE);
1218 cascW = (pw - w) / (numCascade-1);
1219 cascH = (ph - h) / (numCascade-1);
1220 SNAPDOWN(cascW, textCellW);
1221 SNAPDOWN(cascH, textCellH);
1222 cascadeW = (float)cascW;
1223 cascadeH = (float)cascH;
1227 numCascade = Max(numCascade, 2);
1228 cascadeW = (float)(pw - w) / (numCascade-1);
1229 cascadeH = (float)(ph - h) / (numCascade-1);
1232 x = (int)((positionID % numCascade) * cascadeW);
1233 y = (int)((positionID % numCascade) * cascadeH);
1235 else if(anchor.left.type < vTiled)
1237 if(!anchor.left.type || anchor.horz.type == middleRelative)
1239 if(!anchor.right.type)
1241 if(anchor.horz.type == middleRelative)
1242 x = (int)(vpw * (0.5 + anchor.horz.percent) - w / 2);
1244 x = vpw / 2 + anchor.horz.distance - w / 2;
1250 // case A_EDGE: x = x - w; break;
1252 if(!anchor.top.type || anchor.vert.type == middleRelative)
1254 if(!anchor.bottom.type)
1256 if(anchor.vert.type == middleRelative)
1257 y = (int)(vph * (0.5 + anchor.vert.percent) - h / 2);
1259 y = vph / 2 + anchor.vert.distance - h / 2;
1265 // case A_EDGE: y = y - h; break;
1268 if((state == normal /*|| state == Hidden*/) && !OnMoving(&x, &y, w, h))
1276 SNAPDOWN(x, textCellW);
1277 SNAPDOWN(y, textCellH);
1289 if(anchored && style.fixed && style.isActiveClient)
1294 void UpdateCaret(bool forceUpdate, bool erase)
1296 static Window lastWindow = null;
1297 static int caretX, caretY, caretSize;
1299 if(guiApp && guiApp.caretOwner == this)
1301 int x = caretPos.x - scroll.x;
1302 int y = caretPos.y - scroll.y;
1304 if((erase || this.caretSize) &&
1305 x >= clientArea.left && x <= clientArea.right &&
1306 y >= clientArea.top && y <= clientArea.bottom)
1310 guiApp.interfaceDriver.SetCaret(
1311 x + absPosition.x + clientStart.x,
1312 y + absPosition.y + clientStart.y, this.caretSize);
1313 guiApp.caretEnabled = true;
1315 if(erase || lastWindow != this || caretX != x || caretY != y || caretSize != this.caretSize || forceUpdate)
1319 if(lastWindow != this)
1321 updateBox.left = x + 1;
1323 updateBox.right = x + 2;
1324 updateBox.bottom = y + this.caretSize - 1;
1328 updateBox.left = Min(x + 1, caretX + 1);
1329 updateBox.top = Min(y, caretY);
1330 updateBox.right = Max(x + 2, caretX + 2);
1331 updateBox.bottom = Max(y + this.caretSize - 1, caretY + caretSize - 1);
1334 guiApp.caretOwner.Update(updateBox);
1341 caretSize = this.caretSize;
1347 guiApp.interfaceDriver.SetCaret(0,0,0);
1348 guiApp.caretEnabled = false;
1354 void SetPosition(int x, int y, int w, int h, bool modifyArea, bool modifyThisArea, bool modifyClientArea)
1359 scrolledPos.x = position.x = x;
1360 scrolledPos.y = position.y = y;
1362 clientSize.w = size.w = w;
1363 clientSize.h = size.h = h;
1365 if(parent && !style.nonClient)
1367 //if(!style.fixed || style.isDocument)
1369 if(!style.dontScrollHorz) scrolledPos.x -= parent.scroll.x;
1370 if(!style.dontScrollVert) scrolledPos.y -= parent.scroll.y;
1374 clientStart.x = clientStart.y = 0;
1376 SetWindowArea(&clientStart.x, &clientStart.y, &size.w, &size.h, &clientSize.w, &clientSize.h);
1378 //if(!activeClient || activeClient.state != maximized)
1379 if(!noAutoScrollArea)
1381 // Check if scroll area must be modified
1382 if(guiApp && !guiApp.modeSwitching && (sbv || sbh))
1384 bool foundChild = false;
1386 int cw = clientSize.w;// + ((!sbv || sbv.range > 1) ? guiApp.currentSkin.VerticalSBW() : 0);
1387 int ch = clientSize.h;// + ((!sbh || sbh.rangw > 1) ? guiApp.currentSkin.HorizontalSBH() : 0);
1388 for(child = children.first; child; child = child.next)
1390 if(child.modifyVirtArea && !child.style.hidden && child.created && /*!child.anchored &&*/
1391 !child.style.dontScrollHorz && !child.style.dontScrollVert && !child.style.nonClient)
1393 if(child.stateAnchor.right.type == none && child.stateAnchor.left.type == offset)
1394 w = Max(w, child.position.x + child.size.w);
1395 else if(child.stateAnchor.right.type == none && child.stateAnchor.left.type == none)
1396 w = Max(w, Max(child.position.x, 0) + child.size.w);
1397 if(child.stateAnchor.bottom.type == none && child.stateAnchor.top.type == offset)
1398 h = Max(h, child.position.y + child.size.h);
1399 else if(child.stateAnchor.bottom.type == none && child.stateAnchor.top.type == none)
1400 h = Max(h, Max(child.position.y, 0) + child.size.h);
1405 if(foundChild && (w > cw || h > ch))
1407 //if((w > reqScrollArea.w) || (h > reqScrollArea.w))
1409 int stepX = sbStep.x, stepY = sbStep.y;
1410 // Needed to make snapped down position match the skin's check of client area
1411 // against realvirtual
1414 SNAPDOWN(stepX, textCellW);
1415 SNAPDOWN(stepY, textCellH);
1416 stepX = Max(stepX, textCellW);
1417 stepY = Max(stepY, textCellH);
1419 if(scrollFlags.snapX)
1421 if(scrollFlags.snapY)
1424 reqScrollArea.w = w;
1425 reqScrollArea.h = h;
1428 else if(reqScrollArea.w || reqScrollArea.h)
1430 reqScrollArea.w = 0;
1431 reqScrollArea.h = 0;
1432 SetScrollPosition(0,0);
1437 // Automatic MDI Client Scrolling Area Adjustment
1438 if(parent && !parent.noAutoScrollArea)
1440 if(modifyArea && modifyVirtArea /*&& !anchored*/ && (parent.sbv || parent.sbh) &&
1441 !style.dontScrollHorz && !style.dontScrollVert && !style.nonClient)
1443 Window parent = this.parent;
1444 int w = parent.reqScrollArea.w;
1445 int h = parent.reqScrollArea.h;
1447 if(stateAnchor.right.type == none && stateAnchor.left.type == offset)
1448 w = Max(w, position.x + size.w);
1449 else if(stateAnchor.right.type == none && stateAnchor.left.type == none)
1450 w = Max(w, Max(position.x, 0) + size.w);
1451 if(stateAnchor.bottom.type == none && stateAnchor.top.type == offset)
1452 h = Max(h, position.y + size.h);
1453 else if(stateAnchor.bottom.type == none && stateAnchor.top.type == none)
1454 h = Max(h, Max(position.y, 0) + size.h);
1456 if((w > parent.clientSize.w && w > parent.reqScrollArea.w) ||
1457 (h > parent.clientSize.h && h > parent.reqScrollArea.h))
1459 /*bool resize = false;
1460 int stepX = parent.sbStep.x, stepY = parent.sbStep.y;
1461 // Needed to make snapped down position match the skin's check of client area
1462 // against realvirtual
1465 SNAPDOWN(stepX, textCellW);
1466 SNAPDOWN(stepY, textCellH);
1467 stepX = Max(stepX, textCellW);
1468 stepY = Max(stepY, textCellH);
1470 if(parent.scrollFlags.snapX)
1472 if(parent.scrollFlags.snapY)
1474 if(parent.reqScrollArea.w != w || parent.reqScrollArea.h != h)
1476 parent.reqScrollArea.w = w;
1477 parent.reqScrollArea.h = h;*/
1479 // parent.UpdateScrollBars(true, true);
1480 parent.Position(parent.position.x, parent.position.y, parent.size.w, parent.size.h,
1481 false, true, true, true, false, false);
1486 GetRidOfVirtualArea();
1490 UpdateScrollBars(modifyThisArea, false);
1491 else if(guiApp.currentSkin)
1494 &clientStart.x, &clientStart.y, &size.w, &size.h, &clientSize.w, &clientSize.h);
1496 if(sbv && (scrollFlags.dontHide || sbv.range > 1))
1497 clientSize.w -= guiApp.currentSkin.VerticalSBW();
1498 if(sbh && (scrollFlags.dontHide || sbh.range > 1))
1499 clientSize.h -= guiApp.currentSkin.HorizontalSBH();
1502 scrollArea.w = Max(clientSize.w, reqScrollArea.w);
1503 scrollArea.h = Max(clientSize.h, reqScrollArea.h);
1505 absPosition = scrolledPos;
1506 if(guiApp && guiApp.driver != null && guiApp.interfaceDriver)
1507 guiApp.interfaceDriver.OffsetWindow(this, &absPosition.x, &absPosition.y);
1509 if(this != guiApp.desktop && parent)
1511 absPosition.x += parent.absPosition.x;
1512 absPosition.y += parent.absPosition.y;
1513 if(!style.nonClient && this != guiApp.desktop)
1515 absPosition.x += parent.clientStart.x;
1516 absPosition.y += parent.clientStart.y;
1520 box = Box { 0, 0, size.w - 1, size.h - 1 };
1525 // Clip against parent's client area
1526 box.ClipOffset(against, scrolledPos.x, scrolledPos.y);
1528 // Compute client area in this window coordinate system
1529 clientArea.left = 0;
1531 clientArea.right = clientSize.w - 1;
1532 clientArea.bottom = clientSize.h - 1;
1534 // Clip against parent's client area
1536 clientArea.ClipOffset(against, scrolledPos.x + clientStart.x, scrolledPos.y + clientStart.y);
1540 //absPosition.x -= parent.clientStart.x;
1541 //absPosition.y -= parent.clientStart.y;
1544 // Adjust all children
1545 for(child = children.first; child; child = child.next)
1546 child.SetPosition(child.position.x, child.position.y, child.size.w, child.size.h, false, true, true);
1548 UpdateCaret(false, false);
1551 void GetRidOfVirtualArea(void)
1553 if(parent && !parent.destroyed && style.fixed &&
1554 !style.dontScrollHorz && !style.dontScrollVert && !style.nonClient &&
1555 parent.reqScrollArea.w && parent.reqScrollArea.h)
1557 if(!parent.noAutoScrollArea)
1561 for(child = children.first; child; child = child.next)
1563 if(child.modifyVirtArea && !child.style.dontScrollHorz && !child.style.dontScrollVert && !child.style.nonClient)
1565 if(child.position.x + child.size.w > parent.clientSize.w + ((!parent.sbv || parent.sbv.style.hidden) ? 0 : guiApp.currentSkin.VerticalSBW()) ||
1566 child.position.y + child.size.h > parent.clientSize.h + ((!parent.sbh || parent.sbh.style.hidden) ? 0 : guiApp.currentSkin.HorizontalSBH()))
1575 Window parent = this.parent;
1577 parent.position.x, parent.position.y, parent.size.w, parent.size.h,
1578 false, true, true, true, false, false);
1580 parent.SetScrollArea(0,0,true);
1581 parent.SetScrollPosition(0,0);
1587 public void ExternalPosition(int x, int y, int w, int h)
1589 Position(x, y, w, h, false, true, true, true, false, false);
1592 // (w, h): Full window size
1593 bool Position(int x, int y, int w, int h, bool force, bool processAnchors, bool modifyArea, bool updateScrollBars, bool thisOnly, bool changeRootWindow)
1595 bool result = false;
1596 int oldCW = clientSize.w, oldCH = clientSize.h;
1597 bool clientResized, windowResized, windowMoved;
1599 bool realResized = size.w != w || size.h != h;
1601 // TOCHECK: This wasn't in ecere.dll
1602 //if(!parent) return true;
1603 if(destroyed) return false;
1605 windowMoved = position.x != x || position.y != y || force;
1607 // windowResized = realResized || force;
1608 windowResized = size.w != w || size.h != h || force;
1610 if(rootWindow != this && display && !display.flags.flipping && scrolledPos.x != MININT)
1616 scrolledPos.x - parent.clientStart.x + this.box.left, scrolledPos.y - parent.clientStart.y + this.box.top,
1617 scrolledPos.x - parent.clientStart.x + this.box.right,
1618 scrolledPos.y - parent.clientStart.y + this.box.bottom
1624 Box box { scrolledPos.x + this.box.left, scrolledPos.y + this.box.top, scrolledPos.x + this.box.right, scrolledPos.y + this.box.bottom};
1629 SetPosition(x, y, w, h, true, modifyArea, updateScrollBars);
1631 clientResized = oldCW != clientSize.w || oldCH != clientSize.h || force;
1632 if(clientResized && this == rootWindow && nativeDecorations)
1633 windowResized = true;
1635 if(display && rootWindow != this)
1638 if(guiApp && guiApp.windowMoving)
1640 if(guiApp.windowMoving.style.nonClient)
1641 guiApp.windowMoving.parent.SetMouseRangeToWindow();
1643 guiApp.windowMoving.parent.SetMouseRangeToClient();
1653 // Buttons bitmap resources crash if we do this while switching mode
1654 if(!guiApp || !guiApp.modeSwitching)
1657 // Process Anchored Children
1661 for(child = children.first; child; child = child.next)
1664 ((child.stateAnchor.left.type != offset ||
1665 child.stateAnchor.top.type != offset ||
1666 child.stateAnchor.right.type != none ||
1667 child.stateAnchor.bottom.type != none) ||
1668 child.state == maximized || child.state == minimized))
1670 child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor,
1672 // child.Position(x, y, w, h, false, true, true, true, false);
1673 // This must be true cuz otherwise we're gonna miss everything since we SetPosition recursively already
1674 child.Position(x, y, w, h, true, true, true, true, false, true /*false*/);
1680 // Is this gonna cause other problems? Commented out for the FileDialog end bevel bug
1681 //if(updateScrollBars)
1683 OnResize(clientSize.w, clientSize.h);
1685 if((clientResized || windowMoved) && created)
1686 OnPosition(position.x, position.y, clientSize.w, clientSize.h);
1688 if(guiApp.interimWindow && guiApp.interimWindow.master.rootWindow == this)
1690 Window master = guiApp.interimWindow.master;
1691 master.OnPosition(master.position.x, master.position.y, master.clientSize.w, master.clientSize.h);
1694 if(rootWindow == this && !is3D)
1698 x -= guiApp.desktop.absPosition.x;
1699 y -= guiApp.desktop.absPosition.y;
1701 //guiApp.Log("Position %s\n", caption);
1702 if(windowResized || windowMoved)
1703 if(display && !display.flags.memBackBuffer && changeRootWindow)
1704 guiApp.interfaceDriver.PositionRootWindow(this, x, y, w, h, windowMoved, windowResized); //realResized);
1706 if(!guiApp.fullScreenMode && this != guiApp.desktop && (windowResized || windowMoved))
1707 for(child = parent.children.first; child && child != this; child = child.next)
1708 if(child.rootWindow)
1709 guiApp.interfaceDriver.UpdateRootWindow(child.rootWindow);
1713 if(windowMoved || windowResized)
1715 display.Lock(true /*false*/);
1718 display.Position(absPosition.x, absPosition.y);
1719 //display.Position(absPosition.x + clientStart.x, absPosition.y + clientStart.y);
1722 // result = realResized ? display.Resize(size.w, size.h) : true;
1723 if(nativeDecorations)
1725 int w = clientSize.w, h = clientSize.h;
1726 if(hasMenuBar) h += skinMenuHeight;
1727 if(hasStatusBar) h += statusBarHeight;
1728 if(sbv && sbv.visible) w += sbv.size.w;
1729 if(sbh && sbh.visible) h += sbh.size.h;
1730 result = manageDisplay ? display.Resize(w, h) : true;
1733 result = manageDisplay ? display.Resize(size.w, size.h) : true;
1737 else if(clientResized)
1739 // --- Major Slow Down / Fix OpenGL Resizing Main Window Lag
1742 if(!guiApp.fullScreenMode && !guiApp.modeSwitching && this == rootWindow)
1746 if(windowMoved || windowResized)
1751 if(guiApp.driver && changeRootWindow)
1753 if(windowResized || windowMoved)
1754 if(!display || display.flags.memBackBuffer)
1755 guiApp.interfaceDriver.PositionRootWindow(this,
1756 x, y, w, h, windowMoved, windowResized);
1757 guiApp.interfaceDriver.UpdateRootWindow(this);
1759 for(child = children.first; child; child = child.next)
1761 if(child.is3D && child.created)
1763 // Copy Display Content
1764 child.display.displaySystem = display.displaySystem;
1765 child.display.window = display.window;
1766 child.display.current = display.current;
1767 child.display.width = display.width;
1768 child.display.height = display.height;
1769 child.display.driverData = display.driverData;
1770 child.display.mutex = null;
1781 void UpdateScrollBars(bool flag, bool fullThing)
1784 bool resizeH = false, resizeV = false;
1785 bool scrolled = false;
1786 rvw = (activeChild && activeChild.state == maximized) ? 0 : reqScrollArea.w;
1787 rvh = (activeChild && activeChild.state == maximized) ? 0 : reqScrollArea.h;
1789 if(destroyed) return;
1790 if(guiApp.currentSkin)
1792 MinMaxValue cw = 0, ch = 0;
1793 bool sbvVisible, sbhVisible;
1795 int positionH, positionV;
1797 // First get client area with no respect to scroll bars
1802 &clientStart.x, &clientStart.y, &size.w, &size.h, &cw, &ch);
1804 if(scrollFlags.dontHide)
1807 cw -= guiApp.currentSkin.VerticalSBW();
1809 ch -= guiApp.currentSkin.HorizontalSBH();
1811 // Update the scrollbar visibility
1817 sbh.disabled = rangeH <= 1;
1818 if(sbh.style.hidden)
1828 sbv.disabled = rangeV <= 1;
1829 if(sbv.style.hidden)
1837 // Then start off with horizontal scrollbar range
1840 positionH = sbh.thumbPosition;
1845 ch -= guiApp.currentSkin.HorizontalSBH();
1848 // Do the same for vertical scrollbar
1851 positionV = sbv.thumbPosition;
1857 cw -= guiApp.currentSkin.VerticalSBW();
1858 // Maybe we need to set the range on the horizontal scrollbar again
1863 sbh.Action(setRange, positionH, 0);
1864 if(rangeH <= 1 && sbh.range > 1)
1866 ch -= guiApp.currentSkin.HorizontalSBH();
1870 sbv.Action(setRange, positionV, 0);
1877 // Update the scrollbar visibility
1878 if(!scrollFlags.dontHide)
1880 if(sbh && ((rangeH <= 1 && !sbh.style.hidden) || (rangeH > 1 && sbh.style.hidden)))
1884 if(sbv && ((rangeV <= 1 && !sbv.style.hidden) || (rangeV > 1 && sbv.style.hidden)))
1891 if(guiApp.currentSkin)
1898 sbhVisible = sbh.style.hidden ? true : false;
1900 sbvVisible = sbv.style.hidden ? true : false;
1902 // Do our resize here
1903 if(flag && (resizeH || resizeV) && fullThing)
1905 Position(position.x, position.y, size.w, size.h, false, true, false, false, false, false);
1910 OnResize(clientSize.w, clientSize.h);
1916 sbh.visible = sbhVisible;
1918 sbv.visible = sbvVisible;
1920 scrollArea.w = Max(clientSize.w, reqScrollArea.w);
1921 scrollArea.h = Max(clientSize.h, reqScrollArea.h);
1924 sbh.pageStep = clientSize.w;
1926 sbv.pageStep = clientSize.h;
1928 // Notify doesn't handle setRange anymore... process it here
1931 int positionH = sbh.thumbPosition;
1932 if(scroll.x != positionH)
1934 OnHScroll(setRange, positionH, 0);
1938 SNAPDOWN(positionH, textCellW);
1939 scroll.x = positionH;
1945 int seen = clientSize.w, total = reqScrollArea.w;
1948 if(scrollFlags.snapX)
1949 SNAPDOWN(seen, sbStep.x);
1951 if(!total) total = seen;
1952 range = total - seen + 1;
1954 range = Max(range, 1);
1956 if(x >= range) x = range - 1;
1958 if(scrollFlags.snapX)
1959 SNAPUP(x, sbStep.x);
1963 OnHScroll(setRange, x, 0);
1968 SNAPDOWN(x, textCellW);
1974 int positionV = sbv.thumbPosition;
1975 if(scroll.y != positionV)
1977 OnVScroll(setRange, positionV, 0);
1981 SNAPDOWN(positionV, textCellH);
1982 scroll.y = positionV;
1988 int seen = clientSize.h, total = reqScrollArea.h;
1991 if(scrollFlags.snapY)
1992 SNAPDOWN(seen, sbStep.y);
1994 if(!total) total = seen;
1995 range = total - seen + 1;
1996 range = Max(range, 1);
1998 if(y >= range) y = range - 1;
2000 if(scrollFlags.snapY)
2001 SNAPUP(y, sbStep.y);
2005 OnVScroll(setRange, y, 0);
2010 SNAPDOWN(y, textCellH);
2016 if(scrolled || (resizeH || resizeV)) // This ensures children anchored to bottom/right gets repositioned correctly
2019 for(child = children.first; child; child = child.next)
2021 if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2024 child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
2025 child.Position(x, y, w, h, false, true, false, true, false, false);
2032 // Process Scrollbars
2034 if(sbh) // && !sbh.style.hidden
2036 sbh.Move(clientStart.x, clientStart.y + clientSize.h, clientSize.w,0);
2037 // Need to set the range again (should improve...) since the scrollbars didn't have
2038 // the right size when UpdateScrollArea set the range on it
2041 sbh.seen = clientSize.w;
2045 if(sbv) // && !sbv.state.hidden
2047 sbv.Move(clientStart.x + clientSize.w, clientStart.y, 0, clientSize.h);
2048 // Need to set the range again (should improve...) since the scrollbars didn't have
2049 // the right size when UpdateScrollArea set the range on it
2052 sbv.seen = clientSize.h;
2057 // TESTING THIS LOWER
2058 if(scrolled || (resizeH || resizeV)) // This ensures children anchored to bottom/right gets repositioned correctly
2061 for(child = children.first; child; child = child.next)
2063 if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2066 child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
2067 child.Position(x, y, w, h, false, true, false, true, false, false);
2073 bool MaximizeButtonClicked(Button button, int x, int y, Modifiers mods)
2075 SetState(maximized, false, mods);
2079 bool RestoreButtonClicked(Button button, int x, int y, Modifiers mods)
2081 SetState(normal, false, mods);
2085 bool MinimizeButtonClicked(Button button, int x, int y, Modifiers mods)
2087 SetState(minimized, false, mods);
2088 parent.CycleChildren(false, true, false, true);
2092 void ScrollBarNotification(ScrollBar control, ScrollBarAction action, int position, Key keyFlags)
2095 // Scroll bar notifications
2096 if(action != setRange)
2098 bool changed = false;
2102 if(scroll.x != position)
2104 OnHScroll(action, position, keyFlags);
2109 SNAPDOWN(position, textCellW);
2111 scroll.x = position;
2115 if(scroll.y != position)
2117 OnVScroll(action, position, keyFlags);
2122 SNAPDOWN(position, textCellH);
2124 scroll.y = position;
2128 bool childMove = false;
2129 for(child = children.first; child; child = child.next)
2131 if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2134 child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
2135 child.Position(x, y, w, h, false, true, false, true, false, false);
2139 // Testing this patch out to solve MDI workspace redraw bugs
2140 // We were already supposed to be updating parent's affected area in Position() but it doesn't seem to be working
2141 // Scroll offsets to blame?
2145 UpdateCaret(false, false);
2149 // Testing this patch out to solve MDI workspace redraw bugs
2150 for(child = children.first; child; child = child.next)
2152 if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2161 Window GetParentMenuBar()
2163 Window menuBarParent;
2164 for(menuBarParent = this; menuBarParent; menuBarParent = menuBarParent.parent)
2166 if(menuBarParent.menuBar) break;
2167 if(menuBarParent.parent && /*menuBarParent != */!menuBarParent.parent.activeClient)
2169 menuBarParent = null;
2173 return menuBarParent ? menuBarParent.menuBar : null;
2176 void CreateSystemChildren(void)
2178 Window parent = this;
2179 bool scrollBarChanged = false;
2180 bool hasClose = false, hasMaxMin = false;
2181 Point scroll = this.scroll;
2183 if(state == maximized)
2184 parent = GetParentMenuBar();
2188 if(style.hasClose) hasClose = true;
2189 if(style.hasMaximize || style.hasMinimize)
2196 if(sysButtons[2] && (!hasClose || sysButtons[2].parent != parent))
2198 sysButtons[2].Destroy(0);
2199 sysButtons[2] = null;
2201 if(sysButtons[1] && (!hasMaxMin || sysButtons[1].parent != parent))
2203 sysButtons[1].Destroy(0);
2204 sysButtons[1] = null;
2206 if(sysButtons[0] && (!hasMaxMin || sysButtons[0].parent != parent))
2208 sysButtons[0].Destroy(0);
2209 sysButtons[0] = null;
2212 if(hasClose && parent)
2219 parent, master = this,
2220 inactive = true, nonClient = true, visible = false;
2222 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2228 if(this.parent == guiApp.desktop)
2229 sysButtons[2].hotKey = altF4;
2230 else if(style.isActiveClient)
2231 sysButtons[2].hotKey = ctrlF4;
2232 sysButtons[2].Create();
2235 sysButtons[2].symbol = 'X';
2236 sysButtons[2].disabled = !style.hasClose;
2239 if(hasMaxMin && parent)
2243 bool (* method)(Window window, Button button, int x, int y, Modifiers mods);
2244 if(state == maximized)
2247 method = RestoreButtonClicked;
2253 method = MaximizeButtonClicked;
2261 parent, master = this,
2262 hotKey = altEnter, inactive = true, nonClient = true, visible = false
2264 sysButtons[1].Create();
2266 sysButtons[1].NotifyClicked = method;
2268 sysButtons[1].symbol = symbol;
2269 sysButtons[1].disabled = !style.hasMaximize;
2272 if(hasMaxMin && parent)
2276 bool (* method)(Window window, Button button, int x, int y, Modifiers mods);
2277 if (state == minimized)
2280 method = RestoreButtonClicked;
2286 method = MinimizeButtonClicked;
2294 parent, master = this,
2295 hotKey = altM, inactive = true, nonClient = true, visible = false
2297 sysButtons[0].Create();
2299 sysButtons[0].NotifyClicked = method;
2301 sysButtons[0].symbol = symbol;
2302 sysButtons[0].disabled = !style.hasMinimize;
2305 // Create the scrollbars
2306 if(style.hasHorzScroll && !sbh)
2312 direction = horizontal,
2316 snap = scrollFlags.snapX,
2317 NotifyScrolling = ScrollBarNotification
2320 scrollBarChanged = true;
2322 else if(sbh && !style.hasHorzScroll)
2328 if(style.hasVertScroll && !sbv)
2334 direction = vertical,
2338 snap = scrollFlags.snapY,
2339 NotifyScrolling = ScrollBarNotification
2342 scrollBarChanged = true;
2344 else if(sbv && !style.hasVertScroll)
2349 if(scrollBarChanged)
2351 SetScrollLineStep(sbStep.x, sbStep.y);
2352 UpdateScrollBars(true, true);
2356 if(scrollBarChanged)
2358 if(sbh) sbh.thumbPosition = scroll.x;
2359 if(sbv) sbv.thumbPosition = scroll.y;
2363 void UpdateCaption(void)
2365 if(rootWindow == this)
2368 FigureCaption(caption);
2369 guiApp.interfaceDriver.SetRootWindowCaption(this, caption);
2371 UpdateDecorations();
2374 if(parent.rootWindow == parent && parent.activeClient == this) // Added this last check
2377 parent.FigureCaption(caption);
2378 guiApp.interfaceDriver.SetRootWindowCaption(parent, caption);
2380 parent.UpdateDecorations();
2384 void UpdateActiveDocument(Window previous)
2386 Window activeClient = this.activeClient;
2387 Window activeChild = this.activeChild;
2394 activeClient.CreateSystemChildren();
2396 previous.CreateSystemChildren();
2408 // Build window list
2411 Menu windowMenu = menu.FindMenu("Window");
2416 for(id = 0, cycle = activeClient.cycle; cycle && id<10;)
2419 Window document = cycle.data;
2420 if(!document.style.nonClient && document.style.isActiveClient && document.visible)
2422 char name[2048], caption[2048];
2423 document.FigureCaption(caption);
2424 sprintf(name, "%d %s", id+1, caption);
2425 windowMenu.AddDynamic(MenuItem
2427 copyText = true, text = name, hotKey = Key { k1 + id }, id = id++,
2428 NotifySelect = MenuWindowSelectWindow
2432 if(activeClient.cycle == cycle) break;
2437 if((!previous && activeClient) || !activeClient)
2443 item = menu.FindItem(MenuWindowCloseAll, 0);
2444 if(item) item.disabled = false;
2445 item = menu.FindItem(MenuWindowNext, 0);
2446 if(item) item.disabled = false;
2447 item = menu.FindItem(MenuWindowPrevious, 0);
2448 if(item) item.disabled = false;
2449 item = menu.FindItem(MenuWindowCascade, 0);
2450 if(item) item.disabled = false;
2451 item = menu.FindItem(MenuWindowTileHorz, 0);
2452 if(item) item.disabled = false;
2453 item = menu.FindItem(MenuWindowTileVert, 0);
2454 if(item) item.disabled = false;
2455 item = menu.FindItem(MenuWindowArrangeIcons, 0);
2456 if(item) item.disabled = false;
2457 item = menu.FindItem(MenuWindowWindows, 0);
2458 if(item) item.disabled = false;
2461 item = menu.FindItem(MenuFileClose, 0);
2462 if(item) item.disabled = !activeClient || !activeClient.style.hasClose;
2463 item = menu.FindItem(MenuFileSaveAll, 0);
2464 if(item) item.disabled = numDocuments < 1;
2466 if(activeClient && activeClient.menu && activeClient.state != minimized)
2470 //activeClient.menu.Clean(activeClient);
2471 menu.Merge(activeClient.menu, true, activeClient);
2475 if(activeChild && activeChild != activeClient && activeChild.menu && activeChild.state != minimized)
2478 menu.Merge(activeChild.menu, true, activeChild);
2481 // This is called again for a child window change, with same active client
2482 OnActivateClient(activeClient, previous);
2483 if(!menuBar && !((BorderBits)borderStyle).fixed && parent && parent.activeClient == this)
2484 parent.UpdateActiveDocument(null);
2487 void _ShowDecorations(Box box, bool post)
2489 if(rootWindow == this && nativeDecorations) return;
2490 if(visible && this != guiApp.desktop)
2492 Surface surface = RedrawFull(box);
2496 FigureCaption(caption);
2499 ShowDecorations(captionFont.font,
2502 active, //parent.activeClient == this
2503 guiApp.windowMoving == this);
2505 PreShowDecorations(captionFont.font,
2508 active, //parent.activeClient == this
2509 guiApp.windowMoving == this);
2516 void UpdateExtent(Box refresh)
2518 Surface surface = null;
2520 if(!manageDisplay) { OnRedraw(null);return; }
2521 _ShowDecorations(refresh, false);
2523 surface = Redraw(refresh);
2524 // Opaque background: just fill before EW_REDRAW (clear?)
2527 surface.SetBackground(background);
2528 surface.SetForeground(foreground);
2529 surface.DrawingChar(' ');
2530 if(this == rootWindow)
2532 if(style.drawBehind || background.a)
2533 surface.Clear(colorBuffer);
2535 else if(background.a)
2539 background.color = { (byte)GetRandom(0,255), (byte)GetRandom(0,255), (byte)GetRandom(0,255) };
2540 surface.SetForeground((background.color.r > 128 || background.color.g > 128) ? black : white);
2543 if(display.flags.alpha && background.a < 255 && background)
2545 surface.Area(0,0,clientSize.w, clientSize.h);
2546 /*if(style.clearDepthBuffer)
2547 surface.Clear(depthBuffer);*/
2549 else if(/*style.clearDepthBuffer || */background.a)
2551 // surface.Clear((style.clearDepthBuffer ? depthBuffer : 0) | (background.a ? colorBuffer : 0));
2552 surface.Clear(colorBuffer);
2557 surface.TextFont(usedFont.font);
2558 surface.TextOpacity(false);
2562 // Draw the caret ...
2563 if(!disabled && this == guiApp.caretOwner && guiApp.caretEnabled /*&& !guiApp.interimWindow*/ && !guiApp.currentSkin.textMode)
2565 // surface.SetBackground(0xFFFFFF - background.color);
2566 surface.SetBackground(~background.color);
2568 caretPos.x - scroll.x + 1, caretPos.y - scroll.y,
2569 caretPos.x - scroll.x + 2, caretPos.y - scroll.y + caretSize - 1);
2575 void DrawOverChildren(Box refresh)
2577 Surface surface = Redraw(refresh);
2581 surface.DrawingChar(' ');
2582 surface.SetBackground(background);
2583 surface.SetForeground(foreground);
2585 surface.TextFont(usedFont.font);
2586 surface.TextOpacity(false);
2588 OnDrawOverChildren(surface);
2593 _ShowDecorations(refresh, true);
2596 void ComputeClipExtents(void)
2599 Extent clipExtent { /*first = -1, last = -1, free = -1*/ };
2601 clipExtent.Copy(this.clipExtent);
2603 for(child = children.last; child; child = child.prev)
2605 if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2607 bool opaque = child.IsOpaque(); // TODO: acess background directly
2608 int dx = child.absPosition.x - absPosition.x, dy = child.absPosition.y - absPosition.y;
2610 child.clipExtent.Copy(clipExtent);
2611 child.clipExtent.Offset(-dx, -dy);
2612 child.clipExtent.IntersectBox(child.box);
2614 child.ComputeClipExtents();
2616 if(opaque && !child.style.nonClient)
2618 // Adjust the box for the parent:
2619 Box box { child.box.left + dx, child.box.top + dy, child.box.right + dx, child.box.bottom + dy };
2620 clipExtent.ExcludeBox(box, rootWindow.tempExtents[0]);
2625 // ??? Only do this for overlapped window or if parent has with clip children flag
2627 // Do this if window has clip children flag on (default false?)
2628 // this.clipExtent = clipExtent;
2630 clipExtent.Free(null);
2633 void ComputeRenderAreaNonOpaque(Extent dirtyExtent, Extent overDirtyExtent, Extent backBufferUpdate)
2635 bool opaque = IsOpaque();
2637 int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
2638 if(rootWindow.nativeDecorations)
2640 offsetX -= rootWindow.clientStart.x;
2641 offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
2645 for(child = children.last; child; child = child.prev)
2647 ColorAlpha background = *(ColorAlpha *)&child.background;
2648 bool opaque = child.IsOpaque();
2649 if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2653 // Adjust renderArea to the root window level
2654 Extent * renderArea = &rootWindow.tempExtents[1];
2656 int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y;
2657 if(child.rootWindow.nativeDecorations)
2659 offsetX -= child.rootWindow.clientStart.x;
2660 offsetY -= child.rootWindow.clientStart.y - (child.rootWindow.hasMenuBar ? skinMenuHeight : 0);
2664 Extent childRenderArea;
2666 if(backBufferUpdate != null)
2668 childRenderArea.Copy(backBufferUpdate);
2669 childRenderArea.Offset(-offsetX, -offsetY);
2672 childRenderArea.Copy(child.dirtyArea);
2674 // Add extent forced by transparency to the dirty area, adjusting dirty extent to the window
2675 renderArea.Copy(dirtyExtent);
2676 renderArea.Offset(-offsetX, -offsetY);
2677 childRenderArea.Union(renderArea);
2680 // Intersect with the clip extent
2681 childRenderArea.Intersection(child.clipExtent);
2684 renderArea->Copy(child.dirtyArea /*childRenderArea*/);
2685 renderArea->Offset(offsetX, offsetY);
2686 dirtyExtent.Union(renderArea, rootWindow.tempExtents[0]);
2687 // overDirtyExtent.Union(renderArea);
2688 renderArea->Empty();
2689 // childRenderArea.Free();
2691 //child.ComputeRenderAreaNonOpaque(dirtyExtent, overDirtyExtent, backBufferUpdate);
2696 for(child = children.last; child; child = child.prev)
2698 if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2700 child.ComputeRenderAreaNonOpaque(dirtyExtent, overDirtyExtent, backBufferUpdate);
2705 void ComputeRenderArea(Extent dirtyExtent, Extent overDirtyExtent, Extent backBufferUpdate)
2707 bool opaque = IsOpaque();
2708 Extent * dirtyExtentWindow = &rootWindow.tempExtents[1];
2710 int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
2711 if(rootWindow.nativeDecorations)
2713 offsetX -= rootWindow.clientStart.x;
2714 offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
2718 for(child = children.last; child; child = child.prev)
2720 //child.ComputeRenderAreaNonOpaque(dirtyExtent, overDirtyExtent, backBufferUpdate);
2722 ColorAlpha background = *(ColorAlpha *)&child.background;
2723 bool opaque = child.IsOpaque();
2724 if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2728 int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y;
2729 // Adjust renderArea to the root window level
2731 renderArea.Copy(child.dirtyArea);
2732 renderArea.Offset(offsetX, offsetY);
2733 dirtyExtent.Union(renderArea);
2734 overDirtyExtent.Union(renderArea);
2740 for(child = children.last; child; child = child.prev)
2742 if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2744 child.ComputeRenderArea(dirtyExtent, overDirtyExtent, backBufferUpdate);
2748 if(backBufferUpdate != null)
2750 renderArea.Copy(backBufferUpdate);
2751 renderArea.Offset(-offsetX, -offsetY);
2753 overRenderArea.Copy(backBufferUpdate);
2754 overRenderArea.Offset(-offsetX, -offsetY);
2760 renderArea.Copy(dirtyArea);
2762 overRenderArea.Copy(dirtyArea);
2765 // Add extent forced by transparency to the dirty area, adjusting dirty extent to the window
2766 dirtyExtentWindow->Copy(dirtyExtent);
2767 dirtyExtentWindow->Offset(-offsetX, -offsetY);
2768 renderArea.Union(dirtyExtentWindow, rootWindow.tempExtents[0]);
2769 dirtyExtentWindow->Empty();
2771 // Intersect with the clip extent
2772 renderArea.Intersection(clipExtent, rootWindow.tempExtents[0], rootWindow.tempExtents[1], rootWindow.tempExtents[2]);
2775 if(renderArea.count > 10)
2778 printf("\nToo many extents (%d):\n", renderArea.count);
2780 //extent.UnionBox({ 112, 6, 304, 7 }, rootWindow.tempExtents[0]);
2781 //extent.UnionBox({ 112, 8, 304, 17 }, rootWindow.tempExtents[0]);
2786 for(c = 0; c<10; c++)
2789 FASTLIST_LOOP(renderArea, extentBox)
2791 extent.UnionBox(extentBox.box, rootWindow.tempExtents[0]);
2793 renderArea.Copy(extent);
2795 FASTLIST_LOOP(renderArea, extentBox)
2798 printf("(%d, %d) - (%d, %d)\n",
2799 extentBox.box.left, extentBox.box.top,
2800 extentBox.box.right, extentBox.box.bottom);
2804 printf("\nNow %d\n", renderArea.count);
2810 // WHY WAS THIS COMMENTED ??
2812 // Add extent forced by DrawOverChildren to the dirty area, adjusting dirty extent to the window
2813 dirtyExtentWindow->Copy(overDirtyExtent);
2814 dirtyExtentWindow->Offset(-offsetX, -offsetY);
2815 overRenderArea.Union(dirtyExtentWindow, rootWindow.tempExtents[0]);
2816 dirtyExtentWindow->Empty();
2818 // Intersect with the clip extent
2819 overRenderArea.Intersection(clipExtent, rootWindow.tempExtents[0], rootWindow.tempExtents[1], rootWindow.tempExtents[2]);
2825 if(scrollExtent.count)
2827 // Subtract render extent from scrolling extent
2828 scrollExtent.Exclusion(renderArea, rootWindow.tempExtents[0]);
2830 if(backBufferUpdate == null)
2832 Extent * dirty = &rootWindow.tempExtents[3];
2835 // Intersect scrolling extent with clip extent
2836 scrollExtent.Intersection(clipExtent, rootWindow.tempExtents[0], rootWindow.tempExtents[1], rootWindow.tempExtents[2]);
2838 // offset this scroll to be at the root window level
2839 scrollExtent.Offset(offsetX, offsetY);
2840 // Add area that was scrolled to the dirty extents of the back buffer
2841 rootWindow.dirtyBack.Union(scrollExtent, rootWindow.tempExtents[0]);
2845 // Will need scrolledArea.x & scrolledArea.y to support multiple scrolls
2846 for(scrollBox = (BoxItem)scrollExtent.first; scrollBox; scrollBox = (BoxItem)scrollBox.next)
2847 display.Scroll(scrollBox.box, scrolledArea.x, scrolledArea.y, dirty);
2852 scrollExtent.Empty();
2854 // Add the exposed extent to the window render area
2855 dirty->Offset(-offsetX, -offsetY);
2856 renderArea.Union(dirty, rootWindow.tempExtents[0]);
2861 // Subtract the window's box from the transparency forced extent
2862 dirtyExtent.ExcludeBox({box.left + offsetX, box.top + offsetY, box.right + offsetX, box.bottom + offsetY }, rootWindow.tempExtents[0]);
2868 renderArea.Copy(this.renderArea);
2869 renderArea.Offset(offsetX, offsetY);
2870 dirtyExtent.Union(renderArea);
2876 Extent renderArea { };
2878 renderArea.Copy(overRenderArea);
2879 renderArea.Offset(offsetX, offsetY);
2880 overDirtyExtent.Union(renderArea, rootWindow.tempExtents[0]);
2885 if(backBufferUpdate != null)
2887 // Remove render area from dirty area
2888 dirtyArea.Exclusion(renderArea, rootWindow.tempExtents[0]);
2890 dirtyArea.Exclusion(overRenderArea, rootWindow.tempExtents[0]);
2897 // Remove the window render area from the dirty extents of the back buffer
2898 rootWindow.dirtyBack.Exclusion(renderArea);
2902 void Render(Extent updateExtent)
2906 Window rootWindow = this.rootWindow;
2907 int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
2908 if(rootWindow.nativeDecorations)
2910 offsetX -= rootWindow.clientStart.x;
2911 offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
2914 if(rootWindow.fullRender)
2923 background = Color { (byte)GetRandom(0,255), (byte)GetRandom(0,255), (byte)GetRandom(0,255) };
2924 foreground = (background.color.r > 128 || background.color.g > 128) ? black : white;
2929 /*if(renderArea.count)
2930 printf("\n\nRendering %s (%x):\n------------------------------------------\n", _class.name, this);*/
2933 for(extentBox = (BoxItem)renderArea.first; extentBox; extentBox = (BoxItem)extentBox.next)
2935 Box box = extentBox.box;
2938 /*printf("(%d, %d) - (%d, %d)\n",
2939 extentBox.box.left, extentBox.box.top,
2940 extentBox.box.right, extentBox.box.bottom);*/
2945 box.left += offsetX;
2947 box.right += offsetX;
2948 box.bottom += offsetY;
2950 if(updateExtent != null)
2951 updateExtent.UnionBox(box, rootWindow.tempExtents[0]);
2955 for(child = children.first; child; child = child.next)
2956 if(!child.style.hidden && child.created && !child.is3D && child.rootWindow && !child.nonClient)
2957 child.Render(updateExtent);
2959 if(rootWindow.fullRender)
2960 DrawOverChildren(box);
2963 // TO DO: There's an issue about draw over children...
2964 // TO DO: Don't wanna go through this if method isn't used
2965 for(extentBox = (BoxItem)overRenderArea.first; extentBox; extentBox = (BoxItem)extentBox.next)
2966 //FASTLIST_LOOP(/*renderArea */overRenderArea, extentBox)
2968 Box box = extentBox.box;
2970 DrawOverChildren(box);
2972 box.left += offsetX;
2974 box.right += offsetX;
2975 box.bottom += offsetY;
2977 if(updateExtent != null)
2978 updateExtent.UnionBox(box, rootWindow.tempExtents[0]);
2981 for(child = children.first; child; child = child.next)
2982 if(!child.style.hidden && child.created && !child.is3D && child.rootWindow && child.nonClient)
2983 child.Render(updateExtent);
2986 overRenderArea.Empty();
2989 public void UpdateDisplay(void)
2991 if(!manageDisplay) { OnRedraw(null);return; }
2992 if(rootWindow && this != rootWindow)
2993 rootWindow.UpdateDisplay();
2996 Extent dirtyExtent { /*first = -1, last = -1, free = -1*/ }; // Extent that needs to be forced due to transparency
2997 Extent overExtent { /*first = -1, last = -1, free = -1*/ }; // Extent that forced for DrawOverChildren
3000 dirtyExtent.Clear();
3003 clipExtent.AddBox(box);
3005 display.StartUpdate();
3007 if(!rootWindow.fullRender)
3009 ComputeClipExtents();
3010 ComputeRenderAreaNonOpaque(dirtyExtent, overExtent, null);
3011 ComputeRenderArea(dirtyExtent, overExtent, null);
3014 clipExtent.Free(null);
3016 dirtyExtent.Free(null);
3017 overExtent.Free(null);
3019 if(display.flags.flipping)
3022 display.Update(null);
3026 Extent updateExtent { /*first = -1, last = -1, free = -1*/ }; // Extent that needs to be updated
3027 updateExtent.Clear();
3029 Render(updateExtent);
3031 updateExtent.UnionBox(this.box, tempExtents[0]);
3034 //printf("\n\nUpdate:\n------------------------------------------\n");
3037 //FASTLIST_LOOP(updateExtent, extentBox)
3038 for(extentBox = (BoxItem)updateExtent.first; extentBox; extentBox = (BoxItem)extentBox.next)
3041 /*printf("Updating (%d, %d) - (%d, %d)\n",
3042 extentBox.box.left, extentBox.box.top,
3043 extentBox.box.right, extentBox.box.bottom);*/
3046 display.Update(extentBox.box);
3049 updateExtent.Free(null);
3052 display.EndUpdate();
3060 void UpdateBackDisplay(Box box)
3066 Extent intersection { /*first = -1, last = -1, free = -1*/ };
3068 //printf("UpdateBackDisplay going through!\n");
3069 display.StartUpdate();
3073 intersection.Copy(dirtyBack);
3074 intersection.IntersectBox(box);
3076 dirtyExtent.Clear();
3079 clipExtent.AddBox(box);
3081 if(!rootWindow.fullRender)
3083 ComputeClipExtents();
3084 ComputeRenderArea(dirtyExtent, overExtent, intersection);
3087 clipExtent.Free(null);
3089 intersection.Free(null);
3090 dirtyExtent.Free(null);
3091 overExtent.Free(null);
3096 if(display.flags.flipping)
3097 display.Update(null);
3100 rootWindow.display.Update(box);
3103 display.EndUpdate();
3107 dirtyBack.ExcludeBox(box, rootWindow.tempExtents[0]);
3108 if(dirtyBack.count > MAX_DIRTY_BACK)
3110 BoxItem extentBox, next;
3111 BoxItem first = (BoxItem)ACCESS_ITEM(dirtyBack, dirtyBack.first);
3112 for(extentBox = (BoxItem)dirtyBack.first; extentBox; extentBox = next)
3114 next = (BoxItem)extentBox.next;
3115 if(extentBox != first)
3117 if(extentBox.box.left < first.box.left)
3118 first.box.left = extentBox.box.left;
3119 if(extentBox.box.top < first.box.top)
3120 first.box.top = extentBox.box.top;
3121 if(extentBox.box.right > first.box.right)
3122 first.box.right = extentBox.box.right;
3123 if(extentBox.box.bottom > first.box.bottom)
3124 first.box.bottom = extentBox.box.bottom;
3125 dirtyBack.Delete(extentBox);
3134 // --- Window positioning ---
3135 // --- Window identification ---
3137 // Returns window at position "Position"
3138 Window GetAtPosition(int x, int y, bool clickThru, bool acceptDisabled, Window last)
3140 Window child, result = null;
3142 box.left += absPosition.x;
3143 box.right += absPosition.x;
3144 box.top += absPosition.y;
3145 box.bottom += absPosition.y;
3147 if(!destroyed && visible && (acceptDisabled || !disabled))
3149 int lx = x - absPosition.x;
3150 int ly = y - absPosition.y;
3151 if(IsInside(lx, ly))
3152 // if(box.IsPointInside(Point{x, y}))
3154 if(!clickThru || !style.clickThrough) result = (this == last) ? null : this;
3155 // If the window is disabled, stop looking in children (for acceptDisabled mode)
3158 for(child = (last && last.parent == this) ? last.previous : children.last; child; child = child.prev)
3160 if(child != statusBar && child.rootWindow == rootWindow)
3162 Window childResult = child.GetAtPosition(x, y, clickThru, acceptDisabled, last);
3169 for(child = (last && last.parent == this) ? last.previous : children.last; child; child = child.prev)
3171 if(child != statusBar && child.rootWindow == rootWindow)
3173 Window childResult = child.GetAtPosition(x, y, false, acceptDisabled, last);
3185 Window FindModal(void)
3187 Window modalWindow = this, check;
3188 Window check2 = null;
3189 for(check = this; check.master; check = check.master)
3191 if(check.master.modalSlave && check.master.modalSlave.created && check != check.master.modalSlave)
3193 modalWindow = check.master.modalSlave;
3194 check = modalWindow;
3196 // TESTING THIS FOR DROPBOX...
3197 if(!rootWindow || !rootWindow.style.interim)
3199 for(check2 = check; check2.activeChild; check2 = check2.activeChild)
3201 if(check2.modalSlave && check2.modalSlave.created)
3203 modalWindow = check2.modalSlave;
3211 if(modalWindow == this)
3213 for(check = this; check.activeChild; check = check.activeChild)
3215 if(check.modalSlave)
3217 modalWindow = check.modalSlave;
3223 for(; modalWindow.modalSlave && modalWindow.modalSlave.created; modalWindow = modalWindow.modalSlave);
3224 return (modalWindow == this || this == guiApp.interimWindow || IsDescendantOf(modalWindow)) ? null : modalWindow;
3227 void StopMoving(void)
3229 if(this == guiApp.windowMoving)
3231 guiApp.windowMoving = null;
3232 UpdateDecorations();
3233 SetMouseRange(null);
3236 if(rootWindow.active)
3237 guiApp.interfaceDriver.StopMoving(rootWindow);
3240 guiApp.resizeX = guiApp.resizeY = guiApp.resizeEndX = guiApp.resizeEndY = false;
3241 guiApp.windowIsResizing = false;
3245 void SelectMouseCursor(void)
3250 Window cursorWindow = null;
3251 bool rx, ry, rex, rey;
3253 guiApp.desktop.GetMousePosition(&x, &y);
3254 mouseWindow = rootWindow ? rootWindow.GetAtPosition(x,y, true, false, null) : null;
3256 if((guiApp.windowMoving && !guiApp.windowIsResizing) || guiApp.windowScrolling)
3257 guiApp.SetCurrentCursor(guiApp.systemCursors[moving]);
3258 else if(mouseWindow)
3260 modalWindow = mouseWindow.FindModal();
3261 x -= mouseWindow.absPosition.x;
3262 y -= mouseWindow.absPosition.y;
3263 if(guiApp.windowIsResizing)
3265 rex = guiApp.resizeEndX;
3266 rey = guiApp.resizeEndY;
3267 rx = guiApp.resizeX;
3268 ry = guiApp.resizeY;
3269 if((rex && rey) || (rx && ry))
3270 guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNWSE]);
3271 else if((rex && ry) || (rx && rey))
3272 guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNESW]);
3273 else if((ry || rey) && (!rx && !rex))
3274 guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNS]);
3275 else if((rx || rex) && (!ry && !rey))
3276 guiApp.SetCurrentCursor(guiApp.systemCursors[sizeWE]);
3278 else if(!modalWindow && !guiApp.windowCaptured &&
3279 mouseWindow.IsMouseResizing(x, y, mouseWindow.size.w, mouseWindow.size.h,
3280 &rx, &ry, &rex, &rey))
3282 if((rex && rey) || (rx && ry))
3283 guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNWSE]);
3284 else if((rex && ry) || (rx && rey))
3285 guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNESW]);
3286 else if((ry || rey) && (!rx && !rex))
3287 guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNS]);
3288 else if((rx || rex) && (!ry && !rey))
3289 guiApp.SetCurrentCursor(guiApp.systemCursors[sizeWE]);
3291 else if(!guiApp.windowCaptured && !modalWindow && !guiApp.interimWindow)
3293 if(!mouseWindow.clientArea.IsPointInside({x - mouseWindow.clientStart.x, y - mouseWindow.clientStart.y}))
3294 cursorWindow = mouseWindow.parent;
3296 cursorWindow = mouseWindow;
3298 else if(!guiApp.interimWindow)
3299 cursorWindow = guiApp.windowCaptured;
3302 for(; !cursorWindow.cursor && !cursorWindow.style.nonClient; cursorWindow = cursorWindow.parent);
3303 guiApp.SetCurrentCursor(cursorWindow.cursor ? cursorWindow.cursor : guiApp.systemCursors[arrow]);
3305 else if(modalWindow)
3307 guiApp.SetCurrentCursor(guiApp.systemCursors[arrow]);
3309 else if(guiApp.interimWindow)
3311 if(guiApp.interimWindow.cursor)
3312 guiApp.SetCurrentCursor(guiApp.interimWindow.cursor);
3314 guiApp.SetCurrentCursor(mouseWindow.cursor ? mouseWindow.cursor : guiApp.systemCursors[arrow]);
3319 // --- State based input ---
3320 bool AcquireInputEx(bool state)
3325 guiApp.interfaceDriver.GetMousePosition(&guiApp.acquiredMouseX, &guiApp.acquiredMouseY);
3326 guiApp.interfaceDriver.SetMousePosition(clientSize.w/2 + absPosition.x, clientSize.h/2 + absPosition.y);
3328 result = guiApp.interfaceDriver.AcquireInput(rootWindow, state);
3330 guiApp.acquiredWindow = state ? this : null;
3333 SetMouseRangeToClient();
3334 guiApp.interfaceDriver.SetMouseCursor((SystemCursor)-1);
3339 SelectMouseCursor();
3341 if(!state) guiApp.interfaceDriver.SetMousePosition(guiApp.acquiredMouseX, guiApp.acquiredMouseY);
3345 // --- Window activation ---
3346 bool PropagateActive(bool active, Window previous, bool * goOnWithActivation, bool direct)
3349 if(!parent || !parent.style.inactive)
3351 Window parent = this.parent;
3354 if(rootWindow == this)
3355 Log(active ? "active\n" : "inactive\n");
3358 // Testing this here...
3359 if(!parent || parent == guiApp.desktop || parent.active)
3361 this.active = active;
3364 // TESTING THIS HERE
3365 UpdateDecorations();
3366 if(result = OnActivate(active, previous, goOnWithActivation, direct) && *goOnWithActivation && master)
3367 result = NotifyActivate(master, this, active, previous);
3370 this.active = !active;
3375 if(!parent || parent == guiApp.desktop || parent.active)
3377 this.active = active;
3379 AcquireInputEx(active);
3384 if(guiApp.caretOwner)
3388 guiApp.caretOwner.caretPos.x - guiApp.caretOwner.scroll.x + 1,
3389 guiApp.caretOwner.caretPos.y - guiApp.caretOwner.scroll.y + 1,
3390 guiApp.caretOwner.caretPos.x - guiApp.caretOwner.scroll.x + 2,
3391 guiApp.caretOwner.caretPos.y - guiApp.caretOwner.scroll.y + guiApp.caretOwner.caretSize - 1
3393 guiApp.caretOwner.Update(extent);
3396 if(visible || !guiApp.caretOwner)
3397 guiApp.caretOwner = this;
3398 UpdateCaret(false, false);
3404 this.active = false;
3406 AcquireInputEx(active);
3408 if(!active && guiApp.caretOwner == this)
3410 UpdateCaret(false, true);
3411 guiApp.caretOwner = null;
3412 guiApp.interfaceDriver.SetCaret(0,0,0);
3413 guiApp.caretEnabled = false;
3418 if(!active && parent && parent.activeChild && parent.activeChild != this)
3419 if(!parent.activeChild.PropagateActive(false, previous, goOnWithActivation, true) || !*goOnWithActivation)
3425 if(!active && menuBar)
3428 menuBar.OnActivate(false, null, &goOn, true);
3429 menuBar.NotifyActivate(menuBar.master, menuBar, false, null);
3434 Window aChild = activeChild;
3436 if(!aChild.PropagateActive(active, previous, goOnWithActivation, false) || !*goOnWithActivation)
3448 void ConsequentialMouseMove(bool kbMoving)
3452 if(kbMoving || !guiApp.windowMoving)
3456 if(rootWindow == guiApp.desktop || rootWindow.parent == guiApp.desktop)
3458 guiApp.interfaceDriver.GetMousePosition(&x, &y);
3460 if(guiApp.windowMoving || rootWindow.GetAtPosition(x, y, true, false, null))
3461 rootWindow.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x, y, &mods, true, false);
3467 bool IsDescendantOf(Window ancestor)
3470 for(window = this; window && window != ancestor; window = window.parent);
3471 return window == ancestor;
3474 bool IsSlaveOf(Window master)
3477 for(window = this; window && window != master; window = window.master);
3478 return window == master;
3481 bool ActivateEx(bool active, bool activateParent, bool moveInactive, bool activateRoot, Window external, Window externalSwap)
3485 if(this && !destroyed /*&& state != Hidden*/)
3487 Window swap = externalSwap;
3495 if(activateParent &&
3496 (parent.activeChild != this ||
3497 (guiApp.interimWindow && !IsDescendantOf(guiApp.interimWindow))) &&
3498 active && _isModal &&
3499 parent != master && master)
3500 master.ActivateEx(true, true, false, activateRoot, external, externalSwap);
3506 bool real = parent.activeChild != this;
3508 // TEST THIS: New activateParent check here!!! CAUSED MENUS NOT GOING AWAY
3509 if(/*activateParent && */guiApp.interimWindow &&
3510 !IsDescendantOf(guiApp.interimWindow) &&
3511 !IsSlaveOf(guiApp.interimWindow))
3513 Window interimWindow = guiApp.interimWindow;
3514 while(interimWindow && interimWindow != this)
3516 Window master = interimWindow.master;
3518 guiApp.interimWindow = null;
3519 if(guiApp.caretOwner)
3520 guiApp.caretOwner.UpdateCaret(false, false);
3522 incref interimWindow;
3523 if(!interimWindow.PropagateActive(false, this, &goOn, true))
3528 delete interimWindow;
3529 interimWindow = (master && master.style.interim) ? master : null;
3534 guiApp.interimWindow = this;
3535 /*guiApp.interfaceDriver.SetCaret(0,0,0);
3536 guiApp.caretEnabled = false;*/
3537 UpdateCaret(false, true);
3542 bool acquireInput = false;
3544 parent.activeChild &&
3545 parent.activeChild.state == maximized &&
3546 parent != guiApp.desktop;
3548 if(!style.inactive) // (!style.isRemote || parent.active || parent.style.hidden))
3553 swap = parent.activeChild;
3554 if(swap && swap.destroyed) swap = null;
3555 if(swap && swap != this)
3558 if(!swap.PropagateActive(false, this, &goOn, true))
3559 swap = parent.activeChild;
3570 if(!parent || parent.activeChild != this || style.interim)
3573 result = PropagateActive(true, swap, &goOn, true);
3574 if(!result && !goOn)
3579 acquireInput = true;
3583 if(style.hasMaximize && parent != guiApp.desktop)
3586 SetState(maximized, false, 0);
3587 else if(state != maximized)
3590 for(child = parent.children.first; child; child = child.next)
3592 if(this != child && child.state == maximized)
3593 child.SetState(normal, false, 0);
3600 if(!style.inactive && !style.interim /*&& (!style.isRemote || parent.active || parent.style.hidden)*/)
3602 Window previous = parent.activeClient;
3603 parent.activeChild = this;
3604 if(!style.nonClient /*&& style.isActiveClient*/)
3608 if(style.isActiveClient)
3609 parent.activeClient = this;
3610 // Moved UpdateActiveDocument inside hidden check
3611 // To prevent activating previous window while creating a new one
3612 // (It was messing up the privateModule in the CodeEditor)
3613 parent.UpdateActiveDocument(previous);
3619 //if(!style.isRemote)
3621 if(rootWindow != this)
3623 if(activateParent && parent && !parent.active /*parent != parent.parent.activeChild*/)
3624 parent.ActivateEx(true, true, moveInactive, activateRoot, external, externalSwap);
3626 else if(!guiApp.fullScreenMode)
3628 Window modalRoot = FindModal();
3629 if(!modalRoot) modalRoot = this;
3630 if(!modalRoot.isForegroundWindow)
3632 modalRoot.isForegroundWindow = true;
3633 // To check : Why is parent null?
3634 if(activateRoot && modalRoot.parent && !modalRoot.parent.display && external != modalRoot)
3636 guiApp.interfaceDriver.ActivateRootWindow(modalRoot);
3638 modalRoot.isForegroundWindow = false;
3643 if(result && real && (!style.inactive || moveInactive) && parent)
3645 Window last = parent.children.last;
3647 if(!style.stayOnTop)
3648 for(; last && last.style.stayOnTop; last = last.prev);
3650 parent.children.Move(this, last);
3652 // Definitely don't want that: why not?
3656 parent.childrenOrder.Move(order, parent.childrenOrder.last);
3662 if(!parent || style.interim || (parent.activeChild == this && !style.inactive))
3669 parent.activeChild = null;
3670 if(!style.nonClient /*&& style.isActiveClient*/)
3672 Window previous = parent.activeClient;
3673 if(style.isActiveClient)
3674 parent.activeClient = null;
3675 parent.UpdateActiveDocument(previous);
3679 if(this == guiApp.interimWindow)
3681 guiApp.interimWindow = null;
3682 if(guiApp.caretOwner)
3683 guiApp.caretOwner.UpdateCaret(false, false);
3685 if(!PropagateActive(false, externalSwap, &goOn, true) || !goOn)
3692 if(!active || !swap)
3693 UpdateDecorations();
3695 swap.UpdateDecorations();
3697 if(active && rootWindow != this)
3698 ConsequentialMouseMove(false);
3705 // --- Input Messages ---
3706 void ::UpdateMouseMove(int mouseX, int mouseY, bool consequential)
3708 static bool reEntrancy = false;
3709 if(reEntrancy) return;
3713 guiApp.cursorUpdate = true;
3714 if(guiApp.windowScrolling && !consequential)
3716 guiApp.windowScrolling.SetScrollPosition(
3717 (guiApp.windowScrolling.sbh) ?
3718 (guiApp.windowScrollingBefore.x - mouseX + guiApp.windowScrollingStart.x) : 0,
3719 (guiApp.windowScrolling.sbv) ?
3720 (guiApp.windowScrollingBefore.y - mouseY + guiApp.windowScrollingStart.y) : 0);
3722 if(guiApp.windowMoving)
3724 if(mouseX != guiApp.movingLast.x || mouseY != guiApp.movingLast.y)
3726 Window window = guiApp.windowMoving;
3728 int w = window.size.w;
3729 int h = window.size.h;
3734 rx = mouseX - guiApp.windowMovingStart.x;
3735 ry = mouseY - guiApp.windowMovingStart.y;
3738 window.GetDecorationsSize(&ew, &eh);
3740 if(guiApp.windowIsResizing)
3742 x = window.scrolledPos.x;
3743 y = window.scrolledPos.y;
3747 aw = Max(guiApp.windowResizingBefore.w - rx,window.skinMinSize.w);
3748 rx = guiApp.windowResizingBefore.w - aw;
3749 rx = Min(guiApp.windowMovingBefore.x + rx, window.parent.clientSize.w-1) - guiApp.windowMovingBefore.x;
3750 w = guiApp.windowResizingBefore.w - rx;
3754 ah = Max(guiApp.windowResizingBefore.h - ry,window.skinMinSize.h);
3755 ry = guiApp.windowResizingBefore.h - ah;
3756 ry = Min(guiApp.windowMovingBefore.y + ry, window.parent.clientSize.h-1) - guiApp.windowMovingBefore.y;
3757 ry = Max(ry, -guiApp.windowMovingBefore.y);
3758 h = guiApp.windowResizingBefore.h - ry;
3760 if(guiApp.resizeEndX)
3762 w = guiApp.windowResizingBefore.w + rx;
3765 if(guiApp.resizeEndY) h = guiApp.windowResizingBefore.h + ry;
3773 w = Max(w, window.minSize.w);
3774 h = Max(h, window.minSize.h);
3775 w = Min(w, window.maxSize.w);
3776 h = Min(h, window.maxSize.h);
3778 if(!window.OnResizing(&w, &h))
3780 w = window.clientSize.w;
3781 h = window.clientSize.h;
3784 w = Max(w, window.skinMinSize.w);
3785 h = Max(h, window.skinMinSize.h);
3792 SNAPDOWN(w, textCellW);
3793 SNAPDOWN(h, textCellH);
3798 aw = Max(w,window.skinMinSize.w);
3799 rx = guiApp.windowResizingBefore.w - aw;
3800 rx = Min(guiApp.windowMovingBefore.x + rx, window.parent.clientSize.w-1) - guiApp.windowMovingBefore.x;
3801 w = guiApp.windowResizingBefore.w - rx;
3805 ah = Max(h,window.skinMinSize.h);
3806 ry = guiApp.windowResizingBefore.h - ah;
3807 ry = Min(guiApp.windowMovingBefore.y + ry, window.parent.clientSize.h-1) - guiApp.windowMovingBefore.y;
3808 ry = Max(ry, -guiApp.windowMovingBefore.y);
3809 h = guiApp.windowResizingBefore.h - ry;
3814 if(!guiApp.windowIsResizing || guiApp.resizeX)
3815 x = guiApp.windowMovingBefore.x + rx;
3816 if(!guiApp.windowIsResizing || guiApp.resizeY)
3817 y = guiApp.windowMovingBefore.y + ry;
3819 if(!guiApp.windowIsResizing)
3822 if(window.parent == guiApp.desktop && guiApp.virtualScreen.w)
3824 x = Min(x, (guiApp.virtualScreen.w + guiApp.virtualScreenPos.x) -1);
3825 y = Min(y, (guiApp.virtualScreen.h + guiApp.virtualScreenPos.y) -1);
3826 x = Max(x,-(w-1) + guiApp.virtualScreenPos.x);
3827 y = Max(y,-(h-1) + guiApp.virtualScreenPos.y);
3831 x = Min(x, (window.parent.reqScrollArea.w ? window.parent.reqScrollArea.w : window.parent.clientSize.w) -1);
3832 y = Min(y, (window.parent.reqScrollArea.h ? window.parent.reqScrollArea.h : window.parent.clientSize.h) -1);
3838 if(!guiApp.windowIsResizing || (guiApp.resizeX || guiApp.resizeY))
3840 if(!window.OnMoving(&x, &y, w, h))
3842 x = window.scrolledPos.x;
3843 y = window.scrolledPos.y;
3849 SNAPDOWN(x, textCellW);
3850 SNAPDOWN(y, textCellH);
3853 if(!window.style.nonClient)
3855 if(!window.style.fixed /*|| window.style.isDocument*/)
3857 if(!window.style.dontScrollHorz)
3858 x += window.parent.scroll.x;
3859 if(!window.style.dontScrollVert)
3860 y += window.parent.scroll.y;
3864 // Break the anchors for moveable/resizable windows
3865 // Will probably cause problem with IDE windows... Will probably need a way to specify if anchors should break
3866 if(window.style.fixed)
3868 if(window.state == normal)
3870 window.normalAnchor = Anchor { left = x, top = y };
3871 window.normalSizeAnchor = SizeAnchor { { w, h } };
3872 window.anchored = false;
3876 window.stateAnchor = Anchor { left = x, top = y };
3877 window.stateSizeAnchor = SizeAnchor { { w, h } };
3879 window.Position(x, y, w, h, false, true, guiApp.windowIsResizing, guiApp.windowIsResizing, false, true);
3880 // TOCHECK: Investigate why the following only redraws the scrollbars
3881 //window.Position(x, y, w, h, false, true, true, true, false, true);
3883 guiApp.movingLast.x = mouseX;
3884 guiApp.movingLast.y = mouseY;
3890 public bool MouseMessage(uint method, int x, int y, Modifiers * mods, bool consequential, bool activate)
3893 bool wasMoving = guiApp.windowMoving ? true : false;
3894 bool wasScrolling = guiApp.windowScrolling ? true : false;
3896 while(result && w != this)
3898 Window msgWindow = GetAtPosition(x,y, false, true, w);
3899 Window trueWindow = GetAtPosition(x,y, false, false, w);
3900 bool windowDragged = false;
3905 window = (w && !w.disabled) ? w : null;
3907 if(trueWindow) incref trueWindow;
3909 if(consequential) mods->isSideEffect = true;
3911 UpdateMouseMove(x, y, consequential);
3913 if(guiApp.windowCaptured && (guiApp.windowCaptured.rootWindow == this))
3915 if(!guiApp.windowCaptured.isEnabled)
3916 guiApp.windowCaptured.ReleaseCapture();
3918 window = guiApp.windowCaptured;
3921 if(trueWindow && activate &&
3922 (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown ||
3923 method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown ||
3924 method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown ||
3925 method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick))
3927 if(mods->alt && !mods->ctrl && !mods->shift)
3929 Window moved = trueWindow;
3930 for(moved = trueWindow; moved; moved = moved.parent)
3931 if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown || ((moved.style.fixed || moved.moveable) && moved.state != maximized))
3936 windowDragged = true;
3938 // Cancel the ALT menu toggling...
3939 window.rootWindow.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, 0, 0);
3944 if(window && activate &&
3945 (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown ||
3946 method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown ||
3947 method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown ||
3948 method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick))
3950 Window modalWindow = window.FindModal();
3952 /*if(mods->alt && !mods->shift && !mods->ctrl)
3954 Window moved = window;
3955 for(moved = window; moved; moved = moved.parent)
3956 if(method == OnRightButtonDown || ((moved.style.fixed || moved.moveable) && moved.state != maximized))
3961 windowDragged = true;
3963 // Cancel the ALT menu toggling...
3964 window.rootWindow.KeyMessage(OnKeyDown, 0, 0);
3970 Window activateWindow = modalWindow ? modalWindow : window;
3971 if(activateWindow && !activateWindow.isRemote)
3973 bool doActivation = true;
3974 //bool needToDoActivation = false;
3975 Window check = activateWindow;
3977 for(check = activateWindow; check && check != guiApp.desktop; check = check.parent)
3979 if(!check.style.inactive)
3981 //needToDoActivation = true;
3983 doActivation = false;
3988 if(!needToDoActivation)
3989 doActivation = false;
3992 if((doActivation && (activateWindow.parent != guiApp.desktop || guiApp.fullScreen)) ||
3993 (guiApp.interimWindow && !window.IsDescendantOf(guiApp.interimWindow)))
3995 // Let the OnLeftButtonDown do the activating instead
3996 if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick)
4004 incref activateWindow;
4005 if(!activateWindow.ActivateEx(true, true, false, true, null, null))
4007 delete activateWindow;
4011 if(activateWindow._refCount == 1)
4013 delete activateWindow;
4017 delete activateWindow;
4019 mods->isActivate = true;
4023 if(!modalWindow && window && !window.destroyed)
4025 if(!guiApp.windowCaptured || windowDragged)
4027 if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown)
4029 bool moving = ((window.state != maximized &&
4030 window.IsMouseMoving(
4031 x - window.absPosition.x, y - window.absPosition.y, window.size.w, window.size.h)))
4032 || (guiApp.windowMoving && !guiApp.windowIsResizing);
4034 if(!moving && window.IsMouseResizing(
4035 x - window.absPosition.x,
4036 y - window.absPosition.y,
4037 window.size.w, window.size.h,
4038 &guiApp.resizeX, &guiApp.resizeY, &guiApp.resizeEndX, &guiApp.resizeEndY))
4040 guiApp.windowIsResizing = true;
4041 guiApp.windowResizingBefore.w = window.size.w;
4042 guiApp.windowResizingBefore.h = window.size.h;
4044 if(guiApp.windowIsResizing || windowDragged || moving)
4047 guiApp.windowMoving = window;
4048 guiApp.windowMovingStart.x = guiApp.movingLast.x = x;
4049 guiApp.windowMovingStart.y = guiApp.movingLast.y = y;
4050 guiApp.windowMovingBefore.x = window.position.x;//s;
4051 guiApp.windowMovingBefore.y = window.position.y;//s;
4052 if(guiApp.windowMoving == guiApp.windowMoving.rootWindow)
4053 guiApp.interfaceDriver.StartMoving(guiApp.windowMoving.rootWindow, 0,0,false);
4056 else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown)
4058 if(window.style.fixed &&
4060 window.IsMouseMoving(
4061 x - window.absPosition.x, y - window.absPosition.y, window.size.w, window.size.h)))
4063 window.ShowSysMenu(x, y);
4067 else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown)
4069 if(window.sbv || window.sbh)
4072 guiApp.windowScrolling = window;
4073 guiApp.windowScrollingStart.x = x;
4074 guiApp.windowScrollingStart.y = y;
4075 guiApp.windowScrollingBefore.x = window.scroll.x;
4076 guiApp.windowScrollingBefore.y = window.scroll.y;
4079 else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick)
4081 if(window.style.hasMaximize &&
4082 window.IsMouseMoving(
4083 x - window.absPosition.x, y - window.absPosition.y, window.size.w, window.size.h))
4086 (window.state == maximized) ? normal : maximized, false, *mods);
4094 if(guiApp.windowMoving)
4096 if(guiApp.windowMoving.parent)
4098 if(guiApp.windowMoving.style.nonClient)
4099 guiApp.windowMoving.parent.SetMouseRangeToWindow();
4101 guiApp.windowMoving.parent.SetMouseRangeToClient();
4105 window.UpdateDecorations();
4108 else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp)
4110 // Log("\n*** LEFT BUTTON UP ***\n");
4111 if(guiApp.windowMoving)
4112 guiApp.windowMoving.StopMoving();
4114 else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp)
4116 if(guiApp.windowScrolling)
4118 Window windowScrolling = guiApp.windowScrolling;
4119 guiApp.windowScrolling = null;
4120 windowScrolling.ReleaseCapture();
4124 if(!result || (window && window.destroyed)) window = null;
4126 if(window && window.FindModal())
4129 if(trueWindow && trueWindow.FindModal())
4137 msgWindow = GetAtPosition(x,y, true, false);
4139 msgWindow.SelectMouseCursor();
4142 if(guiApp.windowCaptured || trueWindow)
4144 Window prevWindow = guiApp.prevWindow;
4145 if(guiApp.prevWindow && trueWindow != guiApp.prevWindow)
4147 guiApp.prevWindow.mouseInside = false;
4148 guiApp.prevWindow = null;
4150 // Eventually fix this not to include captured?
4151 if(!prevWindow.OnMouseLeave(*mods))
4154 if(result && trueWindow && !trueWindow.destroyed/* && trueWindow == window*/)
4156 Box box = trueWindow.box;
4157 box.left += trueWindow.absPosition.x;
4158 box.right += trueWindow.absPosition.x;
4159 box.top += trueWindow.absPosition.y;
4160 box.bottom += trueWindow.absPosition.y;
4162 if(box.IsPointInside({x, y}) && trueWindow != /*guiApp.*/prevWindow /*!trueWindow.mouseInside*/)
4164 int overX = x - (trueWindow.absPosition.x + trueWindow.clientStart.x);
4165 int overY = y - (trueWindow.absPosition.y + trueWindow.clientStart.y);
4167 overX = Max(Min(overX, 32767),-32768);
4168 overY = Max(Min(overY, 32767),-32768);
4170 trueWindow.mouseInside = true;
4171 if(!trueWindow.OnMouseOver(overX, overY, *mods))
4175 if(trueWindow && trueWindow._refCount > 1 && !trueWindow.destroyed)
4176 guiApp.prevWindow = trueWindow;
4178 guiApp.prevWindow = null;
4180 SelectMouseCursor();
4182 if(window && !guiApp.windowMoving && !wasMoving && !wasScrolling)
4184 int clientX = x - (window.absPosition.x + window.clientStart.x);
4185 int clientY = y - (window.absPosition.y + window.clientStart.y);
4187 bool (* MouseMethod)(Window instance, int x, int y, Modifiers mods);
4189 clientX = Max(Min(clientX, 32767),-32768);
4190 clientY = Max(Min(clientY, 32767),-32768);
4192 MouseMethod = (void *)window._vTbl[method];
4194 if(MouseMethod /*&& !consequential*/ && !window.disabled)
4197 if(!MouseMethod(window, clientX, clientY, *mods))
4204 if(result && w && w.clickThrough && w.parent)
4209 if(!result || !w || !w.clickThrough)
4216 // --- Mouse cursor management ---
4218 bool KeyMessage(uint method, Key key, unichar character)
4223 if(guiApp.interimWindow)
4224 this = guiApp.interimWindow;
4227 if((SmartKey)key != alt && (SmartKey)key != Key::control && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown && parent && this != parent.menuBar)
4231 if(!style.inactive || rootWindow != this)
4233 bool (*KeyMethod)(Window window, Key key, unichar ch) = (void *)_vTbl[method];
4234 Window modalWindow = FindModal();
4235 Window interimMaster = master ? master.rootWindow : null;
4239 if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4240 status = OnSysKeyDown(key, character);
4241 else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit)
4242 status = OnSysKeyHit(key, character);
4243 else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp)
4244 status = OnSysKeyUp(key, character);
4251 // Process Key Message for Internal UI Keyboard actions
4252 if(status && !destroyed && menuBar && state != minimized)
4255 if((SmartKey)key != alt)
4256 menuBar.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, 0, 0);
4259 SmartKey sk = (SmartKey) key;
4260 if((character && !key.alt && !key.ctrl) || sk == left || sk == right || sk == up || sk == down || sk == home || sk == end || sk == escape || sk == alt)
4262 status = menuBar.KeyMessage(method, key, character);
4267 if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4268 menuBar.OnKeyHit(escape, 0);
4270 if(!menuBar.focus && guiApp.caretOwner)
4271 guiApp.caretOwner.UpdateCaret(true, false);
4274 if(!destroyed && status)
4276 if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit || method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4280 case left: case up: case right: case down:
4281 if(guiApp.windowMoving == this)
4284 int w = guiApp.windowMoving.size.w;
4285 int h = guiApp.windowMoving.size.h;
4286 int x = guiApp.windowMoving.scrolledPos.x;
4287 int y = guiApp.windowMoving.scrolledPos.y;
4291 if(key == down || key == up)
4292 step = Max(step, textCellH);
4294 step = Max(step, textCellW);
4297 if(guiApp.windowIsResizing)
4301 case left: w-=step; break;
4302 case right: w+=step; break;
4303 case up: h-=step; break;
4304 case down: h+=step; break;
4311 case left: x-=step; break;
4312 case right: x+=step; break;
4313 case up: y-=step; break;
4314 case down: y+=step; break;
4318 if(guiApp.resizeX) x += w - guiApp.windowMoving.size.w;
4319 if(guiApp.resizeY) y += h - guiApp.windowMoving.size.h;
4321 if(!guiApp.windowIsResizing || guiApp.resizeX)
4322 x = (x - guiApp.windowMovingBefore.x) + guiApp.windowMovingStart.x;
4324 x = (w - guiApp.windowResizingBefore.w) + guiApp.windowMovingStart.x;
4326 if(!guiApp.windowIsResizing || guiApp.resizeY)
4327 y = (y - guiApp.windowMovingBefore.y) + guiApp.windowMovingStart.y;
4329 y = (h - guiApp.windowResizingBefore.h) + guiApp.windowMovingStart.y;
4331 guiApp.interfaceDriver.SetMousePosition(x, y);
4332 ConsequentialMouseMove(true);
4340 if(guiApp.windowMoving && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4342 guiApp.windowMoving.StopMoving();
4343 ConsequentialMouseMove(false);
4351 ShowSysMenu(absPosition.x, absPosition.y);
4359 if(!destroyed && status && state != minimized)
4361 // Process all the way down the children
4362 if(activeChild && !activeChild.disabled)
4364 status = activeChild.KeyMessage(method, key, character);
4366 if(status && activeClient && activeChild != activeClient && !activeClient.disabled && (key.alt || key.ctrl) &&
4367 key.code != left && key.code != right && key.code != up && key.code != down)
4369 status = activeClient.KeyMessage(method, key, character);
4373 if(!destroyed && status && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4375 if((SmartKey)key == enter && !key.alt && !key.ctrl && defaultControl && !defaultControl.disabled && state != minimized)
4376 // && defaultControl != activeChild)
4378 delete previousActive;
4379 previousActive = activeChild;
4380 if(previousActive) incref previousActive;
4382 ConsequentialMouseMove(false);
4383 if((defaultControl.active ||
4384 defaultControl.ActivateEx(true, true, false, true, null, null)) && !defaultControl.disabled)
4385 defaultControl.KeyMessage(method, defaultKey, character);
4391 if(!destroyed && status && (!modalWindow || this == guiApp.desktop))
4393 if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4400 ShowSysMenu(absPosition.x, absPosition.y);
4407 if(this != guiApp.desktop)
4409 if(!guiApp.windowMoving && !guiApp.windowCaptured)
4411 if(state != maximized && (key.shift ? style.sizeable : style.fixed))
4413 MenuMoveOrSize(key.shift, true);
4417 else if(guiApp.windowMoving)
4419 guiApp.windowMoving.StopMoving();
4420 ConsequentialMouseMove(false);
4428 if(!destroyed && status && state != minimized)
4430 if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit || method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4434 case tab: case shiftTab:
4436 Window cycleParent = this;
4437 if(this == guiApp.interimWindow && !master.style.interim && !cycleParent.style.tabCycle)
4438 cycleParent = master.parent;
4440 if(!guiApp.windowCaptured && cycleParent.style.tabCycle)
4442 if(cycleParent.CycleChildren(!key.shift, false, false, true))
4444 Window child = cycleParent.activeChild;
4446 // Scroll the window to include the active control
4448 if(cycleParent.sbh && !child.style.dontScrollHorz)
4450 if(child.scrolledPos.x < 0)
4451 cycleParent.sbh.Action(Position,
4452 cycleParent.scroll.x + child.scrolledPos.x, 0);
4453 else if(child.scrolledPos.x + child.size.w > cycleParent.clientSize.w)
4454 cycleParent.sbh.Action(Position,
4455 cycleParent.scroll.x + child.scrolledPos.x + child.size.w - cycleParent.clientSize.w, 0);
4457 if(cycleParent.sbv && !child.style.dontScrollVert)
4459 if(child.scrolledPos.y < 0)
4460 cycleParent.sbv.Action(Position,
4461 cycleParent.scroll.y + child.scrolledPos.y, 0);
4462 else if(child.scrolledPos.y + child.size.w > window.clientSize.h)
4463 cycleParent.sbv.Action(Position,
4464 cycleParent.scroll.y + child.scrolledPos.y+child.size.h - cycleParent.clientSize.h, 0);
4467 cycleParent.ConsequentialMouseMove(false);
4473 case f6: case shiftF6:
4474 if(!guiApp.windowMoving /*!guiApp.windowCaptured*/)
4476 // NOT NEEDED... guiApp.windowMoving.ReleaseCapture();
4477 if(parent == guiApp.desktop)
4478 if(guiApp.desktop.CycleChildren(key.shift, true, false, true))
4488 if(CycleChildren(key.shift, true, false, true))
4496 // mIRC Style Window Shortcuts
4497 case alt1: case alt2: case alt3: case alt4: case alt5:
4498 case alt6: case alt7: case alt8: case alt9: case alt0:
4503 for(document = children.first; document; document = document.next)
4505 if(document.style.isDocument && document.documentID - 1 == key.code - k1)
4507 if(document == activeChild)
4509 if(document.state == minimized)
4510 document.SetState(normal, false, key);
4513 document.SetState(minimized, false, key);
4514 CycleChildren(false, true, false);
4519 if(activeChild.state == maximized && document.style.hasMaximize)
4520 document.SetState(maximized, false, key);
4521 else if(document.state == minimized)
4522 document.SetState(normal, false, key);
4523 document.Activate();
4538 if(!destroyed && status)
4540 if(state == minimized)
4545 if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp)
4547 if((SmartKey)key == enter && !key.alt && !key.ctrl && defaultControl && previousActive)
4549 if(defaultControl.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, key, character))
4550 previousActive.ActivateEx(true, false, false, true, null, null);
4551 delete previousActive;
4557 if(!destroyed && status)
4559 status = ProcessHotKeys(method, key, character);
4561 if(!destroyed && status && !modalWindow && state != minimized)
4564 status = KeyMethod(this, key, character);
4565 if(!destroyed && status && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4566 status = OnKeyHit(key, character);
4567 if(!destroyed && status && (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown || method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit))
4569 bool result = false;
4572 case ctrlUp: case ctrlDown:
4573 if(sbv && !guiApp.windowScrolling)
4574 result = sbv.Action((key == ctrlUp) ? up : down, 0, key);
4576 case wheelUp: case wheelDown:
4577 if(sbv && !guiApp.windowScrolling)
4579 result = sbv.Action((key == wheelUp) ? wheelUp : wheelDown, 0, key);
4580 // Do we want to do a consequential move regardless of result in this case?
4581 ConsequentialMouseMove(false);
4584 case ctrlPageUp: case ctrlPageDown:
4585 if(sbh && !guiApp.windowScrolling)
4586 result = sbh.Action((key == ctrlPageUp) ? up : down, 0, key);
4591 ConsequentialMouseMove(false);
4596 if(status && !destroyed && menuBar && state != minimized)
4597 status = menuBar.KeyMessage(method, key, character);
4599 if(style.interim && /*destroyed && */status && interimMaster)
4601 // Testing this... for Ctrl-O to open dialog when autocompletion listbox is popped...
4602 status = interimMaster.KeyMessage(method, key, character);
4609 bool ProcessHotKeys(uint method, Key key, unichar character)
4614 for(hotKey = hotKeys.first; hotKey; hotKey = hotKey.next)
4615 if((hotKey.key == key || (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp && hotKey.key.code == key.code)) &&
4616 !hotKey.window.disabled && (hotKey.window.style.nonClient || state != minimized))
4618 Window hotKeyWindow = hotKey.window;
4619 Window parent = hotKeyWindow.parent;
4620 Window prevActiveWindow = activeChild;
4622 // Don't process non-visible buttons, but make an exception for the Alt-F4 with Native Decorations turned on
4623 if(hotKeyWindow.style.hidden && (!hotKeyWindow.style.nonClient || !parent || !parent.nativeDecorations || (hotKeyWindow != parent.sysButtons[2] && hotKeyWindow != parent.sysButtons[1] )))
4626 if(prevActiveWindow) incref prevActiveWindow;
4627 incref hotKeyWindow;
4628 if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown && !hotKeyWindow.style.nonClient)
4629 if(!hotKeyWindow.ActivateEx(true, true, false, true, null, null))
4632 delete hotKeyWindow;
4633 delete prevActiveWindow;
4637 if(hotKeyWindow.style.nonClient && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit)
4638 method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
4639 if(!hotKeyWindow.KeyMessage(method, Key::hotKey, character))
4641 // ********* WORKING ON THIS ***********
4642 if(prevActiveWindow && !guiApp.interimWindow)
4643 prevActiveWindow.ActivateEx(true, false, false, false, null, null);
4646 else if(hotKeyWindow.style.inactive)
4647 status = hotKeyWindow.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, Key::hotKey, character);
4649 delete prevActiveWindow;
4650 delete hotKeyWindow;
4651 // For Key Ups, don't set status to false... (e.g.: Releasing Enter vs AltEnter hot key)
4652 if(method != __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp)
4656 if(status && tabCycle)
4659 for(child = children.first; child; child = child.next)
4661 if(child.tabCycle && !child.ProcessHotKeys(method, key, character))
4672 // --- Windows and graphics initialization / termination ---
4673 bool SetupRoot(void)
4677 // Setup relationship with outside world (bb root || !bb)
4678 if((!guiApp.fullScreenMode && parent == guiApp.desktop) || this == guiApp.desktop ||
4679 (_displayDriver && dispDriver != parent.dispDriver))
4683 tempExtents = new0 Extent[4];
4688 /*if(guiApp.fullScreenMode)
4689 rootWindow = guiApp.desktop;
4691 //rootWindow = parent.created ? parent.rootWindow : null;
4692 rootWindow = parent.rootWindow;
4695 against = &parent.box;
4697 against = &parent.clientArea;
4700 for(child = children.first; child; child = child.next)
4703 return (rootWindow && (rootWindow == this || rootWindow.created)) ? true : false;
4706 bool Setup(bool positionChildren)
4708 bool result = false;
4711 if((!guiApp.fullScreenMode && parent == guiApp.desktop) || (guiApp.fullScreenMode && (this == guiApp.desktop || (_displayDriver && dispDriver != parent.dispDriver))))
4713 subclass(DisplayDriver) dDriver = (dispDriver && !formDesigner) ? dispDriver : GetDisplayDriver(guiApp.defaultDisplayDriver);
4714 DisplaySystem displaySystem = dDriver ? dDriver.displaySystem : null;
4716 windowHandle = dDriver.printer ? null : guiApp.interfaceDriver.CreateRootWindow(this);
4718 // This was here, is it really needed?
4719 //guiApp.interfaceDriver.ActivateRootWindow(this);
4723 displaySystem = DisplaySystem {};
4724 if(!displaySystem.Create(dDriver.name, guiApp.fullScreenMode ? windowHandle : windowHandle /*null*/, guiApp.fullScreenMode))
4726 delete displaySystem;
4731 display = Display { alphaBlend = alphaBlend, useSharedMemory = useSharedMemory, windowDriverData = windowData };
4732 if(display.Create(displaySystem, windowHandle))
4739 guiApp.interfaceDriver.SetIcon(this, icon);
4741 else if(this != guiApp.desktop)
4743 display = rootWindow ? rootWindow.display : null;
4749 if(guiApp.acquiredWindow && rootWindow == guiApp.acquiredWindow.rootWindow)
4750 guiApp.interfaceDriver.AcquireInput(guiApp.acquiredWindow.rootWindow, true);
4752 for(child = children.first; child; child = child.next)
4754 if(child.created && !child.Setup(false))
4760 bool SetupDisplay(void)
4762 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
4763 if(is3D) return Window3D_SetupDisplay(this); else
4770 class_data void ** pureVTbl;
4772 bool LoadGraphics(bool creation, bool resetAnchors)
4774 bool result = false;
4775 bool success = false;
4777 WindowState stateBackup = state;
4780 if(!rootWindow.created)
4784 if(((subclass(Window))_class).pureVTbl)
4786 if(_vTbl == _class._vTbl)
4788 _vTbl = ((subclass(Window))_class).pureVTbl;
4793 for(m = 0; m < _class.vTblSize; m++)
4795 if(_vTbl[m] == _class._vTbl[m])
4796 _vTbl[m] = ((subclass(Window))_class).pureVTbl[m];
4800 if(guiApp.currentSkin && ((subclass(Window))_class).pureVTbl)
4802 if(_vTbl == ((subclass(Window))_class).pureVTbl)
4804 _vTbl = _class._vTbl;
4809 for(m = 0; m < _class.vTblSize; m++)
4811 if(_vTbl[m] == ((subclass(Window))_class).pureVTbl[m])
4812 _vTbl[m] = _class._vTbl[m];
4817 if(guiApp.fullScreenMode || this != guiApp.desktop)
4819 SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
4825 display.Lock(false);
4826 if(rootWindow == this)
4828 // Set Color Palette
4829 display.SetPalette(palette, true);
4833 if(guiApp.fullScreenMode && this == guiApp.desktop)
4838 for(c=0; c<SystemCursor::enumSize; c++)
4839 if(!guiApp.systemCursors[c].bitmap)
4841 guiApp.systemCursors[c].bitmapName = guiApp.currentSkin.CursorsBitmaps(c,
4842 &guiApp.systemCursors[c].hotSpotX,&guiApp.systemCursors[c].hotSpotY, &guiApp.systemCursors[c].paletteShades);
4843 if(guiApp.systemCursors[c].bitmapName)
4845 guiApp.systemCursors[c].bitmap = eBitmap_LoadT(guiApp.systemCursors[c].bitmapName, null,
4846 guiApp.systemCursors[c].paletteShades ? null : guiApp.desktop.display.displaySystem);
4847 if(guiApp.systemCursors[c].bitmap)
4848 guiApp.systemCursors[c].bitmap.paletteShades = guiApp.systemCursors[c].paletteShades;
4853 for(cursor = guiApp.customCursors.first; cursor; cursor = cursor.next)
4855 cursor.bitmap = eBitmap_LoadT(cursor.bitmapName, null,
4856 cursor.paletteShades ? null : guiApp.desktop.display.displaySystem);
4858 cursor.bitmap.paletteShades = cursor.paletteShades;
4862 guiApp.cursorUpdate = true;
4865 ConsequentialMouseMove(false);
4871 // Load Window Graphic Resources
4874 if(usedFont == setFont || usedFont == window.systemFont)
4875 RemoveResource(usedFont);
4878 RemoveResource(setFont); // TESTING setFont instead of usedFont);
4881 RemoveResource(systemFont);
4884 RemoveResource(captionFont);
4886 for(ptr = resources.first; ptr; ptr = ptr.next)
4888 ptr.loaded = display.displaySystem.LoadResource(ptr.resource);
4891 AddResource(setFont);
4893 AddResource(systemFont);
4895 usedFont = setFont ? setFont : ((parent && parent.parent) ? parent.usedFont : systemFont);
4902 //if(master && master.font)
4903 if(parent && parent.font)
4907 faceName = parent.font.faceName,
4908 size = parent.font.size,
4909 bold = parent.font.bold,
4910 italic = parent.font.italic,
4911 underline = parent.font.underline
4913 //font = parent.font;
4914 watch(parent) { font { } };
4917 font = guiApp.currentSkin.SystemFont();
4924 captionFont = guiApp.currentSkin.CaptionFont();
4925 AddResource(captionFont);
4927 if(OnLoadGraphics())
4933 //SetScrollLineStep(sbStep.x, sbStep.y);
4935 if(this != guiApp.desktop)
4939 normalAnchor = anchor;
4940 normalSizeAnchor = sizeAnchor;
4943 // Break the anchors for moveable/resizable windows
4945 if(style.fixed && style.isDocument)
4947 ComputeAnchors(ax, ay, aw, ah, &x, &y, &w, &h);
4959 stateAnchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
4960 stateSizeAnchor = SizeAnchor {};
4965 int maxIcons = parent.clientSize.w / MINIMIZED_WIDTH;
4970 left = (iconID % maxIcons) * MINIMIZED_WIDTH,
4971 bottom = (iconID / maxIcons) * (guiApp.textMode ? 16 : 24)
4974 stateSizeAnchor = SizeAnchor { size.w = MINIMIZED_WIDTH };
4978 stateAnchor = normalAnchor;
4979 stateSizeAnchor = normalSizeAnchor;
4982 position = Point { };
4983 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
4994 if(Position(x, y, w, h, true, false, true, true, true, true))
4996 if((this != guiApp.desktop || guiApp.fullScreenMode) && rootWindow == this)
4999 guiApp.interfaceDriver.SetRootWindowState(this, normal, true);
5016 success = result = true;
5019 if(!creation && result)
5021 // Load menu bar first because sys buttons are on it...
5024 if(!menuBar.LoadGraphics(false, resetAnchors))
5030 for(child = children.first; child; child = child.next)
5032 if(child.created && child != menuBar && !child.LoadGraphics(false, resetAnchors))
5039 CreateSystemChildren();
5043 if(this == guiApp.desktop && !guiApp.fullScreenMode)
5046 guiApp.interfaceDriver.ActivateRootWindow(activeChild);
5051 //guiApp.LogErrorCode(IERR_GRAPHICS_LOADING_FAILED, caption);
5052 guiApp.LogErrorCode(IERR_GRAPHICS_LOADING_FAILED, class.name);
5055 // Do this here to avoid problems on Windows
5056 if(stateBackup == maximized)
5057 property::state = maximized;
5061 void UnloadGraphics(bool destroyWindows)
5065 // Free children's graphics
5066 for(child = children.first; child; child = child.next)
5067 child.UnloadGraphics(destroyWindows);
5070 display.Lock(false);
5073 if(guiApp.fullScreenMode && this == guiApp.desktop)
5078 for(c=0; c<SystemCursor::enumSize; c++)
5079 if(guiApp.systemCursors[c].bitmap)
5080 delete guiApp.systemCursors[c].bitmap;
5082 for(cursor = guiApp.customCursors.first; cursor; cursor = cursor.next)
5083 delete cursor.bitmap;
5085 guiApp.cursorBackground.Free();
5088 if(display && display.displaySystem)
5092 for(ptr = resources.first; ptr; ptr = ptr.next)
5096 display.displaySystem.UnloadResource(ptr.resource, ptr.loaded);
5101 // Free window graphics
5104 // Free skin graphics
5105 if(rootWindow == this)
5107 DisplaySystem displaySystem = display.displaySystem;
5110 display.driverData = null;
5111 display.displaySystem = null;
5115 if(displaySystem && !displaySystem.numDisplays && !is3D)
5116 delete displaySystem;
5125 if(guiApp.acquiredWindow && this == guiApp.acquiredWindow.rootWindow)
5126 guiApp.interfaceDriver.AcquireInput(guiApp.acquiredWindow.rootWindow, false);
5128 if(this == guiApp.desktop || parent == guiApp.desktop)
5130 if((guiApp.fullScreenMode || this != guiApp.desktop) && rootWindow == this && windowHandle && destroyWindows)
5131 guiApp.interfaceDriver.DestroyRootWindow(this);
5135 // --- Window Hiding ---
5137 void SetVisibility(bool state)
5139 bool visible = (style.hidden || !created) ? false : state;
5140 if(visible != this.visible)
5144 this.visible = visible;
5145 for(child = children.first; child; child = child.next)
5146 child.SetVisibility(visible);
5148 ConsequentialMouseMove(false);
5149 if(parent && !nonClient) parent.OnChildVisibilityToggled(this, visible);
5153 // --- Windows and graphics initialization / termination ---
5155 bool DisplayModeChanged(void)
5157 bool result = false;
5158 if(!guiApp.fullScreenMode && !guiApp.modeSwitching/* && guiApp.desktop.active*/)
5160 guiApp.modeSwitching = true;
5161 UnloadGraphics(false);
5163 if(LoadGraphics(false, false))
5165 guiApp.modeSwitching = false;
5170 // --- Window updates system ---
5172 void UpdateDirty(Box updateBox)
5174 if(!manageDisplay) { OnRedraw(null);return; }
5177 if(display && (!guiApp.fullScreenMode || guiApp.desktop.active) && !guiApp.modeSwitching)
5180 if(display.flags.flipping)
5183 rootWindow.UpdateDisplay();
5186 UpdateBackDisplay(updateBox);
5188 if(guiApp.fullScreenMode)
5190 guiApp.cursorUpdate = true;
5191 guiApp.PreserveAndDrawCursor();
5193 if(guiApp.fullScreenMode)
5194 guiApp.RestoreCursorBackground();
5200 // This function is strictly called as a result of system window activation
5201 bool ExternalActivate(bool active, bool activateRoot, Window window, Window swap)
5204 Window interimMaster = null;
5205 Window interimWindow = guiApp.interimWindow;
5206 if(interimWindow && interimWindow.master)
5207 interimMaster = interimWindow.master.rootWindow;
5209 if(active && state == minimized) // && (!window.nativeDecorations || window.rootWindow != window)
5210 // SetState(normal, false, 0);
5211 SetState(lastState, false, 0);
5213 if(interimMaster && swap == interimMaster && interimMaster.IsSlaveOf(window))
5217 /* WTH is this doing here?
5218 while(swap && swap.activeChild)
5220 swap = swap.activeChild;
5223 // TESTING THIS BEFORE...
5224 if(interimWindow && this == interimMaster)
5228 // Window interimSwap = this;
5229 Window menuBar = this.menuBar;
5230 if(menuBar && interimWindow.master == menuBar)
5233 while(interimSwap && interimSwap.activeChild)
5234 interimSwap = interimSwap.activeChild;
5236 result = interimWindow.ActivateEx(false, false, false, activateRoot, null,
5237 (menuBar && interimWindow.master == menuBar) ? menuBar : interimSwap);
5239 result = /*interimWindow.*/ActivateEx(false, false, false, activateRoot, null, menuBar);
5240 //result = ActivateEx(true, true, false, activateRoot, window, null);
5245 // Testing & FindModal() here: broke reactivating when a modal dialog is up (didn't root activate dialog)
5246 result = ActivateEx(active, active, false, activateRoot /*&& FindModal()*/, window, swap);
5248 if(interimWindow == this && interimMaster && !active)
5250 while(interimMaster && interimMaster.interim && interimMaster.master)
5252 // printf("Going up one master %s\n", interimMaster._class.name);
5253 interimMaster = interimMaster.master.rootWindow;
5255 // printf("Unactivating interim master %s (%x)\n", interimMaster._class.name, interimMaster);
5256 interimMaster.ActivateEx(active, active, false, activateRoot, window, swap);
5262 bool DestroyEx(int returnCode)
5265 Timer timer, nextTimer;
5267 OldLink prevOrder = null;
5268 Window client = null;
5270 if(parent) stopwatching(parent, font);
5272 // if(window.modalSlave) return false;
5273 if(destroyed || !created)
5280 OldLink slave = master.slaves.FindLink(this);
5281 master.slaves.Delete(slave);
5284 // TOFIX IMMEDIATELY: COMMENTED THIS OUT... causes problem second time creating file dialog
5290 this.returnCode = (DialogResult)returnCode;
5292 AcquireInput(false);
5297 master.hotKeys.Delete(hotKey);
5301 if(guiApp.prevWindow == this)
5303 guiApp.prevWindow = null;
5306 if(guiApp.caretOwner == this)
5308 guiApp.interfaceDriver.SetCaret(0,0,0);
5309 UpdateCaret(false, true);
5310 guiApp.caretEnabled = false;
5315 parent.childrenCycle.Remove(cycle);
5319 OldLink tmpPrev = order.prev;
5320 if(tmpPrev && !(((Window)tmpPrev.data).style.hidden) && !(((Window)tmpPrev.data).destroyed) && (((Window)tmpPrev.data).created))
5321 prevOrder = tmpPrev;
5324 client = tmpPrev ? tmpPrev.data : null;
5325 if(client == this) { client = null; break; }
5326 if(client && (client.style.hidden || client.destroyed || !client.created))
5327 tmpPrev = client.order.prev;
5331 prevOrder = tmpPrev;
5336 // If this window can be an active client, make sure the next window we activate can also be one
5337 if(!style.nonClient && style.isActiveClient)
5339 tmpPrev = prevOrder;
5342 client = tmpPrev ? tmpPrev.data : null;
5343 if(client == this) { client = null; break; }
5344 if(client && (client.style.nonClient || !client.style.isActiveClient || client.style.hidden || client.destroyed || !client.created))
5345 tmpPrev = client.order.prev;
5349 prevOrder = tmpPrev;
5353 if(client && client.style.hidden) client = null;
5355 // parent.childrenOrder.Remove(order);
5358 if(parent && style.isActiveClient && visible)
5360 if(state == minimized) parent.numIcons--;
5361 parent.numPositions--;
5364 // TESTING THIS HERE!
5368 // If no display, don't bother deactivating stuff (causes unneeded problems when trying
5369 // to create a window inside a rootwindow that's being destroyed)
5370 // DISABLED THIS BECAUSE OF CREATING WINDOW IN DESKTOP IN WINDOWED MODE
5372 if(master && !master.destroyed /*&&
5373 rootWindow && rootWindow.display && !rootWindow.destroyed*/)
5375 if(master.defaultControl == this)
5376 master.defaultControl = null;
5378 if(parent && !parent.destroyed /*&&
5379 rootWindow && rootWindow.display && !rootWindow.destroyed*/)
5381 if((parent.activeChild == this /*|| parent.activeClient == this */|| guiApp.interimWindow == this))
5383 if(order && prevOrder && prevOrder.data != this && active)
5385 //((Window)prevOrder.data).ActivateEx(true, false, false, false /*true*/, null);
5387 ((Window)prevOrder.data).ActivateEx(true, false, false, (rootWindow == this) ? true : false, null, null);
5388 if(parent.activeClient == this)
5390 parent.activeClient = null;
5391 parent.UpdateActiveDocument(null);
5396 if(guiApp.interimWindow == this)
5399 PropagateActive(false, null, &goOn, true);
5403 //if(window.parent.activeChild == window)
5404 parent.activeChild = null;
5405 if(!style.nonClient /*&& style.isActiveClient*/)
5407 Window previous = parent.activeClient;
5408 if(style.isActiveClient)
5409 parent.activeClient = null;
5410 parent.UpdateActiveDocument(previous);
5415 else if(parent.activeClient == this)
5417 parent.activeClient = client;
5418 parent.UpdateActiveDocument(this);
5422 if(guiApp.interimWindow == this)
5424 guiApp.interimWindow = null;
5425 if(guiApp.caretOwner)
5427 Window desktop = guiApp.desktop;
5428 if(desktop.activeChild && desktop.activeChild.menuBar && !desktop.activeChild.menuBar.focus)
5429 guiApp.caretOwner.UpdateCaret(false, false);
5434 if(_isModal && master && master.modalSlave == this)
5435 master.modalSlave = null;
5439 if(!guiApp.caretOwner && parent.caretSize)
5441 guiApp.caretOwner = parent;
5442 parent.UpdateCaret(false, false);
5443 parent.Update(null);
5446 // Why was this commented out?
5447 GetRidOfVirtualArea();
5453 dirtyArea.Free(null);
5454 dirtyBack.Free(null);
5455 scrollExtent.Free(null);
5457 /* ATTEMPTING TO MOVE THAT ABOVE
5466 //for(child = window.children.first; next = child ? child.next : null, child; child = next)
5467 for(;(child = window.children.first);)
5469 for(; child && (child.destroyed || !child.created); child = child.next);
5478 UnloadGraphics(true);
5481 delete previousActive;
5484 // statusBar = null;
5487 if(master && !master.destroyed)
5489 //master.NotifyDestroyed(this, this.returnCode);
5490 NotifyDestroyed(master, this, this.returnCode);
5493 for(timer = guiApp.windowTimers.first; timer; timer = nextTimer)
5495 nextTimer = timer.next;
5496 if(timer.window == this)
5498 // WHY WERE WE SETTING THIS TO NULL? NO MORE WINDOW WHEN RECREATING...
5499 // timer.window = null;
5505 if(this == guiApp.windowMoving)
5508 if(guiApp.windowCaptured == this)
5510 //guiApp.windowCaptured = null;
5512 if(rootWindow != this && rootWindow)
5513 rootWindow.ConsequentialMouseMove(false);
5521 //for(child = children.first; next = child ? child.next : null, child; child = next)
5522 for(;(child = children.first); )
5524 for(; child && (child.destroyed || !child.created); child = child.next);
5534 /* // MOVED THIS UP...
5537 //for(child = window.children.first; next = child ? child.next : null, child; child = next)
5538 for(;(child = window.children.first); )
5540 for(; child && (child.destroyed || !child.created); child = child.next);
5549 while((slave = slaves.first))
5551 for(; slave && (((Window)slave.data).destroyed || !((Window)slave.data).created); slave = slave.next);
5553 ((Window)slave.data).DestroyEx(0);
5558 if(guiApp.caretOwner == this)
5559 guiApp.caretOwner = null;
5561 sysButtons[0] = null;
5562 sysButtons[1] = null;
5563 sysButtons[2] = null;
5566 if(rootWindow != this)
5568 Box box { scrolledPos.x, scrolledPos.y, scrolledPos.x + size.w - 1, scrolledPos.y + size.h - 1 };
5571 box.left -= parent.clientStart.x;
5572 box.top -= parent.clientStart.y;
5573 box.right -= parent.clientStart.x;
5574 box.bottom -= parent.clientStart.y;
5576 if(parent) parent.Update(box);
5581 OldLink slave = master.slaves.FindVoid(this);
5582 master.slaves.Delete(slave);
5588 parent.children.Remove(this);
5593 //autoCreate = false;
5596 // SHOULD THIS BE HERE? FIXED CRASH WITH GOTO DIALOG
5597 if(((subclass(Window))_class).pureVTbl)
5599 if(_vTbl == _class._vTbl)
5601 _vTbl = ((subclass(Window))_class).pureVTbl;
5606 for(m = 0; m < _class.vTblSize; m++)
5608 if(_vTbl[m] == _class._vTbl[m])
5609 _vTbl[m] = ((subclass(Window))_class).pureVTbl[m];
5618 void SetStateEx(WindowState newState, bool activate)
5621 WindowState prevState = state;
5625 if(prevState != newState)
5626 lastState = prevState;
5628 if(rootWindow != this || !nativeDecorations)
5630 if(style.isActiveClient && !style.hidden && prevState == minimized)
5633 // This block used to be at the end of the function... moved it for flicker problem in X
5634 // ------------------------------------------------------
5638 stateAnchor = normalAnchor;
5639 stateSizeAnchor = normalSizeAnchor;
5642 stateAnchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
5643 stateSizeAnchor = SizeAnchor {};
5647 int maxIcons = parent.clientSize.w / MINIMIZED_WIDTH;
5650 byte * idBuffer = new0 byte[size];
5652 for(child = parent.children.first; child; child = child.next)
5654 if(child != this && child.state == minimized)
5656 if(child.iconID > size - 2)
5658 idBuffer = renew0 idBuffer byte[size*2];
5659 memset(idBuffer + size, 0, size);
5662 idBuffer[child.iconID] = (byte)bool::true;
5665 for(c = 0; c<size; c++)
5670 if(style.isActiveClient && !style.hidden)
5673 stateAnchor = Anchor { left = (iconID % maxIcons) * MINIMIZED_WIDTH, bottom = (iconID / maxIcons) * (guiApp.textMode ? 16 : 24) };
5674 stateSizeAnchor = SizeAnchor { size.w = MINIMIZED_WIDTH };
5678 // TOCHECK: Why was this here?
5679 //position.x = (tx > 0) ? tx & 0xFFFFF : tx;
5680 //position.y = (ty > 0) ? ty & 0xFFFFF : ty;
5681 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
5683 Position(x, y, w, h, true, true, true, true, false, true);
5685 if(!style.inactive && !style.interim && this == parent.activeClient)
5686 parent.UpdateActiveDocument(null);
5689 CreateSystemChildren();
5690 // ------------------------------------------------------
5693 int GetPositionID(Window forChild)
5697 byte * idBuffer = new0 byte[size];
5700 for(child = children.first; child; child = child.next)
5702 if(child.style.isActiveClient && !child.style.hidden && child != forChild)
5704 if(child.positionID > size - 2)
5706 idBuffer = renew0 idBuffer byte[size*2];
5707 memset(idBuffer + size, 0, size);
5710 idBuffer[child.positionID] = (byte)bool::true;
5713 for(c = 0; c<size; c++)
5720 // --- Window related graphics ---
5722 void SetPalette(ColorAlpha * newPalette, bool colorMatch)
5724 palette = newPalette;
5725 if(rootWindow.display)
5726 rootWindow.display.SetPalette(palette, colorMatch);
5729 public bool AcquireInput(bool acquired)
5732 if(acquiredInput != acquired)
5734 if(active || (!visible && creationActivation == activate))
5735 result = AcquireInputEx(acquired);
5740 acquiredInput = acquired ? result : !result;
5745 void ListChildren(ListBox listBox)
5749 for(child = children.first; child; child = child.next)
5751 if(child.cycle && !child.style.nonClient && child.style.isActiveClient && child.visible)
5753 DataRow row = listBox.AddRow();
5754 row.tag = (int)child;
5755 child.FigureCaption(caption);
5756 row.SetData(null, caption);
5761 void UpdateVisual(Box extent)
5763 if(guiApp.driver != null)
5765 if(guiApp.fullScreenMode && guiApp.desktop.display)
5767 guiApp.desktop.mutex.Wait();
5768 guiApp.desktop.display.Lock(true);
5771 if(guiApp.desktop.active)
5773 if(guiApp.desktop.dirty || guiApp.cursorUpdate)
5775 if(guiApp.desktop.display.flags.flipping)
5776 guiApp.desktop.Update(null);
5777 guiApp.desktop.UpdateDisplay();
5778 guiApp.cursorUpdate = true;
5780 if(guiApp.cursorUpdate || guiApp.desktop.dirty)
5782 guiApp.PreserveAndDrawCursor();
5783 // guiApp.desktop.display.ShowScreen();
5784 guiApp.cursorUpdate = false;
5785 guiApp.desktop.dirty = false;
5786 guiApp.RestoreCursorBackground();
5790 guiApp.desktop.display.Unlock();
5791 guiApp.desktop.mutex.Release();
5795 Window rootWindow = this.rootWindow;
5796 rootWindow.mutex.Wait();
5801 guiApp.SignalEvent();
5804 guiApp.waitMutex.Wait();
5805 guiApp.interfaceDriver.Lock(rootWindow);
5806 if(!rootWindow.style.hidden && rootWindow.dirty)
5808 if(rootWindow.display)
5810 rootWindow.UpdateDisplay();
5811 //rootWindow.display.ShowScreen(null);
5813 rootWindow.dirty = false;
5815 guiApp.interfaceDriver.Unlock(rootWindow);
5816 guiApp.waitMutex.Release();
5819 rootWindow.mutex.Release();
5824 void UnlockDisplay(void)
5826 guiApp.interfaceDriver.Unlock(rootWindow);
5829 void LockDisplay(void)
5831 guiApp.interfaceDriver.Lock(rootWindow);
5834 Surface GetSurface(Box box)
5836 return Redraw((box == null) ? this.box : box);
5839 void SetMousePosition(int x, int y)
5841 guiApp.interfaceDriver.SetMousePosition(x + absPosition.x + clientStart.x, y + absPosition.y + clientStart.y);
5845 void IntegrationActivate(bool active)
5847 if(!guiApp.modeSwitching && !guiApp.fullScreenMode)
5849 isForegroundWindow = true;
5850 ActivateEx(active, active, false, false, null, null);
5851 isForegroundWindow = false;
5856 Window QueryCapture(void)
5858 return guiApp.windowCaptured;
5861 int GetDocumentID(void)
5865 byte * idBuffer = new0 byte[size];
5868 for(child = children.first; child; child = child.next)
5870 // TO CHECK: Do we want a documentID when we already have a file name?
5871 if(child.style.isDocument && !child.fileName)
5873 if(child.documentID-1 > size - 2)
5875 idBuffer = renew0 idBuffer byte[size*2];
5876 memset(idBuffer + size, 0, size);
5879 idBuffer[child.documentID-1] = 1;
5882 for(c = 0; c<size; c++)
5890 void SetInitSize(Size size)
5893 sizeAnchor.size = size;
5894 normalSizeAnchor = sizeAnchor;
5896 // Break the anchors for moveable/resizable windows
5897 if(state == normal /*|| state == Hidden */) // Hidden is new here ...
5899 stateAnchor = normalAnchor;
5900 stateSizeAnchor = normalSizeAnchor;
5902 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
5903 Position(x,y, w, h, true, true, true, true, false, true);
5907 void MenuMoveOrSize(bool resize, bool setCursorPosition)
5909 if(this != guiApp.desktop && state != maximized && (resize ? (state != minimized && style.sizable) : (style.fixed || moveable)))
5911 guiApp.windowIsResizing = resize;
5912 guiApp.windowMoving = this;
5913 guiApp.windowMovingStart = guiApp.movingLast = absPosition;
5914 if(guiApp.windowIsResizing)
5916 guiApp.windowMovingStart.x += size.w - 1;
5917 guiApp.windowMovingStart.y += size.h - 1;
5919 guiApp.windowMovingBefore = scrolledPos;
5920 guiApp.windowResizingBefore = size;
5921 guiApp.windowMoving.UpdateDecorations();
5922 if(guiApp.windowIsResizing)
5923 guiApp.resizeEndX = guiApp.resizeEndY = true;
5925 if(setCursorPosition)
5926 guiApp.interfaceDriver.SetMousePosition(guiApp.windowMovingStart.x, guiApp.windowMovingStart.y);
5930 guiApp.interfaceDriver.GetMousePosition(&x, &y);
5931 guiApp.windowMovingStart.x += x - absPosition.x;
5932 guiApp.windowMovingStart.y += y - absPosition.y;
5935 if(guiApp.windowMoving)
5937 if(guiApp.windowMoving.style.nonClient)
5938 guiApp.windowMoving.parent.SetMouseRangeToWindow();
5940 guiApp.windowMoving.parent.SetMouseRangeToClient();
5945 if(this == rootWindow)
5946 guiApp.interfaceDriver.StartMoving(rootWindow, guiApp.windowMovingStart.x, guiApp.windowMovingStart.y, true);
5954 bool result = false;
5958 else if(guiApp && guiApp.driver != null)
5960 void * systemParent = null;
5961 OldLink slaveHolder;
5963 bool visible = !style.hidden;
5967 systemParent = parent;
5968 parent = guiApp.desktop;
5970 last = parent ? parent.children.last : null;
5972 if((parent && parent != guiApp.desktop && !parent.created) ||
5973 (master && master != guiApp.desktop && !master.created))
5977 property::parent = guiApp.desktop;
5978 if(!master) master = parent;
5980 if(_isModal && master.modalSlave)
5981 property::master = master.modalSlave;
5985 parent.children.Remove(this);
5988 for(slaveHolder = master.slaves.first; slaveHolder; slaveHolder = slaveHolder.next)
5989 if(slaveHolder.data == this)
5991 master.slaves.Delete(slaveHolder);
5996 if(parent == guiApp.desktop && !mutex)
5999 if(style.isDocument)
6002 parent.numDocuments--;
6003 documentID = parent.GetDocumentID();
6006 if(!style.stayOnTop)
6007 for(; last && last.style.stayOnTop; last = last.prev);
6009 parent.children.Insert((last == this) ? null : last, this);
6010 //parent.children.Add(this);
6013 dispDriver = parent.dispDriver;
6016 master.modalSlave = this;
6018 box = Box { MAXINT, MAXINT, MININT, MININT }; //-MAXINT, -MAXINT };
6023 master.slaves.Add(slaveHolder = OldLink { data = this });
6028 master.hotKeys.Add(hotKey = HotKeySlot { key = setHotKey, window = this });
6030 if(style.isDefault && !master.defaultControl)
6031 master.defaultControl = this;
6033 stateAnchor = normalAnchor = anchor;
6034 stateSizeAnchor = normalSizeAnchor = sizeAnchor;
6036 // TOCHECK: Why is this here?
6037 //position.x = (ax > 0) ? ax & 0xFFFFF : ax;
6038 //position.y = (ay > 0) ? ay & 0xFFFFF : ay;
6040 this.visible = false;
6041 style.hidden = true;
6044 // autoCreate = true;
6052 if(parent == guiApp.desktop)
6053 Log("LoadGraphics %s\n", caption);
6055 if(LoadGraphics(true, false))
6063 usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
6070 if(style.hasMenuBar /*&& menu*/)
6076 menu = menu, isMenuBar = true, anchor = Anchor { top = 23, left = 1, right = 1 },
6077 interim = false, inactive = true, nonClient = true, size.h = 24
6085 // Create the system buttons
6086 CreateSystemChildren();
6088 UpdateActiveDocument(null);
6090 if(style.isDocument)
6094 MenuItem item = menu.FindItem(MenuFileSave, 0);
6095 if(item) item.disabled = !modifiedDocument && fileName;
6100 if(parent == guiApp.desktop)
6101 Log("Preemptive SetState %s\n", caption);
6104 // Preemptive Set State to ensure proper anchoring
6105 SetStateEx(state, false);
6107 style.hidden = true;
6113 for(child = children.first; child; child = next)
6116 if(!child.created && (child.autoCreate || child.wasCreated))
6123 for(link = slaves.first; link; link = next)
6125 Window slave = link.data;
6127 if(!slave.created && (slave.autoCreate || slave.wasCreated))
6136 if(parent == guiApp.desktop)
6137 Log("Real SetState %s\n", caption);
6140 if(isActiveClient && visible)
6142 parent.numPositions--;
6143 if(state == minimized) parent.numIcons--;
6146 // Real set state & activate for proper display & activation
6147 property::visible = visible;
6148 // SetState(state & 0x00000003, true, 0);
6153 /*if(rootWindow == this)
6154 guiApp.interfaceDriver.ActivateRootWindow(this);
6156 if(creationActivation == activate)
6157 ActivateEx(true, false, true, true, null, null);
6158 else if(creationActivation == flash)
6163 rootWindow.ConsequentialMouseMove(false);
6174 guiApp.LogErrorCode(IERR_WINDOW_CREATION_FAILED, caption);
6180 // Testing this here... Otherwise a failed LoadGraphics stalls the application
6182 //style.hidden = true; // !visible;
6183 style.hidden = !visible;
6184 if(master.modalSlave == this)
6185 master.modalSlave = null;
6192 void WriteCaption(Surface surface, int x, int y)
6195 Interface::WriteKeyedTextDisabled(surface, x,y, caption, hotKey ? hotKey.key : 0, !isEnabled);
6198 void Update(Box region)
6204 rootWindow = this.rootWindow;
6206 // rootWindow.mutex.Wait();
6207 if(!destroyed && visible && display)
6212 // Testing this to avoid repetitve full update to take time...
6213 if(dirtyArea.count == 1)
6215 BoxItem item = (BoxItem)ACCESS_ITEM(dirtyArea, dirtyArea.first);
6216 if(item.box.left <= box.left &&
6217 item.box.top <= box.top &&
6218 item.box.right >= box.right &&
6219 item.box.bottom >= box.bottom)
6221 rootWindow.dirty = true;
6226 if(display.flags.flipping && !rootWindow.dirty)
6228 if(this == rootWindow)
6232 rootWindow.Update(null);
6237 rootWindow.dirty = true;
6242 realBox.left += clientStart.x;
6243 realBox.top += clientStart.y;
6244 realBox.right += clientStart.x;
6245 realBox.bottom += clientStart.y;
6251 if(realBox.right >= realBox.left &&
6252 realBox.bottom >= realBox.top)
6254 // if(!rootWindow.fullRender)
6255 dirtyArea.UnionBox(realBox, rootWindow.tempExtents[0]);
6257 for(child = children.first; child; child = child.next)
6262 box.left -= child.absPosition.x - absPosition.x;
6263 box.top -= child.absPosition.y - absPosition.y;
6264 box.right -= child.absPosition.x - absPosition.x;
6265 box.bottom -= child.absPosition.y - absPosition.y;
6266 if(box.right >= child.box.left && box.left <= child.box.right &&
6267 box.bottom >= child.box.top && box.top <= child.box.bottom)
6269 box.left -= child.clientStart.x;
6270 box.top -= child.clientStart.y;
6271 box.right -= child.clientStart.x;
6272 box.bottom -= child.clientStart.y;
6278 realBox.left += absPosition.x - rootWindow.absPosition.x;
6279 realBox.top += absPosition.y - rootWindow.absPosition.y;
6280 realBox.right += absPosition.x - rootWindow.absPosition.x;
6281 realBox.bottom += absPosition.y - rootWindow.absPosition.y;
6282 rootWindow.dirtyBack.UnionBox(realBox, rootWindow.tempExtents[0]);
6285 else if(this == guiApp.desktop)
6288 for(window = children.first; window; window = window.next)
6294 Box childBox = region;
6296 childBox.left -= window.absPosition.x - guiApp.desktop.absPosition.x;
6297 childBox.top -= window.absPosition.y - guiApp.desktop.absPosition.y;
6298 childBox.right -= window.absPosition.x - guiApp.desktop.absPosition.x;
6299 childBox.bottom -= window.absPosition.y - guiApp.desktop.absPosition.y;
6301 window.Update(childBox);
6304 window.Update(null);
6309 // rootWindow.mutex.Release();
6316 if(guiApp.windowCaptured != this)
6318 if(guiApp.windowCaptured)
6322 //Logf("Captured %s (%s)\n", caption, class.name);
6323 guiApp.interfaceDriver.SetMouseCapture(rootWindow);
6324 guiApp.windowCaptured = this;
6330 bool Destroy(int code)
6335 if(!destroyed && !CloseConfirmation(false)) return false;
6339 // TOCHECK: Should autoCreate be set to false here?
6350 void Move(int x, int y, int w, int h)
6352 normalAnchor = Anchor { left = x, top = y };
6353 normalSizeAnchor = SizeAnchor { size = { w, h } };
6355 if(state == normal /*|| state == Hidden */) // Hidden is new here ...
6357 if(destroyed) return;
6359 stateAnchor = normalAnchor;
6360 stateSizeAnchor = normalSizeAnchor;
6362 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
6363 Position(x,y, w, h, true, true, true, true, false, true);
6367 DialogResult Modal(void)
6373 // FIXES MEMORY LEAK IF Create() FAILED
6379 void SetScrollArea(int width, int height, bool snapToStep)
6381 bool resize = false;
6384 int stepX = sbStep.x, stepY = sbStep.y;
6385 // Needed to make snapped down position match the skin's check of client area
6386 // against realvirtual
6389 SNAPDOWN(stepX, textCellW);
6390 SNAPDOWN(stepY, textCellH);
6391 stepX = Max(stepX, textCellW);
6392 stepY = Max(stepY, textCellH);
6394 if(scrollFlags.snapX)
6395 SNAPUP(width, stepX);
6396 if(scrollFlags.snapY)
6397 SNAPUP(height, stepY);
6400 reqScrollArea.w = width;
6401 reqScrollArea.h = height;
6402 noAutoScrollArea = (width > 0 || height > 0);
6404 UpdateScrollBars(true, true);
6407 void SetScrollPosition(int x, int y)
6410 sbh.Action(setPosition, x, 0);
6414 int seen = clientSize.w, total = reqScrollArea.w;
6416 if(scrollFlags.snapX)
6417 SNAPDOWN(seen, sbStep.x);
6419 if(!total) total = seen;
6420 range = total - seen + 1;
6421 range = Max(range, 1);
6423 if(x >= range) x = range - 1;
6425 if(scrollFlags.snapX)
6426 SNAPUP(x, sbStep.x);
6429 OnHScroll(setPosition, x, 0);
6433 SNAPDOWN(x, textCellW);
6439 sbv.Action(setPosition, y, 0);
6443 int seen = clientSize.h, total = reqScrollArea.h;
6446 if(scrollFlags.snapY)
6447 SNAPDOWN(seen, sbStep.y);
6449 if(!total) total = seen;
6450 range = total - seen + 1;
6451 range = Max(range, 1);
6453 if(y >= range) y = range - 1;
6455 if(scrollFlags.snapY)
6456 SNAPUP(y, sbStep.y);
6459 OnVScroll(setPosition, y, 0);
6462 SNAPDOWN(y, textCellH);
6467 UpdateCaret(false, false);
6470 void SetScrollLineStep(int stepX, int stepY)
6476 SNAPDOWN(stepX, textCellW);
6477 SNAPDOWN(stepY, textCellH);
6478 stepX = Max(stepX, textCellW);
6479 stepY = Max(stepY, textCellH);
6482 sbh.lineStep = stepX;
6484 sbv.lineStep = stepY;
6487 void SetState(WindowState newState, bool activate, Modifiers mods)
6491 if(state == newState || OnStateChange(newState, mods))
6493 WindowState prevState = state;
6497 // This used to be at the end of the brackets... moved for X, testing...
6498 // This has the effect of activating the window through the system...
6499 if(rootWindow == this)
6500 guiApp.interfaceDriver.SetRootWindowState(this, newState, !style.hidden);
6502 SetStateEx(newState, activate);
6504 if(rootWindow == this && !rootWindow.nativeDecorations)
6506 int x = position.x, y = position.y;
6509 x -= guiApp.desktop.absPosition.x;
6510 y -= guiApp.desktop.absPosition.y;
6512 guiApp.interfaceDriver.PositionRootWindow(this, x, y, size.w, size.h, true, true);
6516 //state = prevState;
6518 if(state != maximized && style.hasMaximize)
6521 for(child = parent.children.first; child; child = child.next)
6523 if(child != this && child.state == maximized)
6524 child.SetStateEx(normal, false);
6528 if(!style.nonClient && (sbv || sbh) && this != parent.sbv && this != parent.sbh)
6529 parent.UpdateScrollBars(true, true);
6532 // Do we really need this stuff here?
6533 // Shouldn't the Activate stuff take care of it?
6534 if(parent.rootWindow == parent && style)
6537 parent.FigureCaption(caption);
6538 guiApp.interfaceDriver.SetRootWindowCaption(parent, caption);
6539 parent.UpdateDecorations();
6543 rootWindow.ConsequentialMouseMove(false);
6550 BitmapResource GetIcon(SkinBitmap iconID)
6552 return guiApp.currentSkin.GetBitmap(iconID);
6555 void SetMouseRange(Box range)
6557 if(range || guiApp.fullScreenMode)
6562 clip.left = range.left + absPosition.x + clientStart.x;
6563 clip.top = range.top + absPosition.y + clientStart.y;
6564 clip.right = range.right + absPosition.x + clientStart.x;
6565 clip.bottom = range.bottom + absPosition.y + clientStart.y;
6569 clip.left = guiApp.desktop.box.left;
6570 clip.top = guiApp.desktop.box.top;
6571 clip.right = guiApp.desktop.box.right;
6572 clip.bottom = guiApp.desktop.box.bottom;
6574 guiApp.interfaceDriver.SetMouseRange(rootWindow, clip);
6577 guiApp.interfaceDriver.SetMouseRange(rootWindow, null);
6580 void SetMouseRangeToClient(void)
6582 if(guiApp.fullScreenMode || this != guiApp.desktop)
6584 Box box {0, 0, clientSize.w - 1, clientSize.h - 1 };
6585 box.Clip(clientArea);
6589 SetMouseRange(null);
6592 void SetMouseRangeToWindow(void)
6594 Box box { -clientStart.x, -clientStart.y, size.w-1, size.h-1 };
6595 if(this == guiApp.desktop)
6596 SetMouseRangeToClient();
6601 // x, y: Desktop Coordinates
6602 void ShowSysMenu(int x, int y)
6605 PopupMenu windowMenu { master = this, interim = true, position = { x + 1 - guiApp.desktop.position.x, y + 1 - guiApp.desktop.position.y }, menu = menu };
6608 menu, $"Restore", r, NotifySelect = MenuWindowRestore,
6609 disabled = (!style.hasMaximize && !style.hasMinimize) || state == normal, bitmap = guiApp.currentSkin.GetBitmap(restore)
6613 menu, $"Move", m, NotifySelect = MenuWindowMove,
6614 disabled = !style.fixed || state == maximized
6618 menu, $"Size", s, NotifySelect = MenuWindowSize,
6619 disabled = !style.sizable || state != normal
6623 menu, $"Minimize", n, NotifySelect = MenuWindowMinimize,
6624 disabled = !style.hasMinimize || state == minimized, bitmap = guiApp.currentSkin.GetBitmap(minimize)
6628 menu, $"Maximize", KeyCode::x, NotifySelect = MenuWindowMaximize,
6629 disabled = !style.hasMaximize || state == maximized, bitmap = guiApp.currentSkin.GetBitmap(maximize)
6633 menu, $"Stay On Top", t, NotifySelect = MenuWindowStayOnTop,
6634 disabled = !style.fixed, checkable = true, checked = style.stayOnTop
6636 MenuDivider { menu };
6639 menu, $"Close", c, (parent == guiApp.desktop) ? altF4 : ( style.isActiveClient ? ctrlF4 : 0), NotifySelect = MenuWindowClose,
6640 bold = true, disabled = !style.hasClose, bitmap = guiApp.currentSkin.GetBitmap(close)
6642 windowMenu.Create();
6647 ActivateEx(true, true, true, true, null, null);
6650 void MakeActive(void)
6652 ActivateEx(true, false, true, false, null, null);
6655 void SoftActivate(void)
6657 if(guiApp.desktop.active)
6663 void Deactivate(void)
6665 ActivateEx(false, true, true, true, null, null);
6670 guiApp.interfaceDriver.FlashRootWindow(rootWindow);
6673 bool CycleChildren(bool backward, bool clientOnly, bool tabCycleOnly, bool cycleParents)
6675 bool result = false;
6676 if(activeChild && activeChild.cycle)
6678 Window modalWindow, child = activeChild;
6679 if(!clientOnly /*&& parent.tabCycle*/)
6681 Window next = child;
6684 if(next.cycle == (backward ? childrenCycle.first : childrenCycle.last))
6688 if(parent && parent.CycleChildren(backward, false, true, true))
6696 next = next.cycle.prev.data;
6698 next = next.cycle.next.data;
6699 if(!next.disabled && !next.inactive /*isRemote*/ && next.created && !next.nonClient && (!clientOnly || next.style.isActiveClient) && !next.style.hidden && next.FindModal() != activeChild)
6704 if(!clientOnly && child.cycle == (backward ? childrenCycle.first : childrenCycle.last) &&
6705 parent.tabCycle && parent.CycleChildren(backward, false, false))
6709 if(tabCycleOnly && !tabCycle) return false;
6716 child = child.cycle.prev.data;
6718 child = child.cycle.next.data;
6719 if(child == child.parent.activeChild)
6721 else if(!child.disabled && child.created && (!clientOnly || child.style.isActiveClient) && !child.style.hidden && child.FindModal() != activeChild)
6724 modalWindow = child.FindModal();
6727 // Scroll the window to include the active control
6728 if(sbh && !child.style.dontScrollHorz)
6730 if(child.scrolledPos.x < 0)
6731 sbh.Action(setPosition, scroll.x + child.scrolledPos.x, 0);
6732 else if(child.scrolledPos.x + child.size.w > clientSize.w)
6733 sbh.Action(setPosition, scroll.x + child.scrolledPos.x + child.size.w - clientSize.w, 0);
6735 if(sbv && !child.style.dontScrollVert)
6737 if(child.scrolledPos.y < 0)
6738 sbv.Action(setPosition, scroll.y + child.scrolledPos.y, 0);
6739 else if(child.scrolledPos.y + child.size.h > clientSize.h)
6740 sbv.Action(setPosition, scroll.y + child.scrolledPos.y + child.size.h - clientSize.h, 0);
6744 child = modalWindow ? modalWindow : child;
6745 child.ActivateEx(true, true, true, true, null, null);
6746 if(child.tabCycle && child.childrenCycle.first)
6747 child = ((OldLink)(backward ? child.childrenCycle.first : child.childrenCycle.last)).data;
6755 ConsequentialMouseMove(false);
6759 void AddResource(Resource resource)
6763 ResPtr ptr { resource = resource };
6767 // Load Graphics here if window is created already
6768 if(/*created && */display)
6770 display.Lock(false);
6771 ptr.loaded = display.displaySystem.LoadResource(resource);
6775 // Temporary hack to load font right away for listbox in dropbox ...
6776 else if(master && master.display)
6778 master.display.Lock(false);
6779 master.display.displaySystem.LoadResource(resource);
6780 master.display.Unlock();
6786 void RemoveResource(Resource resource)
6791 for(ptr = resources.first; ptr; ptr = ptr.next)
6793 if(ptr.resource == resource)
6799 // Unload Graphics here if window is created already
6800 if(/*created && */display)
6804 display.Lock(false);
6805 display.displaySystem.UnloadResource(resource, ptr.loaded);
6811 resources.Delete(ptr);
6816 void SetCaret(int x, int y, int size)
6823 if(active && !style.interim)
6825 if(visible || !guiApp.caretOwner)
6826 guiApp.caretOwner = size ? this : null;
6828 UpdateCaret(false, false);
6831 guiApp.interfaceDriver.SetCaret(0,0,0);
6832 UpdateCaret(false, true);
6833 guiApp.caretEnabled = false;
6836 else if(style.inactive && active)
6838 guiApp.interfaceDriver.SetCaret(0,0,0);
6839 UpdateCaret(false, true);
6840 guiApp.caretEnabled = false;
6845 void Scroll(int x, int y)
6847 bool opaque = !style.drawBehind || background.a;
6848 if(opaque && display && display.flags.scrolling)
6850 Box box = clientArea;
6851 box.left += clientStart.x;
6852 box.top += clientStart.y;
6853 box.right += clientStart.x;
6854 box.bottom += clientStart.y;
6856 //scrollExtent.Free(null);
6857 scrollExtent.AddBox(box);
6858 scrolledArea.x += x;
6859 scrolledArea.y += y;
6861 //scrollExtent.Free();
6862 //scrollExtent.AddBox(clientArea);
6863 //scrollExtent.Offset(clientStart.x, clientStart.y);
6864 //scrolledArea.x = x;
6865 //scrolledArea.y = y;
6871 rootWindow.dirty = true;
6874 void ReleaseCapture()
6876 if(guiApp && guiApp.windowCaptured && guiApp.windowCaptured == this)
6878 Window oldCaptured = guiApp.windowCaptured;
6879 guiApp.windowCaptured = null;
6880 guiApp.prevWindow = null;
6883 //guiApp.Log("Released Capture\n");
6885 guiApp.interfaceDriver.SetMouseCapture(null);
6887 //oldCaptured.OnMouseCaptureLost();
6890 oldCaptured.ConsequentialMouseMove(false);
6895 void SetText(char * format, ...)
6902 char caption[MAX_F_STRING];
6904 va_start(args, format);
6905 vsprintf(caption, format, args);
6908 this.caption = new char[strlen(caption)+1];
6910 strcpy(this.caption, caption);
6919 bool Grab(Bitmap bitmap, Box box, bool decorations)
6921 bool result = false;
6922 if(display || this == guiApp.desktop)
6924 Box clip = {MININT, MININT, MAXINT, MAXINT};
6930 clip.Clip(clientArea);
6932 clip.Clip(this.box);
6934 if(rootWindow != this)
6936 clip.left += absPosition.y;
6937 clip.top += absPosition.y;
6938 clip.right += absPosition.x;
6939 clip.bottom += absPosition.y;
6942 clip.left += decorations ? 0 : clientStart.x;
6943 clip.top += decorations ? 0 : clientStart.y;
6944 clip.right += decorations ? 0 : clientStart.x;
6945 clip.bottom += decorations ? 0 : clientStart.y;
6947 if(display && display.flags.flipping)
6949 rootWindow.Update(null);
6950 rootWindow.UpdateDisplay();
6957 result = window.display.displaySystem.driver.GrabScreen(null, bitmap, clip.left, clip.top,
6958 clip.right - clip.left + 1, clip.bottom - clip.top + 1);
6962 result = display.Grab(bitmap, clip.left, clip.top,
6963 clip.right - clip.left + 1, clip.bottom - clip.top + 1);
6965 if(bitmap.pixelFormat != pixelFormat888 && bitmap.pixelFormat != pixelFormat8)
6967 if(!bitmap.Convert(null, pixelFormat888, null))
6974 void GetMousePosition(int * x, int * y)
6976 int mouseX = 0, mouseY = 0;
6977 if(!guiApp.acquiredWindow && (guiApp.desktop.active || !guiApp.fullScreenMode))
6980 guiApp.interfaceDriver.GetMousePosition(&mouseX, &mouseY);
6981 if(this != guiApp.desktop)
6983 mouseX -= absPosition.x + clientStart.x;
6984 mouseY -= absPosition.y + clientStart.y;
6991 DialogResult DoModal()
6993 DialogResult returnCode = 0;
6994 int terminated = terminateX;
6997 while(!destroyed && guiApp.driver != null)
6999 if(terminateX != terminated)
7001 terminated = terminateX;
7002 guiApp.desktop.Destroy(0);
7003 if(guiApp.desktop.created)
7006 //printf("Resetting terminate X to 0\n");
7012 guiApp.UpdateDisplay();
7013 if(!guiApp.ProcessInput(false))
7016 returnCode = this.returnCode;
7029 return !destroyed && guiApp.driver != null && terminateX < 2;
7032 DialogResult DoModalEnd()
7034 DialogResult returnCode = this.returnCode;
7039 // --- Window manipulation ---
7040 /*bool GetDisabled()
7042 bool disabled = this.disabled;
7044 for(window = this; (window = window.master); )
7055 // --- Mouse Manipulation ---
7056 void GetNCMousePosition(int * x, int * y)
7058 GetMousePosition(x, y);
7059 if(x) *x += clientStart.x;
7060 if(y) *y += clientStart.y;
7063 // --- Carets manipulation ---
7064 void GetCaretPosition(Point caretPos)
7066 caretPos = this.caretPos;
7069 int GetCaretSize(void)
7074 bool ButtonCloseDialog(Button button, int x, int y, Modifiers mods)
7080 bool CloseConfirmation(bool parentClosing)
7093 if(!OnClose(parentClosing))
7096 // If you want to skip this, simply set modifiedDocument to false in OnClose
7097 if(result && (/*fileName || */style.isDocument) && modifiedDocument)
7099 DialogResult dialogRes;
7102 sprintf(message, $"Save changes to %s?", fileName);
7104 sprintf(message, $"Save changes to Untitled %d?", documentID);
7106 dialogRes = MessageBox { master = master, type = yesNoCancel, text = parent.caption, contents = message }.Modal();
7108 if(dialogRes == yes)
7110 // TOFIX: Precomp error if brackets are taken out
7111 result = (DialogResult)MenuFileSave(null, 0) != cancel;
7113 else if(dialogRes == cancel)
7119 for(slave = slaves.first; slave; slave = slave.next)
7120 if(!((Window)slave.data).CloseConfirmation(true))
7122 // ((Window)slave.data).CloseConfirmation(true);
7130 for(child = children.first; child; child = child.next)
7131 if(child.master != this && !child.CloseConfirmation(true))
7141 // Static methods... move them somewhere else?
7142 void ::RestoreCaret()
7144 if(guiApp.caretOwner)
7145 guiApp.caretOwner.UpdateCaret(false, false);
7148 void ::FreeMouseRange()
7150 guiApp.interfaceDriver.SetMouseRange(null, null);
7154 bool MenuFileClose(MenuItem selection, Modifiers mods)
7156 Window document = activeChild;
7158 document.Destroy(0);
7162 bool MenuFileExit(MenuItem selection, Modifiers mods)
7168 bool MenuFileSave(MenuItem selection, Modifiers mods)
7172 fileMonitor.fileName = null;
7175 if(OnSaveFile(fileName))
7177 //if(OnFileModified != Window::OnFileModified)
7180 fileMonitor.fileName = fileName;
7186 MessageBox dialog { master = master, type = yesNoCancel, text = $"Error writing file", contents = $"Save as a different file?" };
7187 DialogResult answer = dialog.Modal();
7189 if(answer != yes) return (bool)answer;
7192 return MenuFileSaveAs(selection, mods);
7195 bool MenuFileSaveAs(MenuItem selection, Modifiers mods)
7197 DialogResult result = (DialogResult)bool::true;
7198 FileDialog fileDialog = saveDialog;
7201 fileDialog = FileDialog {};
7206 fileDialog.filePath = fileName;
7209 char filePath[MAX_FILENAME];
7210 sprintf(filePath, "Untitled %d", documentID);
7211 fileDialog.filePath = filePath;
7213 fileMonitor.fileName = null;
7215 fileDialog.type = save;
7216 fileDialog.text = $"Save As";
7220 fileDialog.master = master.parent ? master : this;
7221 if(fileDialog.Modal() == ok)
7223 char * filePath = fileDialog.filePath;
7225 if(OnSaveFile(filePath))
7228 property::fileName = filePath;
7229 NotifySaved(master, this, filePath);
7234 MessageBox dialog { master = master.parent ? master : this, type = yesNoCancel, text = $"Error writing file", contents = $"Save as a different file?" };
7235 DialogResult answer = dialog.Modal();
7250 //if(OnFileModified != Window::OnFileModified && fileName)
7253 fileMonitor.fileName = fileName;
7257 return (bool)result; // Actually returning result from Yes/NoCancel message box
7260 bool MenuFileSaveAll(MenuItem selection, Modifiers mods)
7262 Window document = activeChild;
7264 for(document = children.first; document; document = next)
7266 next = document.next;
7267 if(document.style.isDocument || document.fileName)
7268 document.MenuFileSave(selection, mods);
7273 bool MenuWindowArrangeIcons(MenuItem selection, Modifiers mods)
7277 for(document = children.first; document; document = document.next)
7278 //if(document.style.isDocument && document.state == minimized)
7279 if(document.style.isActiveClient && document.state == minimized)
7280 document.SetState(minimized, false, mods);
7284 bool MenuWindowCascade(MenuItem selection, Modifiers mods)
7286 Window document = activeChild;
7289 Window firstDocument = null;
7291 OldLink cycle = document.cycle.prev;
7296 if(child.style.isActiveClient && !child.style.hidden)
7300 firstDocument = child;
7301 if(child.state == minimized)
7302 child.SetState(minimized, false, mods);
7305 child.positionID = id++;
7306 child.SetState(normal, false, mods);
7307 child.anchor.left.type = cascade;
7310 child.normalSizeAnchor = *&child.sizeAnchor;
7311 child.normalAnchor = child.anchor;
7313 // Break the anchors for moveable/resizable windows
7314 if(child.style.fixed)
7316 child.ComputeAnchors(child.anchor, *&child.sizeAnchor, &x, &y, &w, &h);
7318 (*&child.normalAnchor).left = x;
7319 (*&child.normalAnchor).top = y;
7320 (*&child.normalAnchor).right.type = none;
7321 (*&child.normalAnchor).bottom.type = none;
7323 child.normalSizeAnchor.isClientW = false;
7324 child.normalSizeAnchor.isClientH = false;
7325 child.normalSizeAnchor.size.w = w;
7326 child.normalSizeAnchor.size.h = h;
7327 child.anchored = false;
7330 if(child.state == normal /*|| child.state == Hidden */) // Hidden is new here ...
7332 child.stateAnchor = child.normalAnchor;
7333 child.stateSizeAnchor = child.normalSizeAnchor;
7335 child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
7336 child.Position(x, y, w, h, true, true, true, true, false, false);
7341 last = children.last;
7342 if(!child.style.stayOnTop)
7343 for(; last && last.style.stayOnTop; last = last.prev);
7344 children.Move(child, last);
7345 childrenOrder.Move(child.order, childrenOrder.last);
7347 if(cycle == document.cycle) break;
7351 firstDocument.Activate();
7356 bool MenuWindowClose(MenuItem selection, Modifiers mods)
7363 // Close all closes all active clients, not all documents
7364 bool MenuWindowCloseAll(MenuItem selection, Modifiers mods)
7366 Window next, document;
7368 for(document = children.first; document; document = next)
7370 for(next = document.next; next && !(next.style.isActiveClient; next = next.next);
7371 if(document.style.isActiveClient)
7372 if(!document.Destroy(0) && !document.style.hidden)
7378 bool MenuWindowMaximize(MenuItem selection, Modifiers mods)
7380 if(style.hasMaximize && state != maximized)
7381 SetState(maximized, 0, 0);
7385 bool MenuWindowMinimize(MenuItem selection, Modifiers mods)
7387 if(style.hasMinimize && state != minimized)
7389 SetState(minimized, 0, 0);
7390 parent.CycleChildren(false, true, false, true);
7395 bool MenuWindowMove(MenuItem selection, Modifiers mods)
7397 MenuMoveOrSize(false, selection ? true : false);
7401 bool MenuWindowNext(MenuItem selection, Modifiers mods)
7403 CycleChildren(false, true, false, true);
7407 bool MenuWindowPrevious(MenuItem selection, Modifiers mods)
7409 CycleChildren(true, true, false, true);
7413 bool MenuWindowSize(MenuItem selection, Modifiers mods)
7415 MenuMoveOrSize(true, true);
7419 bool MenuWindowRestore(MenuItem selection, Modifiers mods)
7422 SetState(normal, 0, 0);
7426 bool MenuWindowSelectWindow(MenuItem selection, Modifiers mods)
7429 int id = selection.id;
7430 OldLink cycle = activeClient.cycle;
7432 //for(c = 0, cycle = activeChild.cycle; c<id; cycle = cycle.next, c++);
7435 Window sibling = cycle.data;
7436 if(sibling.style.isActiveClient && sibling.visible && !sibling.style.nonClient)
7444 document = cycle.data;
7445 document.Activate();
7447 //if(activeChild.state == maximized)
7448 // document.SetState(maximized, false, mods);
7449 //else if(document.state == minimized)
7450 // document.SetState(normal, false, mods);
7454 bool MenuWindowStayOnTop(MenuItem selection, Modifiers mods)
7456 stayOnTop = !style.stayOnTop;
7460 bool MenuWindowTileHorz(MenuItem selection, Modifiers mods)
7462 Window document = activeChild;
7465 Window firstDocument = null;
7466 OldLink cycle = document.cycle;
7470 Window child = cycle.data;
7471 if(child.style.isActiveClient && !child.style.hidden)
7473 if(!firstDocument) firstDocument = child;
7474 if(child.state == minimized)
7475 child.SetState(minimized, false, mods);
7478 child.positionID = id++;
7479 child.SetState(normal, false, mods);
7480 child.ActivateEx(true, false, false, false, null, null); // To move active clients on top of other windows
7482 child.anchor.left.type = hTiled;
7485 child.normalSizeAnchor = *&child.sizeAnchor;
7486 child.normalAnchor = child.anchor;
7488 // Break the anchors for moveable/resizable windows
7489 if(child.style.fixed)
7491 child.ComputeAnchors(child.anchor, *&child.sizeAnchor, &x, &y, &w, &h);
7493 (*&child.normalAnchor).left = x;
7494 (*&child.normalAnchor).top = y;
7495 (*&child.normalAnchor).right.type = none;
7496 (*&child.normalAnchor).bottom.type = none;
7497 child.normalSizeAnchor.isClientW = false;
7498 child.normalSizeAnchor.isClientH = false;
7499 child.normalSizeAnchor.size.w = w;
7500 child.normalSizeAnchor.size.h = h;
7501 child.anchored = false;
7504 if(child.state == normal /*|| child.state == Hidden */) // Hidden is new here ...
7506 child.stateAnchor = child.normalAnchor;
7507 child.stateSizeAnchor = child.normalSizeAnchor;
7509 child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
7510 child.Position(x,y, w, h, true, true, true, true, false, true);
7515 if((cycle = cycle.next) == document.cycle) break;
7518 firstDocument.Activate();
7523 bool MenuWindowTileVert(MenuItem selection, Modifiers mods)
7525 Window document = activeChild;
7528 Window firstDocument = null;
7530 OldLink cycle = document.cycle;
7535 //if(child.style.isDocument)
7536 if(child.style.isActiveClient && !child.style.hidden)
7538 if(!firstDocument) firstDocument = child;
7539 if(child.state == minimized)
7540 child.SetState(minimized, false, mods);
7543 child.positionID = id++;
7544 child.SetState(normal, false, mods);
7545 child.ActivateEx(true, false, false, false, null, null); // To move active clients on top of other windows
7547 child.anchor.left.type = vTiled;
7550 child.normalSizeAnchor = *&child.sizeAnchor;
7551 child.normalAnchor = child.anchor;
7553 // Break the anchors for moveable/resizable windows
7554 if(child.style.fixed)
7556 child.ComputeAnchors(child.anchor, *&child.sizeAnchor, &x, &y, &w, &h);
7558 (*&child.normalAnchor).left = x;
7559 (*&child.normalAnchor).top = y;
7560 (*&child.normalAnchor).right.type = none;
7561 (*&child.normalAnchor).bottom.type = none;
7562 child.normalSizeAnchor.isClientW = false;
7563 child.normalSizeAnchor.isClientH = false;
7564 child.normalSizeAnchor.size.w = w;
7565 child.normalSizeAnchor.size.h = h;
7566 child.anchored = false;
7569 if(child.state == normal /*|| child.state == Hidden */) // Hidden is new here ...
7571 child.stateAnchor = child.normalAnchor;
7572 child.stateSizeAnchor = child.normalSizeAnchor;
7574 child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
7575 child.Position(x,y, w, h, true, true, true, true, false, true);
7580 if((cycle = cycle.next) == document.cycle) break;
7583 firstDocument.Activate();
7588 bool MenuWindowWindows(MenuItem selection, Modifiers mods)
7590 WindowList dialog { master = this };
7591 Window document = (Window)dialog.Modal();
7594 if(activeChild.state == maximized)
7595 document.SetState(maximized, false, mods);
7596 else if(document.state == minimized)
7597 document.SetState(normal, false, mods);
7598 document.Activate();
7604 virtual bool OnCreate(void);
7605 virtual void OnDestroy(void);
7606 virtual void OnDestroyed(void);
7607 virtual bool OnClose(bool parentClosing);
7608 virtual bool OnStateChange(WindowState state, Modifiers mods);
7609 virtual bool OnPostCreate(void);
7610 virtual bool OnMoving(int *x, int *y, int w, int h);
7611 virtual bool OnResizing(int *width, int *height);
7612 virtual void OnResize(int width, int height);
7613 virtual void OnPosition(int x, int y, int width, int height);
7614 virtual bool OnLoadGraphics(void);
7615 virtual void OnApplyGraphics(void);
7616 virtual void OnUnloadGraphics(void);
7617 virtual void OnRedraw(Surface surface);
7618 virtual bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct);
7619 virtual void OnActivateClient(Window client, Window previous);
7620 virtual bool OnKeyDown(Key key, unichar ch);
7621 virtual bool OnKeyUp(Key key, unichar ch);
7622 virtual bool OnKeyHit(Key key, unichar ch);
7623 virtual bool OnSysKeyDown(Key key, unichar ch);
7624 virtual bool OnSysKeyUp(Key key, unichar ch);
7625 virtual bool OnSysKeyHit(Key key, unichar ch);
7626 virtual bool OnMouseOver(int x, int y, Modifiers mods);
7627 virtual bool OnMouseLeave(Modifiers mods);
7628 virtual bool OnMouseMove(int x, int y, Modifiers mods);
7629 virtual bool OnLeftButtonDown(int x, int y, Modifiers mods);
7630 virtual bool OnLeftButtonUp(int x, int y, Modifiers mods);
7631 virtual bool OnLeftDoubleClick(int x, int y, Modifiers mods);
7632 virtual bool OnRightButtonDown(int x, int y, Modifiers mods);
7633 virtual bool OnRightButtonUp(int x, int y, Modifiers mods);
7634 virtual bool OnRightDoubleClick(int x, int y, Modifiers mods);
7635 virtual bool OnMiddleButtonDown(int x, int y, Modifiers mods);
7636 virtual bool OnMiddleButtonUp(int x, int y, Modifiers mods);
7637 virtual bool OnMiddleDoubleClick(int x, int y, Modifiers mods);
7638 virtual void OnMouseCaptureLost(void);
7639 virtual void OnHScroll(ScrollBarAction action, int position, Key key);
7640 virtual void OnVScroll(ScrollBarAction action, int position, Key key);
7641 virtual void OnDrawOverChildren(Surface surface);
7642 virtual bool OnFileModified(FileChange fileChange, char * param);
7643 virtual bool OnSaveFile(char * fileName);
7645 // Virtual Methods -- Children management (To support Stacker, for lack of built-in auto-layout)
7646 // Note: A 'client' would refer to isActiveClient, rather than
7647 // being confined to the 'client area' (nonClient == false)
7648 virtual void OnChildAddedOrRemoved(Window child, bool removed);
7649 virtual void OnChildVisibilityToggled(Window child, bool visible);
7650 virtual void OnChildResized(Window child, int x, int y, int w, int h);
7652 // Skins Virtual Functions
7653 virtual void GetDecorationsSize(MinMaxValue * w, MinMaxValue * h);
7654 virtual void SetWindowMinimum(MinMaxValue * mw, MinMaxValue * mh);
7655 virtual void SetWindowArea(int * x, int * y, MinMaxValue * w, MinMaxValue * h, MinMaxValue * cw, MinMaxValue * ch)
7660 virtual void ShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving);
7661 virtual void PreShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving);
7662 virtual bool IsMouseMoving(int x, int y, int w, int h);
7663 virtual bool IsMouseResizing(int x, int y, int w, int h, bool *resizeX, bool *resizeY, bool *resizeEndX, bool *resizeEndY);
7664 virtual void UpdateNonClient();
7665 virtual void SetBox(Box box);
7666 virtual bool IsInside(int x, int y)
7668 return box.IsPointInside({x, y});
7670 virtual bool IsOpaque()
7672 return (!style.drawBehind || background.a == 255);
7676 virtual bool Window::NotifyActivate(Window window, bool active, Window previous);
7677 virtual void Window::NotifyDestroyed(Window window, DialogResult result);
7678 virtual void Window::NotifySaved(Window window, char * filePath);
7683 property Window parent
7685 property_category $"Layout"
7688 if(value || guiApp.desktop)
7691 Window oldParent = parent;
7692 Anchor anchor = this.anchor;
7694 if(value && value.IsDescendantOf(this)) return;
7695 if(value && value == this)
7697 if(!value) value = guiApp.desktop;
7699 if(value == oldParent) return;
7701 if(!master || (master == this.parent && master == guiApp.desktop))
7702 property::master = value;
7706 parent.children.Remove(this);
7707 parent.OnChildAddedOrRemoved(this, true);
7711 box.left - absPosition.x + parent.absPosition.x + style.nonClient * parent.clientStart.x,
7712 box.top - absPosition.y + parent.absPosition.y + style.nonClient * parent.clientStart.y,
7713 box.right - absPosition.x + parent.absPosition.x + style.nonClient * parent.clientStart.x,
7714 box.bottom - absPosition.y + parent.absPosition.y + style.nonClient * parent.clientStart.y
7718 last = value.children.last;
7720 if(style.isDocument)
7723 parent.numDocuments--;
7724 documentID = value.GetDocumentID();
7727 if(style.isActiveClient && !style.hidden)
7729 if(parent && parent != guiApp.desktop && !(style.hidden))
7731 if(state == minimized) parent.numIcons--;
7732 parent.numPositions--;
7736 if(!style.stayOnTop)
7737 for(; last && last.style.stayOnTop; last = last.prev);
7739 value.children.Insert(last, this);
7741 // *** NEW HERE: ***
7743 parent.childrenCycle.Delete(cycle);
7745 parent.childrenOrder.Delete(order);
7753 int x = position.x, y = position.y, w = size.w, h = size.h;
7757 x += parent.absPosition.x - value.absPosition.x + parent.clientStart.x - value.clientStart.x;
7758 y += parent.absPosition.y - value.absPosition.y + parent.clientStart.y - value.clientStart.y;
7760 vpw = value.clientSize.w;
7761 vph = value.clientSize.h;
7767 else if(style.fixed)
7769 if(!style.dontScrollHorz && value.scrollArea.w) vpw = value.scrollArea.w;
7770 if(!style.dontScrollVert && value.scrollArea.h) vph = value.scrollArea.h;
7773 anchor = this.anchor;
7775 if(anchor.left.type == offset) anchor.left.distance = x;
7776 else if(anchor.left.type == relative) anchor.left.percent = (float)x / vpw;
7777 if(anchor.top.type == offset) anchor.top.distance = y;
7778 else if(anchor.top.type == relative) anchor.top.percent = (float)y / vph;
7779 if(anchor.right.type == offset) anchor.right.distance = vpw - (x + w);
7780 //else if(anchor.right.type == relative) anchor.right.percent = 1.0-(float) (vpw - (x + w)) / vpw;
7781 else if(anchor.right.type == relative) anchor.right.percent = (float) (vpw - (x + w)) / vpw;
7782 if(anchor.bottom.type == offset) anchor.bottom.distance = vph - (y + h);
7783 //else if(anchor.bottom.type == relative) anchor.bottom.percent = 1.0-(float) (vph - (y + h)) / vph;
7784 else if(anchor.bottom.type == relative) anchor.bottom.percent = (float) (vph - (y + h)) / vph;
7786 if(!anchor.left.type && !anchor.right.type)
7788 anchor.horz.distance = (x + w / 2) - (vpw / 2);
7789 //anchor.horz.type = anchor.horz.distance ? AnchorValueOffset : 0;
7791 else if(anchor.horz.type == middleRelative) anchor.horz.percent = (float) ((x + w / 2) - (vpw / 2)) / vpw;
7792 if(!anchor.top.type && !anchor.bottom.type)
7794 anchor.vert.distance = (y + h / 2) - (vph / 2);
7795 //anchor.vert.type = anchor.vert.distance ? AnchorValueOffset : 0;
7797 else if(anchor.vert.type == middleRelative) anchor.vert.percent = (float)((y + h / 2) - (vph / 2)) / vph;
7800 parent.OnChildAddedOrRemoved(this, false);
7806 parent.childrenCycle.Insert(
7807 (parent.activeChild && parent.activeChild.cycle) ? parent.activeChild.cycle.prev : null,
7808 cycle = OldLink { data = this });
7809 parent.childrenOrder.Insert(
7810 (parent.activeChild && parent.activeChild.order) ? parent.activeChild.order.prev : parent.childrenOrder.last,
7811 order = OldLink { data = this });
7814 if(!style.hidden && style.isActiveClient)
7816 positionID = parent.GetPositionID(this);
7817 parent.numPositions++;
7818 if(state == minimized) parent.numIcons--;
7821 // *** FONT INHERITANCE ***
7822 if(!setFont && oldParent)
7823 stopwatching(oldParent, font);
7827 RemoveResource(systemFont);
7830 // TESTING WITH WATCHERS:
7831 usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
7832 // usedFont = setFont ? setFont : (systemFont);
7836 if(guiApp.currentSkin)
7838 systemFont = guiApp.currentSkin.SystemFont();
7841 usedFont = systemFont;
7842 AddResource(systemFont);
7850 usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
7859 if(value.rootWindow && value.rootWindow.display && rootWindow)
7861 bool reloadGraphics = (oldParent.rootWindow == oldParent && value.rootWindow) || (!value.rootWindow && rootWindow == this) ||
7862 (value.rootWindow.display && value.rootWindow.display.displaySystem != rootWindow.display.displaySystem);
7865 UnloadGraphics(false);
7868 LoadGraphics(false, false);
7871 if(value.rootWindow != rootWindow)
7872 DisplayModeChanged();
7876 scrolledPos.x = MININT; // Prevent parent update
7877 property::anchor = anchor;
7881 if(guiApp.currentSkin)
7882 guiApp.currentSkin.SetWindowMinimum(this, &skinMinSize.w, &skinMinSize.h);
7884 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
7885 Position(x, y, w, h, true, true, true, true, false, true);
7890 // else parent = value;
7893 get { return parent; }
7896 property Window master
7898 property_category $"Behavior"
7901 //if(this == value) return;
7902 if(value && value.IsSlaveOf(this)) return;
7908 OldLink slaveHolder;
7909 for(slaveHolder = master.slaves.first; slaveHolder; slaveHolder = slaveHolder.next)
7910 if(slaveHolder.data == this)
7912 master.slaves.Delete(slaveHolder);
7919 value.slaves.Add(OldLink { data = this });
7924 master.hotKeys.Remove(hotKey);
7925 value.hotKeys.Add(hotKey);
7928 if(master && master.defaultControl == this)
7929 master.defaultControl = null;
7931 if(style.isDefault && !value.defaultControl)
7932 value.defaultControl = this;
7937 get { return master ? master : parent; }
7940 property char * caption
7942 property_category $"Appearance"
7949 caption = new char[strlen(value)+1];
7951 strcpy(caption, value);
7956 get { return caption; }
7961 property_category $"Behavior"
7970 master.hotKeys.Add(hotKey = HotKeySlot { });
7974 hotKey.window = this;
7979 master.hotKeys.Delete(hotKey);
7984 get { return hotKey ? hotKey.key : 0; }
7987 property Color background
7989 property_category $"Appearance"
7992 background.color = value;
7997 if(this == rootWindow)
7998 guiApp.interfaceDriver.SetRootWindowColor(this);
8001 get { return background.color; }
8004 property Percentage opacity
8006 property_category $"Appearance"
8009 background.a = (byte)Min(Max((int)(value * 255), 0), 255);
8010 drawBehind = background.a ? false : true;
8012 get { return background.a / 255.0f; }
8015 property Color foreground
8017 property_category $"Appearance"
8025 get { return foreground; }
8028 property BorderStyle borderStyle
8030 property_category $"Appearance"
8033 if(!((BorderBits)value).fixed)
8035 style.hasClose = false;
8036 style.hasMaximize = false;
8037 style.hasMinimize = false;
8038 nativeDecorations = false;
8040 style.borderBits = value;
8044 SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
8046 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8047 Position(x, y, w, h, true, true, true, true, false, true);
8048 CreateSystemChildren();
8051 get { return (BorderStyle)style.borderBits; }
8054 property Size minClientSize
8056 property_category $"Layout"
8057 set { minSize = value; }
8058 get { value = minSize; }
8061 property Size maxClientSize
8063 property_category $"Layout"
8064 set { maxSize = value; }
8065 get { value = maxSize; }
8068 property bool hasMaximize
8070 property_category $"Window Style"
8073 style.hasMaximize = value;
8074 if(value) { style.fixed = true; style.contour = true; }
8078 SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
8080 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8081 Position(x, y, w, h, true, true, true, true, false, true);
8083 CreateSystemChildren();
8086 get { return style.hasMaximize; }
8089 property bool hasMinimize
8091 property_category $"Window Style"
8094 style.hasMinimize = value;
8095 if(value) { style.fixed = true; style.contour = true; }
8099 SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
8101 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8102 Position(x, y, w, h, true, true, true, true, false, true);
8104 CreateSystemChildren();
8107 get { return style.hasMinimize; }
8110 property bool hasClose
8112 property_category $"Window Style"
8115 style.hasClose = value;
8116 if(value) { style.fixed = true; style.contour = true; }
8120 SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
8121 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8122 Position(x, y, w, h, true, true, true, true, false, true);
8123 CreateSystemChildren();
8126 get { return style.hasClose; }
8129 property bool nonClient
8131 property_category $"Layout"
8134 style.nonClient = value;
8136 style.stayOnTop = true;
8138 get { return style.nonClient; }
8141 property bool inactive
8143 property_category $"Behavior"
8148 // *** NEW HERE: ***
8152 parent.childrenCycle.Delete(cycle);
8154 parent.childrenOrder.Delete(order);
8161 active = false; // true;
8162 if(parent.activeChild == this)
8163 parent.activeChild = null;
8164 if(parent.activeClient == this)
8165 parent.activeClient = null;
8174 parent.childrenCycle.Insert(
8175 (parent.activeChild && parent.activeChild.cycle) ? parent.activeChild.cycle.prev : null,
8176 cycle = OldLink { data = this });
8178 parent.childrenOrder.Insert(
8179 (parent.activeChild && parent.activeChild.order) ? parent.activeChild.order.prev : parent.childrenOrder.last,
8180 order = OldLink { data = this });
8183 style.inactive = value;
8185 get { return style.inactive; }
8188 property bool clickThrough
8190 property_category $"Behavior"
8191 set { style.clickThrough = value; }
8192 get { return style.clickThrough; }
8195 property bool isRemote
8197 property_category $"Behavior"
8198 set { style.isRemote = value; }
8199 get { return style.isRemote; }
8202 property bool noCycle
8204 property_category $"Behavior"
8205 set { style.noCycle = value; }
8206 get { return style.noCycle; }
8209 property bool isModal
8211 property_category $"Behavior"
8212 set { style.modal = value; }
8213 get { return style.modal; }
8216 property bool interim
8218 property_category $"Behavior"
8219 set { style.interim = value; }
8220 get { return style.interim; }
8223 property bool tabCycle
8225 property_category $"Behavior"
8226 set { style.tabCycle = value; }
8227 get { return style.tabCycle; }
8230 property bool isDefault
8232 property_category $"Behavior"
8240 /*for(sibling = parent.children.first; sibling; sibling = sibling.next)
8241 if(sibling != this && sibling.style.isDefault)
8242 sibling.style.isDefault = false;*/
8243 if(master.defaultControl)
8244 master.defaultControl.style.isDefault = false;
8245 master.defaultControl = this;
8247 else if(master.defaultControl == this)
8248 master.defaultControl = null;
8252 style.isDefault = value;
8254 Position(position.x, position.y, size.w, size.h, true, true, true,true,true, true);
8256 get { return style.isDefault; }
8259 property bool drawBehind
8261 property_category $"Window Style"
8262 set { style.drawBehind = value; }
8263 get { return style.drawBehind; }
8266 property bool hasMenuBar
8268 property_category $"Window Style"
8278 if(created && !menuBar)
8285 anchor = Anchor { top = 23, left = 1, right = 1 },
8287 inactive = true, nonClient = true
8292 else if(created && menuBar)
8297 style.hasMenuBar = value;
8299 get { return style.hasMenuBar; }
8302 property bool hasStatusBar
8304 property_category $"Window Style"
8311 statusBar = StatusBar { this };
8319 style.hasStatusBar = value;
8321 get { return style.hasStatusBar; }
8323 property bool stayOnTop
8325 property_category $"Window Style"
8330 if(created && !style.stayOnTop)
8332 if(rootWindow == this)
8333 guiApp.interfaceDriver.OrderRootWindow(this, true);
8334 else if(parent.children.last != this)
8336 parent.children.Move(this, parent.children.last);
8340 style.stayOnTop = true;
8344 if(created && style.stayOnTop)
8346 if(rootWindow == this)
8347 guiApp.interfaceDriver.OrderRootWindow(this, false);
8354 for(order = (this.order == parent.childrenOrder.first) ? null : this.order.prev;
8355 order && ((Window)order.data).style.stayOnTop;
8356 order = (order == parent.childrenOrder.first) ? null : order.prev);
8357 last = order ? order.data : null;
8361 for(last = parent.children.last;
8362 last && last.style.stayOnTop;
8366 parent.children.Move(this, last);
8370 style.stayOnTop = false;
8373 get { return style.stayOnTop; }
8378 property_category $"Window Style"
8388 if(menuBar && !value)
8395 if(!menuBar && style.hasMenuBar && value)
8399 this, menu = value, isMenuBar = true,
8400 anchor = Anchor { left = 1, top = 23, right = 1 }, size.h = 24,
8401 inactive = true, nonClient = true
8405 UpdateActiveDocument(null);
8408 get { return menu; }
8411 property FontResource font
8413 property_category $"Appearance"
8415 isset { return setFont ? true : false; }
8420 if(value && !setFont) { stopwatching(parent, font); }
8421 else if(!value && setFont)
8427 usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
8436 RemoveResource(setFont);
8441 RemoveResource(systemFont);
8448 AddResource(setFont);
8451 usedFont = setFont ? setFont : ((parent && parent.parent) ? parent.usedFont : systemFont);
8454 systemFont = guiApp.currentSkin.SystemFont();
8456 usedFont = systemFont;
8457 AddResource(systemFont);
8465 get { return usedFont; }
8468 property SizeAnchor sizeAnchor
8470 property_category $"Layout"
8473 return ((anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none) ||
8474 (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none)) &&
8475 sizeAnchor.isClientW != sizeAnchor.isClientH;
8482 normalSizeAnchor = sizeAnchor;
8484 if(state == normal /*|| state == Hidden */) // Hidden is new here ...
8486 stateAnchor = normalAnchor;
8487 stateSizeAnchor = normalSizeAnchor;
8489 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8490 Position(x,y, w, h, true, true, true, true, false, true);
8497 { sizeAnchor.isClientW ? clientSize.w : size.w, sizeAnchor.isClientH ? clientSize.h : size.h },
8498 sizeAnchor.isClientW,
8499 sizeAnchor.isClientH
8506 property_category $"Layout"
8509 Anchor thisAnchor = anchor;
8510 SizeAnchor thisSizeAnchor = sizeAnchor;
8511 bool leftRight = (anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none);
8512 bool topBottom = (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none);
8513 bool isClient = !sizeAnchor.isClientW && !sizeAnchor.isClientH;
8514 return ((anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none) ||
8515 (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none)) &&
8516 !sizeAnchor.isClientW && !sizeAnchor.isClientH && sizeAnchor.size.w && sizeAnchor.size.h;
8522 sizeAnchor.isClientW = false;
8523 sizeAnchor.isClientH = false;
8524 sizeAnchor.size = value;
8526 normalSizeAnchor = sizeAnchor;
8528 if(state == normal /*|| state == Hidden*/) // Hidden is new here ...
8530 stateAnchor = normalAnchor;
8531 stateSizeAnchor = normalSizeAnchor;
8533 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8534 Position(x, y, w, h, true, true, true, true, false, true);
8535 if(parent && parent.created && !nonClient) parent.OnChildResized(this, x, y, w, h);
8538 get { value = size; }
8541 property Size clientSize
8543 property_category $"Layout"
8546 return ((anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none) ||
8547 (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none)) &&
8548 sizeAnchor.isClientW && sizeAnchor.isClientH && sizeAnchor.size.w && sizeAnchor.size.h;
8553 sizeAnchor.isClientW = true;
8554 sizeAnchor.isClientH = true;
8555 sizeAnchor.size = value;
8557 normalSizeAnchor = sizeAnchor;
8559 if(state == normal /*|| state == Hidden */) // Hidden is new here ...
8561 stateAnchor = normalAnchor;
8562 stateSizeAnchor = normalSizeAnchor;
8564 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8565 Position(x,y, w, h, true, true, true, true, false, true);
8568 get { value = clientSize; }
8571 property Size initSize { get { value = sizeAnchor.size; } };
8573 property Anchor anchor
8575 property_category $"Layout"
8576 isset { return (anchor.left.type != offset || anchor.top.type != offset || anchor.right.type || anchor.bottom.type); }
8582 if(anchor.left.type && anchor.right.type && (!value.left.type || !value.right.type))
8584 normalSizeAnchor.isClientW = sizeAnchor.isClientW = false;
8585 normalSizeAnchor.size.w = sizeAnchor.size.w = size.w;
8587 if(anchor.top.type && anchor.bottom.type && (!value.top.type || !value.bottom.type))
8589 normalSizeAnchor.isClientH = sizeAnchor.isClientH = false;
8590 normalSizeAnchor.size.h = sizeAnchor.size.h = size.h;
8594 if(anchor.right.type && (anchor.horz.type == middleRelative || !anchor.left.type))
8596 anchor.left.distance = 0;
8597 anchor.horz.type = 0;
8599 if(anchor.bottom.type && (anchor.vert.type == middleRelative || !anchor.top.type))
8601 anchor.top.distance = 0;
8602 anchor.vert.type = 0;
8611 normalAnchor = anchor;
8613 // Break the anchors for moveable/resizable windows
8614 /*if(style.fixed ) //&& value.left.type == cascade)
8616 ComputeAnchors(anchor, sizeAnchor, &x, &y, &w, &h);
8618 this.anchor = normalAnchor = Anchor { left = x, top = y };
8619 normalSizeAnchor = SizeAnchor { { w, h } };
8622 if(state == normal /*|| state == Hidden */) // Hidden is new here ...
8624 stateAnchor = normalAnchor;
8625 stateSizeAnchor = normalSizeAnchor;
8627 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8628 Position(x, y, w, h, true, true, true, true, false, true);
8637 get { value = this ? anchor : Anchor { }; }
8640 property Point position
8642 property_category $"Layout"
8645 if(value == null) return;
8647 anchor.left = value.x;
8648 anchor.top = value.y;
8649 anchor.right.type = none;
8650 anchor.bottom.type = none;
8655 normalAnchor = anchor;
8657 // Break the anchors for moveable/resizable windows
8661 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8663 normalAnchor.left = x;
8664 normalAnchor.top = y;
8665 normalAnchor.right.type = none;
8666 normalAnchor.bottom.type = none;
8667 normalSizeAnchor.size.width = w;
8668 normalSizeAnchor.size.height = h;
8672 if(state == normal /*|| state == Hidden */) // Hidden is new here ...
8674 stateAnchor = normalAnchor;
8675 stateSizeAnchor = normalSizeAnchor;
8677 ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8678 Position(x,y, w, h, true, true, true, true, false, true);
8682 get { value = position; }
8685 property bool disabled
8687 property_category $"Behavior"
8690 if(this && disabled != value)
8697 get { return (bool)disabled; }
8700 property bool isEnabled
8705 for(parent = this; parent; parent = parent.parent)
8712 property WindowState state
8714 property_category $"Behavior"
8715 set { SetState(value, false, 0); }
8716 get { return this ? state : 0; }
8719 property bool visible
8721 property_category $"Behavior"
8724 if(this && !value && !style.hidden && parent)
8726 bool wasActiveChild = parent.activeChild == this;
8727 Window client = null;
8729 style.hidden = true;
8730 if(style.isActiveClient)
8732 parent.numPositions--;
8733 if(state == minimized) parent.numIcons--;
8738 OldLink prevOrder = null;
8740 if(rootWindow == this)
8741 guiApp.interfaceDriver.SetRootWindowState(this, state, false);
8744 Box box { scrolledPos.x, scrolledPos.y, scrolledPos.x + size.w - 1, scrolledPos.y + size.h - 1 };
8747 box.left -= parent.clientStart.x;
8748 box.top -= parent.clientStart.y;
8749 box.right -= parent.clientStart.x;
8750 box.bottom -= parent.clientStart.y;
8754 if(_isModal && master && master.modalSlave == this)
8755 master.modalSlave = null;
8759 OldLink tmpPrev = order.prev;
8760 client = tmpPrev ? tmpPrev.data : null;
8761 if(client && !client.style.hidden && !client.destroyed && client.created)
8762 prevOrder = tmpPrev;
8765 client = tmpPrev ? tmpPrev.data : null;
8766 if(client == this) { client = null; break; }
8767 if(client && ((client.style.hidden) || client.destroyed || !client.created))
8769 tmpPrev = client.order.prev;
8774 prevOrder = tmpPrev;
8779 // If this window can be an active client, make sure the next window we activate can also be one
8780 if(!style.nonClient && style.isActiveClient)
8782 tmpPrev = prevOrder;
8785 client = tmpPrev ? tmpPrev.data : null;
8786 if(client == this) { client = null; break; }
8787 if(client && (client.style.nonClient || !client.style.isActiveClient || client.style.hidden || client.destroyed || !client.created))
8789 tmpPrev = client.order.prev;
8794 prevOrder = tmpPrev;
8798 if(client && client.style.hidden) client = null;
8802 if((wasActiveChild /*parent.activeChild == this*/ || guiApp.interimWindow == this) && true /*activate*/)
8804 if(order && prevOrder && prevOrder.data != this)
8805 ((Window)prevOrder.data).ActivateEx(true, false, false, true, null, null);
8807 ActivateEx(false, false, false, true, null, null);
8809 // TESTING THIS HERE FOR HIDING ACTIVE CLIENT
8810 if(parent.activeClient == this)
8812 parent.activeClient = null;
8813 parent.UpdateActiveDocument(null);
8816 else if(parent.activeClient == this)
8818 parent.activeClient = client;
8819 parent.UpdateActiveDocument(this);
8822 // *** Not doing this anymore ***
8825 parent.childrenCycle.Delete(cycle);
8827 parent.childrenOrder.Delete(order);
8832 SetVisibility(!parent.style.hidden && (style.hidden ? false : true));
8837 else if(this && value && style.hidden)
8839 style.hidden = false;
8842 SetVisibility(!parent.style.hidden && (style.hidden ? false : true));
8843 if(rootWindow == this)
8844 guiApp.interfaceDriver.SetRootWindowState(this, state, true);
8846 if(_isModal && master)
8847 master.modalSlave = this;
8849 if(style.isActiveClient)
8851 positionID = parent.GetPositionID(this);
8852 parent.numPositions++;
8853 if(state == minimized) parent.numIcons++;
8856 // *** NOT DOING THIS ANYMORE ***
8858 if(!(style.inactive))
8860 if(!(style.noCycle))
8862 cycle = parent.childrenCycle.AddAfter(
8863 (parent.activeChild && parent.activeChild.cycle) ?
8864 parent.activeChild.cycle.prev : null, sizeof(OldLink));
8867 order = parent.childrenOrder.AddAfter(
8868 (parent.activeChild && parent.activeChild.order) ? parent.activeChild.order.prev : parent.childrenOrder.last,
8875 if(true || !parent.activeChild)
8876 ActivateEx(true, false, true, true, null, null);
8878 if(creationActivation == activate)
8879 ActivateEx(true, false, true, true, null, null);
8880 else if(creationActivation == flash && !object)
8883 //SetVisibility(!parent.style.hidden && (style.hidden ? false : true));
8887 ConsequentialMouseMove(false);
8893 style.hidden = !value;
8896 get { return (style.hidden || !setVisible) ? false : true; }
8899 property bool isDocument
8901 property_category $"Document"
8902 set { style.isDocument = value; }
8903 get { return style.isDocument; }
8906 property bool mergeMenus
8908 property_category $"Window Style"
8909 set { mergeMenus = value; }
8910 get { return (bool)mergeMenus; }
8913 property bool hasHorzScroll
8915 property_category $"Window Style"
8920 if(!style.hasHorzScroll && created)
8922 CreateSystemChildren();
8923 Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8926 else if(style.hasHorzScroll)
8930 Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8932 style.hasHorzScroll = value;
8935 get { return style.hasHorzScroll; }
8938 property bool hasVertScroll
8940 property_category $"Window Style"
8945 if(!style.hasVertScroll && created)
8947 style.hasVertScroll = true;
8948 CreateSystemChildren();
8949 Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8952 else if(style.hasVertScroll)
8956 Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8958 style.hasVertScroll = value;
8960 get { return style.hasVertScroll; }
8963 property bool dontHideScroll
8965 property_category $"Behavior"
8968 scrollFlags.dontHide = value;
8971 //UpdateScrollBars(true, true);
8972 Position(position.x, position.y, size.w, size.h, false, true, true, true, true, true);
8976 // UpdateScrollBars(true, true);
8977 Position(position.x, position.y, size.w, size.h, false, true, true, true, true, true);
8980 get { return scrollFlags.dontHide; }
8983 property bool dontScrollVert
8985 property_category $"Behavior"
8986 set { style.dontScrollVert = value; }
8987 get { return style.dontScrollVert; }
8989 property bool dontScrollHorz
8991 property_category $"Behavior"
8992 set { style.dontScrollHorz = value; }
8993 get { return style.dontScrollHorz; }
8996 property bool snapVertScroll
8998 property_category $"Behavior"
9001 scrollFlags.snapY = value;
9002 if(sbv) sbv.snap = value;
9004 get { return scrollFlags.snapY; }
9006 property bool snapHorzScroll
9008 property_category $"Behavior"
9011 scrollFlags.snapX = value;
9012 if(sbh) sbh.snap = value;
9014 get { return scrollFlags.snapX; }
9017 property Point scroll
9019 property_category $"Behavior"
9023 // TESTING THIS IMPLEMENTATION:
9024 SetScrollPosition(value.x, value.y);
9026 get { value = scroll; }
9029 property bool modifyVirtualArea
9031 property_category $"Behavior"
9032 set { modifyVirtArea = value; }
9033 get { return (bool)modifyVirtArea; }
9036 property char * fileName
9038 property_category $"Document"
9041 if(menu && ((!fileName && value) || (fileName && !value)))
9043 MenuItem item = menu.FindItem(MenuFileSave, 0);
9044 if(item) item.disabled = !modifiedDocument && value;
9049 if(value && value[0])
9050 fileName = CopyString(value);
9052 if(parent && this == parent.activeClient)
9053 parent.UpdateActiveDocument(null);
9057 // if(style.isDocument)
9059 fileMonitor.fileName = value;
9061 get { return fileName; }
9066 property_category $"Data"
9071 property bool modifiedDocument
9073 property_category $"Document"
9076 if(style.isDocument || fileName)
9080 MenuItem item = menu.FindItem(MenuFileSave, 0);
9081 if(item) item.disabled = !value && fileName;
9085 if(modifiedDocument != value)
9087 modifiedDocument = value;
9088 if(style.isDocument || fileName)
9092 get { return (bool)modifiedDocument; }
9095 property bool showInTaskBar
9097 property_category $"Window Style"
9098 set { style.showInTaskBar = value; }
9099 get { return (style.showInTaskBar; }
9101 property FileDialog saveDialog { set { saveDialog = value; } };
9102 property bool isActiveClient
9104 property_category $"Behavior"
9105 set { style.isActiveClient = value; }
9106 get { return style.isActiveClient; }
9109 property Cursor cursor
9111 property_category $"Appearance"
9115 SelectMouseCursor();
9117 get { return cursor; }
9120 //#if !defined(ECERE_VANILLA)
9121 property char * name
9123 property_category $"Design"
9126 return (this && object) ? object.name : null;
9131 activeDesigner.RenameObject(object, value);
9135 property char * displayDriver
9137 property_category $"Behavior"
9140 dispDriver = GetDisplayDriver(value);
9141 //DisplayModeChanged();
9145 return dispDriver ? dispDriver.name : null;
9149 // RUNTIME PROPERTIES
9150 property bool autoCreate { set { autoCreate = value; } get { return (bool)autoCreate; } };
9151 property Size scrollArea
9153 property_category $"Behavior"
9157 SetScrollArea(value.w, value.h, false);
9159 SetScrollArea(0,0, true);
9161 get { value = scrollArea; }
9164 return scrollArea.w > clientSize.w || scrollArea.h > clientSize.h;
9169 property_category $"Layout"
9170 set { if(this) is3D = value; }
9171 get { return (bool)is3D; }
9174 // Runtime Only Properties (No Set, can display the displayable ones depending on the type?)
9176 // Will be merged with font later
9177 property Font fontObject { get { return usedFont ? usedFont.font : null; } };
9178 property Point clientStart { get { value = clientStart; } };
9179 property Point absPosition { get { value = absPosition; } };
9180 property Anchor normalAnchor { get {value = normalAnchor; } };
9181 // property Size normalSizeAnchor { get { value = normalSizeAnchor; } };
9182 property bool active { get { return (bool)active; } };
9183 property bool created { get { return (bool)created; } };
9184 property bool destroyed { get { return (bool)destroyed; } };
9185 property Window firstSlave { get { return slaves.first ? ((OldLink)slaves.first).data : null; } };
9186 property Window firstChild { get { return children.first; } };
9187 property Window lastChild { get { return children.last; } };
9188 property Window activeClient { get { return activeClient; } };
9189 property Window activeChild { get { return activeChild; } };
9190 property Display display { get { return display ? display : ((parent && parent.rootWindow) ? parent.rootWindow.display : null); } };
9191 property DisplaySystem displaySystem { get { return display ? display.displaySystem : null; } };
9192 property ScrollBar horzScroll { get { return sbh; } };
9193 property ScrollBar vertScroll { get { return sbv; } };
9194 property StatusBar statusBar { get { return statusBar; } };
9195 property Window rootWindow { get { return rootWindow; } };
9196 property bool closing { get { return (bool)closing; } set { closing = value; } };
9197 property int documentID { get { return documentID; } };
9198 property Window previous { get { return prev; } }
9199 property Window next { get { return next; } }
9200 property Window nextSlave { get { OldLink link = master ? master.slaves.FindLink(this) : null; return (link && link.next) ? link.next.data : null; } }
9201 property PopupMenu menuBar { get { return menuBar; } }
9202 property ScrollBar sbv { get { return sbv; } }
9203 property ScrollBar sbh { get { return sbh; } }
9204 property bool fullRender { set { fullRender = value; } get { return (bool)fullRender; } }
9205 property void * systemHandle { get { return windowHandle; } }
9206 property Button minimizeButton { get { return sysButtons[0]; } };
9207 property Button maximizeButton { get { return sysButtons[1]; } };
9208 property Button closeButton { get { return sysButtons[2]; } };
9209 property BitmapResource icon
9211 get { return icon; }
9215 if(icon) incref icon;
9217 guiApp.interfaceDriver.SetIcon(this, value);
9220 property bool moveable { get { return (bool)moveable; } set { moveable = value; } };
9221 property bool alphaBlend { get { return (bool)alphaBlend; } set { alphaBlend = value; } };
9222 property bool useSharedMemory { get { return (bool)useSharedMemory; } set { useSharedMemory = value; } };
9223 property CreationActivationOption creationActivation { get { return creationActivation; } set { creationActivation = value; } };
9224 property bool nativeDecorations
9226 get { return (bool)nativeDecorations && (formDesigner || rootWindow == this); }
9227 set { nativeDecorations = value; }
9228 isset { return nativeDecorations != style.fixed; }
9230 property bool manageDisplay { get { return (bool)manageDisplay; } set { manageDisplay = value; } };
9232 property char * text
9234 property_category $"Deprecated"
9236 set { property::caption = value; }
9237 get { return property::caption; }
9243 WindowBits style; // Window Style
9244 char * caption; // Name / Caption
9245 Window parent; // Parent window
9246 OldList children; // List of children in Z order
9247 Window activeChild; // Child window having focus
9248 Window activeClient;
9249 Window previousActive; // Child active prior to activating the default child
9250 Window master; // Window owning and receiving notifications concerning this window
9251 OldList slaves; // List of windows belonging to this window
9252 Display display; // Display this window is drawn into
9254 Point position; // Position in parent window client area
9255 Point absPosition; // Absolute position
9256 Point clientStart; // Client area position from (0,0) in this window
9258 Size clientSize; // Client area size
9259 Size scrollArea; // Virtual Scroll area size
9260 Size reqScrollArea; // Requested virtual area size
9261 Point scroll; // Virtual area scrolling position
9262 public ScrollBar sbh, sbv; // Scrollbar window handles
9263 Cursor cursor; // Mouse cursor used for this window
9266 StatusBar statusBar;
9267 Button sysButtons[3];
9269 Box clientArea; // Client Area box clipped to parent
9271 HotKeySlot hotKey; // HotKey for this window
9275 ScrollFlags scrollFlags;// Window Scrollbar Flags
9276 int id; // Control ID
9278 ColorAlpha background; // Background color used to draw the window area
9280 subclass(DisplayDriver) dispDriver; // Display driver name for this window
9281 OldList childrenCycle; // Cycling order
9282 OldLink cycle; // Element of parent's cycling order
9283 OldList childrenOrder; // Circular Z-Order
9284 OldLink order; // Element of parent's circular Z-Order
9285 Window modalSlave; // Slave window blocking this window's interaction
9287 Window rootWindow; // Topmost system managed window
9288 void * windowHandle; // System window handle
9290 DialogResult returnCode;// Return code for modal windows
9292 Point sbStep; // Scrollbar line scrolling steps
9295 SizeAnchor stateSizeAnchor;
9297 Anchor normalAnchor;
9298 SizeAnchor normalSizeAnchor;
9300 Size skinMinSize; // Minimal window size based on style
9301 Point scrolledPos; // Scrolled position
9302 Box box; // Window box clipped to parent
9303 Box * against; // What to clip the box to
9305 Extent dirtyArea { /*first = -1, last = -1, free = -1*/ }; // Area marked for update by Update
9306 Extent renderArea { /*first = -1, last = -1, free = -1*/ }; // Temporary extent: Area that is going to be rendered
9307 Extent overRenderArea { /*first = -1, last = -1, free = -1*/ }; // Temporary extent: Area that is going to be rendered over children
9308 Extent clipExtent { /*first = -1, last = -1, free = -1*/ }; // Temporary extent against which to clip render area
9309 Extent scrollExtent { /*first = -1, last = -1, free = -1*/ }; // Area to scroll
9310 Point scrolledArea; // Distance to scroll area by
9311 Extent dirtyBack { /*first = -1, last = -1, free = -1*/ }; // Only used by root window
9313 OldList hotKeys; // List of the hotkeys of all children
9314 Window defaultControl; // Default child control
9318 ColorAlpha * palette; // Color palette used for this window
9320 int caretSize; // Size of caret, non zero if a caret is present
9321 Point caretPos; // Caret position
9323 void * systemParent; // Parent System Window for embedded windows
9330 WindowState lastState;
9332 FileMonitor fileMonitor
9334 this, FileChange { modified = true };
9336 bool OnFileNotify(FileChange action, char * param)
9339 fileMonitor.StopMonitoring();
9340 if(OnFileModified(action, param))
9341 fileMonitor.StartMonitoring();
9346 FontResource setFont, systemFont;
9347 FontResource usedFont;
9348 FontResource captionFont;
9350 FileDialog saveDialog;
9352 SizeAnchor sizeAnchor;
9354 // FormDesigner data
9357 Extent * tempExtents; //[4];
9358 BitmapResource icon;
9360 CreationActivationOption creationActivation;
9363 bool active:1; // true if window and ancestors are active
9364 bool acquiredInput:1; // true if the window is processing state based input
9365 bool modifiedDocument:1;
9366 bool disabled:1; // true if window cannot interact
9367 bool isForegroundWindow:1;// true while a root window is being activated
9368 bool visible:1; // Visibility flag
9369 bool destroyed:1; // true if window is being destroyed
9370 bool anchored:1; // true if this window is repositioned when the parent resizes
9371 bool dirty:1; // Flag set to true if any descendant must be redrawn
9377 bool modifyVirtArea:1;
9378 bool noAutoScrollArea:1;
9381 bool setVisible:1; // FOR FORM DESIGNER
9387 bool useSharedMemory:1;
9390 bool nativeDecorations:1;
9391 bool manageDisplay:1;
9392 bool formDesigner:1; // True if we this is running in the form editor
9395 // Checks used internally for them not to take effect in FormDesigner
9396 property bool _isModal { get { return !formDesigner ? style.modal : false; } }
9397 property subclass(DisplayDriver) _displayDriver { get { return !formDesigner ? dispDriver : null; } }
9399 WindowController controller;
9400 public property WindowController controller { get { return controller; } set { delete controller; controller = value; if(controller) incref controller; } }
9403 public class CommonControl : Window
9405 // creationActivation = doNothing;
9408 public property String toolTip
9410 property_category $"Appearance"
9413 if(created) CommonControl::OnDestroy();
9415 toolTip = value ? ToolTip { tip = value; } : null;
9417 if(created) CommonControl::OnCreate();
9419 get { return toolTip ? toolTip.tip : null; }
9425 // (Very) Ugly work around for the fact that the parent watcher
9426 // won't fire when it's already been disconnected...
9427 eInstance_FireSelfWatchers(toolTip,
9428 __ecereProp___ecereNameSpace__ecere__gui__Window_parent);
9434 toolTip.parent = this;
9443 public class Percentage : float
9445 char * OnGetString(char * string, float * fieldData, bool * needClass)
9449 sprintf(string, "%.2f", this);
9450 c = strlen(string)-1;
9453 if(string[c] != '0')
9454 last = Max(last, c);
9455 if(string[c] == '.')
9468 public void ApplySkin(Class c, char * name, void ** vTbl)
9470 char className[1024];
9475 subclass(Window) wc = (subclass(Window))c;
9476 subclass(Window) base = (subclass(Window))c.base;
9478 sprintf(className, "%sSkin_%s", name, c.name);
9479 wc.pureVTbl = c._vTbl;
9480 c._vTbl = new void *[c.vTblSize];
9481 memcpy(c._vTbl, wc.pureVTbl, c.vTblSize * sizeof(void *));
9482 sc = eSystem_FindClass(c.module.application, className);
9486 for(m = 0; m < c.base.vTblSize; m++)
9488 if(c._vTbl[m] == base.pureVTbl[m])
9489 c._vTbl[m] = vTbl[m];
9494 for(m = 0; m < c.vTblSize; m++)
9496 if(sc._vTbl[m] != wc.pureVTbl[m])
9497 c._vTbl[m] = sc._vTbl[m];
9501 for(d = c.derivatives.first; d; d = d.next)
9503 ApplySkin(d.data, name, c._vTbl);
9507 public void UnapplySkin(Class c)
9509 char className[1024];
9511 subclass(Window) wc = (subclass(Window))c;
9512 subclass(Window) base = (subclass(Window))c.base;
9515 if(wc.pureVTbl && c._vTbl != wc.pureVTbl)
9518 c._vTbl = wc.pureVTbl;
9522 for(d = c.derivatives.first; d; d = d.next)
9524 UnapplySkin(d.data);
9528 void CheckFontIntegrity(Window window)
9533 if(window.usedFont && window.usedFont.font == 0xecececec)
9535 FontResource uf = window.usedFont;
9536 char * className = window._class.name;
9537 char * text = window.text;
9540 for(c = window.firstChild; c; c = c.next)
9541 CheckFontIntegrity(c);
9545 public class ControllableWindow : Window
9547 /*WindowController controller;
9548 public property WindowController controller { get { return controller; } set { delete controller; controller = value; incref controller; } }
9549 ~ControllableWindow() { delete controller; }*/
9552 class WindowControllerInterface : ControllableWindow
9554 bool OnKeyDown(Key key, unichar ch)
9556 bool result = ((int(*)())(void *)controller.OnKeyDown)((void *)controller.controlled, (void *)controller, key, ch);
9558 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown](controller.window, key, ch);
9562 bool OnKeyUp(Key key, unichar ch)
9564 bool result = ((int(*)())(void *)controller.OnKeyUp)((void *)controller.controlled, (void *)controller, key, ch);
9566 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp](controller.window, key, ch);
9570 bool OnKeyHit(Key key, unichar ch)
9572 bool result = ((int(*)())(void *)controller.OnKeyHit)((void *)controller.controlled, (void *)controller, key, ch);
9574 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit](controller.window, key, ch);
9578 bool OnMouseMove(int x, int y, Modifiers mods)
9580 bool result = ((int(*)())(void *)controller.OnMouseMove)((void *)controller.controlled, (void *)controller, x, y, mods);
9582 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove](controller.window, x, y, mods);
9586 bool OnLeftButtonDown(int x, int y, Modifiers mods)
9588 bool result = ((int(*)())(void *)controller.OnLeftButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
9590 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown](controller.window, x, y, mods);
9594 bool OnLeftButtonUp(int x, int y, Modifiers mods)
9596 bool result = ((int(*)())(void *)controller.OnLeftButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
9598 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp](controller.window, x, y, mods);
9602 bool OnLeftDoubleClick(int x, int y, Modifiers mods)
9604 bool result = ((int(*)())(void *)controller.OnLeftDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
9606 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick](controller.window, x, y, mods);
9610 bool OnRightButtonDown(int x, int y, Modifiers mods)
9612 bool result = ((int(*)())(void *)controller.OnRightButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
9614 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown](controller.window, x, y, mods);
9618 bool OnRightButtonUp(int x, int y, Modifiers mods)
9620 bool result = ((int(*)())(void *)controller.OnRightButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
9622 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp](controller.window, x, y, mods);
9626 bool OnRightDoubleClick(int x, int y, Modifiers mods)
9628 bool result = ((int(*)())(void *)controller.OnRightDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
9630 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick](controller.window, x, y, mods);
9634 bool OnMiddleButtonDown(int x, int y, Modifiers mods)
9636 bool result = ((int(*)())(void *)controller.OnMiddleButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
9638 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown](controller.window, x, y, mods);
9642 bool OnMiddleButtonUp(int x, int y, Modifiers mods)
9644 bool result = ((int(*)())(void *)controller.OnMiddleButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
9646 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp](controller.window, x, y, mods);
9650 bool OnMiddleDoubleClick(int x, int y, Modifiers mods)
9652 bool result = ((int(*)())(void *)controller.OnMiddleDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
9654 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick](controller.window, x, y, mods);
9658 void OnResize(int width, int height)
9660 ((int(*)())(void *)controller.OnResize)((void *)controller.controlled, (void *)controller, width, height);
9661 controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnResize](controller.window, width, height);
9664 void OnRedraw(Surface surface)
9666 ((int(*)())(void *)controller.OnRedraw)((void *)controller.controlled, (void *)controller, surface);
9667 controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw](controller.window, surface);
9672 bool result = ((int(*)())(void *)controller.OnCreate)((void *)controller.controlled, (void *)controller);
9674 result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnCreate](controller.window);
9679 public class WindowController<class V>
9682 property Window window
9686 uint size = class(Window).vTblSize;
9689 windowVTbl = new void *[size];
9690 memcpy(windowVTbl, value._vTbl, size * sizeof(void *));
9691 if(value._vTbl == value._class._vTbl)
9693 value._vTbl = new void *[value._class.vTblSize];
9694 memcpy(value._vTbl + size, value._class._vTbl + size, (value._class.vTblSize - size) * sizeof(void *));
9698 for(c = 0; c < size; c++)
9700 void * function = class(WindowControllerInterface)._vTbl[c];
9701 if(function != DefaultFunction)
9702 value._vTbl[c] = function;
9704 value._vTbl[c] = windowVTbl[c];
9709 memcpy(value._vTbl, windowVTbl, class(Window).vTblSize * sizeof(void *));
9712 get { return window; }
9714 property V controlled
9716 set { controlled = value; }
9717 get { return controlled; }
9719 virtual bool V::OnKeyDown(WindowController controller, Key key, unichar ch);
9720 virtual bool V::OnKeyUp(WindowController controller, Key key, unichar ch);
9721 virtual bool V::OnKeyHit(WindowController controller, Key key, unichar ch);
9722 virtual bool V::OnMouseMove(WindowController controller, int x, int y, Modifiers mods);
9723 virtual bool V::OnLeftButtonDown(WindowController controller, int x, int y, Modifiers mods);
9724 virtual bool V::OnLeftButtonUp(WindowController controller, int x, int y, Modifiers mods);
9725 virtual bool V::OnLeftDoubleClick(WindowController controller, int x, int y, Modifiers mods);
9726 virtual bool V::OnRightButtonDown(WindowController controller, int x, int y, Modifiers mods);
9727 virtual bool V::OnRightButtonUp(WindowController controller, int x, int y, Modifiers mods);
9728 virtual bool V::OnRightDoubleClick(WindowController controller, int x, int y, Modifiers mods);
9729 virtual bool V::OnMiddleButtonDown(WindowController controller, int x, int y, Modifiers mods);
9730 virtual bool V::OnMiddleButtonUp(WindowController controller, int x, int y, Modifiers mods);
9731 virtual bool V::OnMiddleDoubleClick(WindowController controller, int x, int y, Modifiers mods);
9732 virtual void V::OnResize(WindowController controller, int width, int height);
9733 virtual void V::OnRedraw(WindowController controller, Surface surface);
9734 virtual bool V::OnCreate(WindowController controller);
9737 int (** windowVTbl)();