Usermode/AxWin3 - Fixed scan-build complaints, added more complete debug
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / decorator.c
1 /*
2  * Acess2 Window Manager v3 (axwin3)
3  * - By John Hodge (thePowersGang)
4  *
5  * decorator.c
6  * - Window Decorator
7  */
8 #include <common.h>
9 #include <wm.h>
10 #include <decorator.h>
11 #include <wm_messages.h>
12
13 // === IMPORTS ===
14 extern tWindow  *gpWM_FocusedWindow;
15
16 // === PROTOTYPES ===
17 void    Decorator_UpdateBorderSize(tWindow *Window);
18 void    Decorator_Redraw(tWindow *Window);
19  int    Decorator_HandleMessage(tWindow *Window, int Message, int Length, const void *Data);
20
21 // === CONSTANTS ===
22 #define BTN_CLOSE(win)  win->W-16, -16, 14, 14
23 #define BTN_MIN(win)    win->W-32, -16, 14, 14
24 tColour cColourActive_Titlebar   = 0x00CC44;
25 tColour cColourActive_TitleText  = 0x000000;
26 tColour cColourInactive_Titlebar = 0xD0D0D0;
27 tColour cColourInactive_TitleText= 0x000000;
28 tColour cColour_TitleTopBorder   = 0xFFFFFF;
29 tColour cColour_SideBorder       = 0x008000;
30 tColour cColour_BottomBorder     = 0x008000;
31 tColour cColour_CloseBtn         = 0xFF1100;
32  int    ciTitlebarHeight        = 18;
33  int    ciSideBorderWidth       = 2;
34  int    ciBottomBorderWidth     = 4;
35
36 // === CODE ===
37 void Decorator_UpdateBorderSize(tWindow *Window)
38 {
39         Window->BorderT = ciTitlebarHeight;
40         Window->BorderB = 0;
41         Window->BorderL = 0;
42         Window->BorderR = 0;
43         
44         if( Window->Flags & WINFLAG_MAXIMIZED )
45                 return ;
46
47         Window->BorderB = ciBottomBorderWidth;
48         Window->BorderR = ciSideBorderWidth;
49         Window->BorderL = ciSideBorderWidth;
50 }
51
52 void Decorator_Redraw(tWindow *Window)
53 {
54          int    bActive = 0;
55          int    text_width, text_height;
56         
57         // TODO: This could possibly be expensive, but is there a better way?
58         {
59                 tWindow *win;
60                 for(win = gpWM_FocusedWindow; win; win = win->Owner)
61                 {
62                         if(win == Window) {
63                                 bActive = 1;
64                                 break;
65                         }
66                 }
67         }
68
69         // Draw title bar
70         // - Body
71         WM_Render_FillRect(Window,
72                 0, -ciTitlebarHeight, Window->W, ciTitlebarHeight,
73                 (bActive ? cColourActive_Titlebar : cColourInactive_Titlebar)
74                 );
75         // - Top Border
76         WM_Render_FillRect(Window,
77                 0, -ciTitlebarHeight, Window->W, 1,
78                 cColour_TitleTopBorder
79                 );
80         // - Sides
81         WM_Render_FillRect(Window,
82                 0, -ciTitlebarHeight, 1, ciTitlebarHeight,
83                 cColour_SideBorder
84                 );
85         WM_Render_FillRect(Window,
86                 Window->W, -ciTitlebarHeight, 1, ciTitlebarHeight,
87                 cColour_SideBorder
88                 );
89
90         // Get the font height
91         WM_Render_GetTextDims(
92                 NULL,   // TODO: Select font
93                 Window->Title ? Window->Title : "jI", -1,
94                 &text_width, &text_height
95                 );
96         // - Use that to draw the window title on the left of the window
97         WM_Render_DrawText(Window,
98                 ciTitlebarHeight + 4, -(ciTitlebarHeight - (ciTitlebarHeight/2 - text_height/2)),
99                 Window->W - ciTitlebarHeight - 4, text_height,
100                 NULL,   // TODO: Select font
101                 (bActive ? cColourActive_TitleText : cColourInactive_TitleText),
102                 Window->Title ? Window->Title : "--", -1
103                 );
104
105         // TODO: Minimise, Maximise and Close   
106
107         // Maximized windows don't have any other borders
108         if( Window->Flags & WINFLAG_MAXIMIZED )
109                 return ;
110         
111         // Left Border
112         WM_Render_FillRect(Window,
113                 -ciSideBorderWidth, -ciTitlebarHeight,
114                 ciSideBorderWidth, Window->H + ciTitlebarHeight + ciBottomBorderWidth,
115                 cColour_SideBorder
116                 );
117         // Right Border
118         WM_Render_FillRect(Window,
119                 Window->W, -ciTitlebarHeight,
120                 ciSideBorderWidth, Window->H + ciTitlebarHeight + ciBottomBorderWidth,
121                 cColour_SideBorder
122                 );
123         // Bottom Border (hard line)
124         WM_Render_FillRect(Window,
125                 -ciSideBorderWidth, Window->H,
126                 ciSideBorderWidth*2+Window->W, 1,
127                 0x000000
128                 );
129         // Bottom Border
130         WM_Render_FillRect(Window,
131                 -ciSideBorderWidth, Window->H+1,
132                 ciSideBorderWidth*2+Window->W, ciBottomBorderWidth-1,
133                 cColour_BottomBorder
134                 );
135         
136         // Buttons
137         WM_Render_FillRect(Window, BTN_CLOSE(Window), cColour_CloseBtn);
138         // TODO: Conditional for each
139 }
140
141 static inline int Decorator_INT_CoordInRange(int X, int Y, int SX, int SY, int EX, int EY)
142 {
143         _SysDebug("(%i<=%i<%i, %i<=%i<%i", SX, X, EX, SY, Y, EY);
144         return (X >= SX && X < EX && Y >= SY && Y < EY);
145 }
146 static inline int Decorator_INT_CoordInRangeR(int X, int Y, int SX, int SY, int W, int H)
147 {
148         return Decorator_INT_CoordInRange(X, Y, SX, SY, SX+W, SY+H);
149 }
150
151 int Decorator_HandleMessage(tWindow *Window, int Message, int Length, const void *Data)
152 {
153         static tWindow  *btn1_down;
154         static enum {
155                 BTN1_MOVE,
156                 BTN1_RLEFT,
157                 BTN1_RRIGHT,
158                 BTN1_RBOTTOM,
159         } btn1_mode;
160         switch(Message)
161         {
162         case WNDMSG_MOUSEMOVE: {
163                 const struct sWndMsg_MouseMove  *msg = Data;
164
165                 if( Window && btn1_down == Window )
166                 {
167                         switch(btn1_mode)
168                         {
169                         case BTN1_MOVE: // Move
170                                 WM_MoveWindow(Window, Window->X + msg->dX, Window->Y + msg->dY);
171                                 break;
172                         case BTN1_RLEFT:        // Resize left
173                                 if( Window->W + msg->dX > 50 )
174                                 {
175                                         WM_MoveWindow(Window, Window->X + msg->dX, Window->Y);
176                                         WM_ResizeWindow(Window, Window->W - msg->dX, Window->H);
177                                 }
178                                 break;
179                         case BTN1_RRIGHT:       // Resize right
180                                 if( Window->W + msg->dX > 50 )
181                                 {
182                                         WM_ResizeWindow(Window, Window->W + msg->dX, Window->H);
183                                 }
184                                 break;
185                         case BTN1_RBOTTOM:      // Resize bottom
186                                 if( Window->H + msg->dY > 50 )
187                                 {
188                                         WM_ResizeWindow(Window, Window->W, Window->H + msg->dY);
189                                 }
190                                 break;
191                         }
192                         return 0;
193                 }
194
195                 // TODO: Change cursor when hovering over edges
196
197                 if(msg->Y >= 0) return 1;       // Pass
198
199                 // TODO: Handle
200                 return 0; }
201         case WNDMSG_MOUSEBTN: {
202                 const struct sWndMsg_MouseButton        *msg = Data;
203                 
204                 // TODO: Do something with other buttons
205                 // - Window menu for example
206                 if( msg->Button != 0 )
207                         return 1;       // pass on
208
209                 if( !msg->bPressed )
210                         btn1_down = 0;          
211
212                 #define HOTSPOTR(x,y,w,h) Decorator_INT_CoordInRangeR(msg->X, msg->Y, x, y, w, h)
213                 #define HOTSPOTA(sx,sy,ex,ey) Decorator_INT_CoordInRange(msg->X, msg->Y, sx, sy, ew, eh)
214                 // Left resize border
215                 if( msg->bPressed && HOTSPOTR(-ciSideBorderWidth, -ciTitlebarHeight,
216                                 ciSideBorderWidth, ciTitlebarHeight+Window->H+ciBottomBorderWidth) )
217                 {
218                         btn1_down = Window;
219                         btn1_mode = BTN1_RLEFT;
220                         return 0;
221                 }
222                 // Right resize border
223                 if( msg->bPressed && HOTSPOTR(Window->W, -ciTitlebarHeight,
224                         ciSideBorderWidth, ciTitlebarHeight+Window->H+ciBottomBorderWidth) )
225                 {
226                         btn1_down = Window;
227                         btn1_mode = BTN1_RRIGHT;
228                         return 0;
229                 }
230                 // Bottom resize border
231                 if( msg->bPressed && HOTSPOTR(0, Window->H,
232                         Window->W, ciTitlebarHeight) )
233                 {
234                         btn1_down = Window;
235                         btn1_mode = BTN1_RBOTTOM;
236                         return 0;
237                 }
238                 // Titlebar buttons
239                 if( msg->bPressed && Decorator_INT_CoordInRangeR(msg->X, msg->Y, BTN_CLOSE(Window)) )
240                 {
241                         WM_SendMessage(NULL, Window, WNDMSG_CLOSE, 0, NULL);
242                         return 0;
243                 }
244                 // Titlebar - Move
245                 if( msg->bPressed && msg->Y < 0 )
246                 {
247                         btn1_down = Window;
248                         btn1_mode = BTN1_MOVE;
249                         return 0;
250                 }
251                 #undef HOTSPOTR
252                 #undef HOTSPOTA
253
254                 return 1; }
255         default:        // Anything unhandled is passed on
256                 return 1;
257         }
258 }
259

UCC git Repository :: git.ucc.asn.au