ecere;samples/blokus: Grouped High DPI tweaks separately with HIGH_DPI preprocessor...
[sdk] / ecere / src / gui / skins / WindowsSkin.ec
index f4a0214..6cbd743 100644 (file)
@@ -1,24 +1,47 @@
-namespace gui::skins;
+#if defined(WIN32)
+#define WIN32_LEAN_AND_MEAN
+#define String _String
+#define Method _Method
+#define strlen _strlen
+#include <windows.h>
+#undef Method
+#undef String
+#undef strlen
+#endif
 
 import "Window"
 
+#if !defined(WIN32)
+bool gui::drivers::XGetBorderWidths(Window window, Box box);
+#endif
+
+namespace gui::skins;
+
 #define BORDER       4
 #define TOP          4
 #define BOTTOM       4
 #define CORNER       (BORDER * 2)
+#if defined(HIGH_DPI)
+#define BUTTON_SIZE  45
+#define CAPTION      60
+#else
+#define BUTTON_SIZE  15
 #define CAPTION      20
+#endif
 #define DEAD_BORDER  3
 #define MIN_WIDTH    60
 #define MIN_HEIGHT   3
 #define BUTTON_OFFSET   2
+#if defined(HIGH_DPI)
+#define NAME_OFFSET   12
+#else
 #define NAME_OFFSET   2
+#endif
 #define NAME_OFFSETX  4
 
 #define SB_WIDTH  16
 #define SB_HEIGHT 16
 
-#define MENU_HEIGHT     25
-#define STATUS_HEIGHT   18
 
 #define GRADIENT_SMOOTHNESS 1.0f
 
@@ -38,16 +61,18 @@ static ColorKey gradient[] =
 #define GRADIENT_DIRECTION vertical
 static ColorKey gradient[] =
 {
-   { ColorAlpha { 255, { 180, 200, 220} }, 0.00f },
+   //{ ColorAlpha { 255, { 180, 200, 220} }, 0.00f },
+   { ColorAlpha { 255, menuBarColor }, 0.00f },
    { ColorAlpha { 255, { 255, 255, 255} }, 0.60f },
-   { ColorAlpha { 255, { 128, 128, 130} }, 1.00f }
+   { ColorAlpha { 255, { 158, 158, 160} }, 1.00f }
 };
 
 static ColorKey gradientInactive[] =
 {
-   { ColorAlpha { 255, { 160, 180, 200} },  0.00f },
+   //{ ColorAlpha { 255, { 160, 180, 200} },  0.00f },
+   { ColorAlpha { 255, popupMenuColor }, 0.00f },
    { ColorAlpha { 255, { 220, 220, 220} }, 0.60f },
-   { ColorAlpha { 255, { 100, 100, 100} }, 1.00f }
+   { ColorAlpha { 255, { 120, 120, 120} }, 1.00f }
 };
 
 /*
@@ -111,12 +136,20 @@ class WindowsSkin : Skin
 
    FontResource ::SystemFont()
    {
-      return FontResource { faceName = "Tahoma", size = 8.25f };
+#if defined(HIGH_DPI)
+      return FontResource { faceName = $"Tahoma", size = 18.25f };
+#else
+      return FontResource { faceName = $"Tahoma", size = 8.25f };
+#endif
    }
 
    FontResource ::CaptionFont()
    {
-      return FontResource { faceName = "Tahoma", size = 8.25f, bold = true };
+#if defined(HIGH_DPI)
+      return FontResource { faceName = $"Tahoma", size = 18.25f, bold = true };
+#else
+      return FontResource { faceName = $"Tahoma", size = 8.25f, bold = true };
+#endif
    }
 
    char * ::CursorsBitmaps(uint id, int * hotSpotX, int *hotSpotY, byte ** paletteShades)
@@ -145,14 +178,34 @@ public class WindowsSkin_Window : Window
 
       if(hasMenuBar && state != minimized)
       {
-         *h += MENU_HEIGHT;
+         *h += skinMenuHeight;
       }
       if(statusBar && state != minimized)
       {
-         *h += STATUS_HEIGHT;
+         *h += statusBarHeight;
       }
 
-      if(nativeDecorations) return;
+      if(nativeDecorations && rootWindow == this && windowHandle)
+      {
+#if defined(WIN32)
+         RECT rcClient = { 0 }, rcWindow = { 0 };
+         if(GetClientRect(windowHandle, &rcClient) && GetWindowRect(windowHandle, &rcWindow))
+         {
+            *w += (rcWindow.right - rcWindow.left) - rcClient.right;
+            *h += (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
+         }
+
+         // PrintLn(_class.name, " is at l = ", rcWindow.left, ", r = ", rcWindow.right);
+#else
+         Box widths = { 0 };
+#if !defined(__ANDROID__)
+         XGetBorderWidths(this, widths);
+#endif
+         *w += widths.left + widths.right;
+         *h += widths.top + widths.bottom;
+#endif
+         return;
+      }
       if((((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel) && state != minimized)
       {
          *w += 4;
@@ -163,7 +216,7 @@ public class WindowsSkin_Window : Window
          *w += 2 * BORDER;
          *h += TOP + BOTTOM;
       }
-      if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
+      if(((BorderBits)borderStyle).fixed && (state != maximized || !GetParentMenuBar()))
       {
          *h += CAPTION;
          if(!((BorderBits)borderStyle).sizable || state == minimized)
@@ -182,8 +235,8 @@ public class WindowsSkin_Window : Window
    void SetWindowMinimum(MinMaxValue * mw, MinMaxValue * mh)
    {
       bool isNormal = (state == normal);
-      if(nativeDecorations) return;
-      if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
+      if(nativeDecorations && rootWindow == this && windowHandle) return;
+      if(((BorderBits)borderStyle).fixed && (state != maximized || !GetParentMenuBar()))
       {
          *mw = MIN_WIDTH;
          *mh = MIN_HEIGHT;
@@ -216,12 +269,30 @@ public class WindowsSkin_Window : Window
 
       if(hasMenuBar)
       {
-         *y += MENU_HEIGHT;
+         *y += skinMenuHeight;
       }
 
       GetDecorationsSize(&aw, &ah);
 
-      if(!nativeDecorations)
+      if(nativeDecorations && rootWindow == this && windowHandle)
+      {
+#if defined(WIN32)
+         RECT rcWindow;
+         POINT client00 = { 0, 0 };
+         ClientToScreen(windowHandle, &client00);
+         GetWindowRect(windowHandle, &rcWindow);
+         *x += client00.x - rcWindow.left;
+         *y += client00.y - rcWindow.top;
+#else
+         Box widths;
+#if !defined(__ANDROID__)
+         XGetBorderWidths(this, widths);
+#endif
+         *x += widths.left;
+         *y += widths.top;
+#endif
+      }
+      else
       {
          // Compute client area start
          if(((BorderBits)borderStyle).deep || ((BorderBits)borderStyle).bevel)
@@ -236,7 +307,7 @@ public class WindowsSkin_Window : Window
             *y += TOP;
          }
 
-         if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
+         if(((BorderBits)borderStyle).fixed && (state != maximized || !GetParentMenuBar()))
          {
             *y += CAPTION;
             if(!((BorderBits)borderStyle).sizable || state == minimized)
@@ -265,8 +336,9 @@ public class WindowsSkin_Window : Window
    {
       bool isNormal = (state == normal);
       int top = 0, border = 0, bottom = 0;
+      Window parentMenuBar = GetParentMenuBar();
 
-      if(nativeDecorations) return;
+      if(nativeDecorations && rootWindow == this && windowHandle) return;
 
       if(state == minimized)
          top = border = bottom = DEAD_BORDER;
@@ -295,7 +367,7 @@ public class WindowsSkin_Window : Window
          if(((BorderBits)borderStyle).contour)
          {
             deepBorder = border;
-            deepTop = (((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar)) ? (top + CAPTION) : top;
+            deepTop = (((BorderBits)borderStyle).fixed && (state != maximized || !parentMenuBar)) ? (top + CAPTION) : top;
             deepBottom = (((BorderBits)borderStyle).sizable && isNormal) ? bottom : border;
          }
 
@@ -303,13 +375,13 @@ public class WindowsSkin_Window : Window
             size.w - deepBorder - deepBorder, size.h - deepBottom - deepTop);
       }
 
-      if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
+      if(((BorderBits)borderStyle).fixed && (state != maximized || !parentMenuBar))
       {
          if(state != maximized || !((BorderBits)borderStyle).sizable)
          {
             // Frame for ES_CAPTION windows
             surface.Bevel(false, 0, 0, size.w, size.h);
-            surface.SetForeground(activeBorder);
+            surface.SetForeground(formColor);
             surface.Rectangle(2, 2, size.w-3, size.h-3);
 
             // Resizeable frame is 1 pixel thicker 
@@ -326,7 +398,7 @@ public class WindowsSkin_Window : Window
             GRADIENT_SMOOTHNESS, GRADIENT_DIRECTION,
                border, top, size.w - border - 1, top + CAPTION - 2);
 
-         surface.SetForeground(activeBorder);
+         surface.SetForeground(formColor);
          if(state != minimized)
             surface.HLine(border, size.w-border-1, top + CAPTION-1);
 
@@ -336,7 +408,7 @@ public class WindowsSkin_Window : Window
          if(name)
          {
             int buttonsSize = border +
-               ((hasMaximize || hasMinimize) ? 52 : 18);
+               ((hasMaximize || hasMinimize) ? (BUTTON_SIZE*3)+7 : (BUTTON_SIZE+3));
             surface.WriteTextDots(left, border + NAME_OFFSETX, top + NAME_OFFSET, 
                size.w - (buttonsSize + border + 4), name, strlen(name));
          }
@@ -351,7 +423,7 @@ public class WindowsSkin_Window : Window
       {
          if(sbh && sbh.visible && sbv && sbv.visible)
          {
-            surface.SetBackground(activeBorder);
+            surface.SetBackground(formColor);
             surface.Area(
                clientStart.x + clientSize.w,
                clientStart.y + clientSize.h,
@@ -365,9 +437,9 @@ public class WindowsSkin_Window : Window
    {
       bool isNormal = (state == normal);
       bool result = false;
-      if(nativeDecorations) return false;
+      if(nativeDecorations && rootWindow == this && windowHandle) return false;
 
-      if(((BorderBits)borderStyle).fixed && (state != maximized || !parent.menuBar))
+      if(((BorderBits)borderStyle).fixed && (state != maximized || !GetParentMenuBar()))
       {
          int corner = 0, border = 0, top = 0;
          if(((BorderBits)borderStyle).sizable && isNormal)
@@ -390,7 +462,7 @@ public class WindowsSkin_Window : Window
       bool result = false;
 
       *resizeX = *resizeY = *resizeEndX = *resizeEndY = false;
-      if(nativeDecorations) return false;
+      if(nativeDecorations && rootWindow == this && windowHandle) return false;
 
       if(((BorderBits)borderStyle).sizable && (state == normal))
       {
@@ -428,13 +500,13 @@ public class WindowsSkin_Window : Window
       int top = 0, border = 0;
       int insideBorder = 0;
 
-      if(!nativeDecorations
+      if(!nativeDecorations || rootWindow != this || !windowHandle)
       {
          if(state == minimized)
             top = border = DEAD_BORDER;
          else if(((BorderBits)borderStyle).sizable)
          {
-            if(state == maximized && parent.menuBar)
+            if(state == maximized && GetParentMenuBar())
             {
                top = 2;
                border = 2;
@@ -459,6 +531,11 @@ public class WindowsSkin_Window : Window
          if(((BorderBits)borderStyle).deep)
             insideBorder += 2;
       }
+      else
+      {
+         border = clientStart.x;
+         insideBorder = border;
+      }
 
       if(menuBar)
       {
@@ -466,7 +543,7 @@ public class WindowsSkin_Window : Window
             menuBar.visible = false;
          else
             menuBar.visible = true;
-         menuBar.Move(clientStart.x, clientStart.y - MENU_HEIGHT, size.w - insideBorder * 2, MENU_HEIGHT);
+         menuBar.Move(clientStart.x, clientStart.y - skinMenuHeight, size.w - insideBorder * 2, skinMenuHeight);
       }
       if(statusBar)
       {
@@ -475,24 +552,32 @@ public class WindowsSkin_Window : Window
          else
          {
             statusBar.visible = true;
-            statusBar.anchor = { left = clientStart.x, bottom = border };
-            statusBar.size.w = size.w - insideBorder * 2;
+            if(nativeDecorations && rootWindow == this && windowHandle)
+            {
+               statusBar.anchor = { left = clientStart.x, bottom = (int)(size.h - clientSize.h - clientStart.y - statusBarHeight ) };
+               statusBar.size.w = size.w - insideBorder * 2;
+            }
+            else
+            {
+               statusBar.anchor = { left = clientStart.x, bottom = border };
+               statusBar.size.w = size.w - insideBorder * 2;
+            }
          }
       }
-      if(!nativeDecorations)
+      if(!nativeDecorations || rootWindow != this || !windowHandle)
       {
          if(sysButtons[0])
          {
-            sysButtons[0].anchor = { right = 35 + border, top = top + BUTTON_OFFSET };
-            sysButtons[0].size = { 15, 15 };
+            sysButtons[0].anchor = { right = 2+(2*BUTTON_SIZE+3) + border, top = top + BUTTON_OFFSET };
+            sysButtons[0].size = { BUTTON_SIZE, BUTTON_SIZE };
             sysButtons[0].bevel = true;
             sysButtons[0].bitmap = { skinBitmaps[(state == minimized) ? restore : minimize] };
             sysButtons[0].visible = true;
          }
          if(sysButtons[1])
          {
-            sysButtons[1].anchor = { right = 20 + border, top = top + BUTTON_OFFSET };
-            sysButtons[1].size = { 15, 15 };
+            sysButtons[1].anchor = { right = 2+(BUTTON_SIZE+3) + border, top = top + BUTTON_OFFSET };
+            sysButtons[1].size = { BUTTON_SIZE, BUTTON_SIZE };
             sysButtons[1].bevel = true;
             sysButtons[1].bitmap = { skinBitmaps[(state == maximized) ? restore : maximize] };
             sysButtons[1].visible = true;
@@ -500,7 +585,7 @@ public class WindowsSkin_Window : Window
          if(sysButtons[2])
          {
             sysButtons[2].anchor = { right = 2 + border, top = top + BUTTON_OFFSET };
-            sysButtons[2].size = { 15, 15 };
+            sysButtons[2].size = { BUTTON_SIZE, BUTTON_SIZE };
             sysButtons[2].bevel = true;
             sysButtons[2].bitmap = { skinBitmaps[close] };
             sysButtons[2].visible = true;
@@ -508,3 +593,321 @@ public class WindowsSkin_Window : Window
       }
    }
 }
+
+
+#define PUREVTBL(c)     (*(void ***)((byte *)class(c).data + sizeof(uintptr)))
+#define CAPTION_DISTANCE   18
+
+default:
+static void Dummy()
+{
+   Window a;
+   a.OnApplyGraphics();
+   a.OnRedraw(null);
+}
+
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnApplyGraphics;
+extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw;
+private:
+
+public class WindowsSkin_Button : Button
+{
+   void OnRedraw(Surface surface)
+   {
+      if(isRadio)
+      {
+         ((void (*)(Window, Surface))PUREVTBL(Button)[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw])(this, surface);
+         return;
+      }
+      // if(bevel)
+      {
+         ButtonState state = this.buttonState;
+         Bitmap buttonBitmap = bitmap ? bitmap.bitmap : null;
+         char * text = this.text;
+         int offset = (state == down && this.offset) ? 1 : 0;
+         Color backColor = background;
+         int isDefault = this.isDefault;
+         Font font;
+         int tw = 0, th = 0;
+         int bw = 0, bh = 0;
+
+         font = fontObject;
+         surface.TextFont(font);
+         if(text)
+            surface.TextExtent(text, strlen(text),&tw, &th);
+
+         if(bevelOver && checked)
+            offset = 1;
+
+         if(!isEnabled)
+         {
+            if(bitmaps[disabled]) buttonBitmap = bitmaps[disabled].bitmap;
+            state = disabled;
+         }
+
+         if(buttonBitmap && buttonStyle.bevelOver && !buttonStyle.checkBox && !buttonStyle.radio && text)
+            isDefault = 0;
+
+         // Background
+         if((bevel /*|| bevelOver*/) && opacity && backColor)
+         {
+            if(!scaleBitmap || !buttonBitmap)
+            {
+               ColorKey keys[2] = { { silver, 0.0f }, { white, 1.0f } };
+               surface.Gradient(keys, sizeof(keys) / sizeof(ColorKey), 1, vertical, 0, 0, clientSize.w-1, clientSize.h-1);
+            }
+         }
+
+         // Checkbox
+         if(isCheckbox && !buttonBitmap)
+         {
+            int height = 16;
+            int start = (clientSize.h - height) / 2;
+
+            if(!isEnabled)
+               // surface.SetBackground(formColor);
+               surface.SetBackground(gainsboro);
+            else if(active && !text)
+               surface.SetBackground((offset ? formColor : Color { 0,0,170 }));
+            else
+               surface.SetBackground((offset ? formColor : white));
+            surface.Area(2, start+2,height-3,start+height-3);
+
+            surface.SetForeground(Color { 85, 85, 85 });
+            surface.HLine(0, height - 2, start + 0);
+            surface.VLine(start+1, start+height - 2, 0);
+
+            surface.SetForeground(Color { 64,64,64 });
+            surface.HLine(1, height - 3, start + 1);
+            surface.VLine(start+2, start+height - 3, 1);
+
+            surface.SetForeground(Color { 212,208,200 });
+            surface.HLine(1, height - 2, start + height-2);
+            surface.VLine(start+1, start+height - 3, height-2);
+
+            surface.SetForeground(white);
+            surface.HLine(0, height - 1, start + height-1);
+            surface.VLine(start+0, start+height - 2, height-1);
+
+            if(checked)
+            {
+               if(active && !text)
+                  surface.SetForeground(white);
+               else if(!isEnabled)
+                  surface.SetForeground(Color { 85, 85, 85 });
+               else
+                  surface.SetForeground(black);
+               surface.DrawLine(4, start+8, 7,start+11);
+               surface.DrawLine(4, start+9, 7,start+12);
+               surface.DrawLine(7, start+11, 11,start+3);
+               surface.DrawLine(7, start+12, 11,start+4);
+            }
+         }
+
+         // Bitmaps
+         if(buttonBitmap)
+         {
+            surface.SetForeground(white);
+            if(isRadio || isCheckbox)
+            {
+               int x = 0, y = (clientSize.h-buttonBitmap.height)/2;
+               if(bevelOver && text)
+               {
+                  x = (CAPTION_DISTANCE-buttonBitmap.width)/2 + offset;
+                  y = (clientSize.h-buttonBitmap.height)/2 + offset;
+
+
+               }
+
+               // Radio Buttons and Checkboxes
+               surface.Blit(buttonBitmap,
+                  x, y,
+                  0,0,buttonBitmap.width,buttonBitmap.height);
+            }
+            else 
+            {
+               // Push Buttons
+               if(scaleBitmap)
+               {
+                  if(bevel || offset)
+                     surface.Stretch(buttonBitmap, 
+                        1 + offset, 1 + offset,0,0,
+                        clientSize.w-3,clientSize.h-3,buttonBitmap.width,buttonBitmap.height);
+                  else
+                     surface.Stretch(buttonBitmap, 0,0, 0,0,
+                        clientSize.w,clientSize.h,buttonBitmap.width,buttonBitmap.height);
+               }
+               else
+               {
+                  int x, y;
+                  bw = buttonBitmap.width;
+                  bh = buttonBitmap.height;
+
+                  if(bitmapAlignment == left || bitmapAlignment == right)
+                  {
+                     if(bitmapAlignment == left)
+                        x = 2;
+                     else
+                        x = clientSize.w-bw-2;
+                     y = (clientSize.h-bh)/2;
+                  }
+                  else if(bitmapAlignment == top || bitmapAlignment == bottom)
+                  {
+                     x = (clientSize.w-bw)/2;
+                     if(bitmapAlignment == top)
+                        y = 2;
+                     else
+                        y = clientSize.h-bh-2;
+                  }
+                  else
+                  {
+                     x = (clientSize.w-bw)/2;
+                     y = (clientSize.h-bh - (int)(buttonStyle.bevelOver && text) * th)/2;
+                  }
+                  if(buttonStyle.bevel || buttonStyle.offset)
+                  {
+                     x += offset;
+                     y += offset;
+                  }
+                  surface.Blit(buttonBitmap, x,y, 0,0, bw,bh);
+               }
+            }
+         }
+
+         // Shadows
+         if(bevel || (bevelOver && (state == down || state == over || checked)))
+         {
+            if(state == down || checked)
+            {
+               surface.SetForeground(Color { 85, 85, 85 });
+               surface.HLine(isDefault + 0, clientSize.w-2-isDefault, 0);
+               surface.VLine(isDefault + 1, clientSize.h-2-isDefault, 0);
+               surface.SetForeground(white);
+               surface.HLine(isDefault + 0, clientSize.w-1-isDefault, clientSize.h-1-isDefault);
+               surface.VLine(isDefault + 0, clientSize.h-2-isDefault, clientSize.w-1-isDefault);
+            }
+            else
+            {
+               surface.SetForeground(white);
+               surface.HLine(0 + isDefault, clientSize.w-2 - isDefault,  isDefault);
+               surface.VLine(1 + isDefault, clientSize.h-2 - isDefault,  isDefault);
+               surface.SetForeground(Color { 85, 85, 85 });
+               surface.HLine(1 + isDefault, clientSize.w-2 - isDefault, clientSize.h-2 - isDefault);
+               surface.VLine(1 + isDefault, clientSize.h-3 - isDefault, clientSize.w-2 - isDefault);
+
+               if(bevel)
+               {
+                  surface.SetForeground(black);
+                  surface.HLine( isDefault, clientSize.w-1 - isDefault, clientSize.h-1 - isDefault);
+                  surface.VLine( isDefault, clientSize.h-2 - isDefault, clientSize.w-1 - isDefault);
+               }
+            }
+         }
+
+         // Text
+         surface.TextOpacity(false);
+         surface.SetForeground(foreground);
+         if(text)
+         {
+            int tw, th;
+            surface.TextExtent(text, strlen(text),&tw, &th);
+
+            if((isRadio || isCheckbox) && !bevelOver)
+               WriteCaption(surface, CAPTION_DISTANCE + 3, // + clientSize.h,
+                  (clientSize.h - th - 4)/2);
+            else 
+            {
+               int x, y = (clientSize.h - th - 1)/2 + offset;
+               
+               if(buttonStyle.bevelOver && buttonBitmap && !buttonStyle.checkBox && !buttonStyle.radio)
+               {
+                  if(bitmapAlignment == top)
+                     y = (clientSize.h - bh - 4 - th - 5)/2 + offset + bh + 4;
+                  else if(bitmapAlignment == bottom)
+                     y = (clientSize.h - bh - 4 - th - 5)/2 + offset;
+                  else//if(bitmapAlignment == left || bitmapAlignment == right)
+                     y = clientSize.h - th - 5 + offset;
+               }
+               else
+                  y = (clientSize.h - th - 1)/2 + offset;
+
+               if(ellipsis)
+               {
+                  int width = clientSize.w - 2*6;
+                  int x = 6 + offset;
+
+                  surface.WriteTextDots(alignment, x, y, width, text, strlen(text));
+               }
+               else
+               {
+                  int width = clientSize.w - 2 * 6;
+                  x = 6 + offset;
+                  if(bitmapAlignment == left || bitmapAlignment == right)
+                  {
+                     if(bitmapAlignment == left)
+                        x += bw + 4;
+                     width -= bw + 4;
+                  }
+                  if(isCheckbox || ((isRadio /*|| bevelOver*/) && buttonBitmap))
+                  {
+                     x += CAPTION_DISTANCE + 3;
+                  }
+
+                  if(tw < width)
+                  {
+                     if(alignment == right)
+                        x += width - tw - 1;
+                     else if(alignment == center)
+                        x += (width - tw) / 2;
+                  }
+                  WriteCaption(surface, x, y);
+               }
+            }
+         }
+
+         // Activation Highlight
+         if(isDefault)
+         {
+            surface.SetForeground(black);
+            surface.Rectangle(0,0,clientSize.w-1,clientSize.h-1);
+         }
+         if(!bevelOver && !isRemote)
+         {
+            if(active) // && (text || !(buttonStyle.radio || buttonStyle.checkBox)))
+            {
+               int x1,y1,x2,y2;
+               surface.SetForeground(black);
+               surface.LineStipple(0x5555);
+
+               if((isRadio || isCheckbox) && text)
+               {
+                  x1 = CAPTION_DISTANCE;  // + clientSize.h;
+                  y1 = 0;
+                  x2 = clientSize.w-4;
+                  y2 = clientSize.h-4;
+               }
+               else
+               {
+                  x1 = 3+offset;
+                  y1 = 3+offset;
+                  x2 = clientSize.w - 5+offset;
+                  y2 = clientSize.h - 5+offset;
+
+                  if(isRadio || isCheckbox)
+                  {
+                     x1-=3;
+                     y1-=3;
+                     x2+=1;
+                     y2+=1;
+                  }
+               }
+               if((x2 - x1) & 1) x2++;
+               if((y2 - y1) & 1) y2++;
+
+               surface.Rectangle(x1, y1, x2, y2);
+               surface.LineStipple(0);
+            }
+         }
+      }
+   }
+}