1 /*
2  * IceWM
3  *
4  * Copyright (C) 1997-2001 Marko Macek
5  */
6 #include "config.h"
7 #include "wmframe.h"
8 #include "wmbutton.h"
9 #include "wmtitle.h"
10 #include "yxapp.h"
11 #include "yprefs.h"
12 #include "prefs.h"
13 #include "wpixmaps.h"
14 #include "intl.h"
15 
16 static YColorName titleButtonBg(&clrNormalTitleButton);
17 static YColorName titleButtonFg(&clrNormalTitleButtonText);
18 
background(bool active)19 inline YColor YFrameButton::background(bool active) {
20     return YFrameTitleBar::background(active);
21 }
22 
YFrameButton(YFrameTitleBar * parent,char kind)23 YFrameButton::YFrameButton(YFrameTitleBar* parent, char kind) :
24     YButton(parent, actionNull),
25     fKind(kind),
26     fVisible(false)
27 {
28     if (parent->isRight(kind))
29         setWinGravity(NorthEastGravity);
30 
31     addStyle(wsNoExpose);
32     addEventMask(VisibilityChangeMask);
33     setParentRelative();
34 
35     setKind(kind);
36 }
37 
~YFrameButton()38 YFrameButton::~YFrameButton() {
39 }
40 
titlebar() const41 YFrameTitleBar *YFrameButton::titlebar() const {
42     return reinterpret_cast<YFrameTitleBar*>(parent());
43 }
44 
getFrame() const45 YFrameWindow *YFrameButton::getFrame() const {
46     return titlebar()->getFrame();
47 }
48 
focused() const49 bool YFrameButton::focused() const {
50     return getFrame()->focused();
51 }
52 
setKind(char kind)53 void YFrameButton::setKind(char kind) {
54     const unsigned height = wsTitleBar;
55     unsigned width;
56     fKind = kind;
57     if (kind == YFrameTitleBar::Menu) {
58         if (LOOK(lookPixmap | lookMetal | lookGtk | lookFlat | lookMotif)
59             && showFrameIcon)
60             width = height;
61         else {
62             ref<YPixmap> pixmap(getPixmap(0));
63             width = (pixmap == null) ? height : pixmap->width();
64         }
65     }
66     else if (LOOK(lookPixmap | lookMetal | lookGtk | lookFlat)) {
67         ref<YPixmap> pixmap(getPixmap(0));
68         width = (pixmap == null) ? height : pixmap->width();
69     }
70     else if (wmLook == lookWin95) {
71         width = height - 3;
72     }
73     else {
74         width = height;
75     }
76     setSize(width, height);
77 
78     switch (kind) {
79     case YFrameTitleBar::Depth:
80         setAction(actionDepth);
81         setToolTip(_("Raise/Lower"));
82         setTitle("Lower");
83         break;
84     case YFrameTitleBar::Hide:
85         setAction(actionHide);
86         setToolTip(_("Hide"));
87         setTitle("Hide");
88         break;
89     case YFrameTitleBar::Maxi:
90         if (getFrame()->isMaximized()) {
91             setAction(actionRestore);
92             setToolTip(_("Restore"));
93             setTitle("Restore");
94         } else {
95             setAction(actionMaximize);
96             setToolTip(_("Maximize"));
97             setTitle("Maximize");
98         }
99         break;
100     case YFrameTitleBar::Mini:
101         setAction(actionMinimize);
102         setToolTip(_("Minimize"));
103         setTitle("Minimize");
104         break;
105     case YFrameTitleBar::Roll:
106         setAction(actionRollup);
107         if (getFrame()->isRollup()) {
108             setToolTip(_("Rolldown"));
109             setTitle("Rolldown");
110         } else {
111             setToolTip(_("Rollup"));
112             setTitle("Rollup");
113         }
114         break;
115     case YFrameTitleBar::Menu:
116         setAction(actionNull);
117         setActionListener(getFrame());
118         setPopup(getFrame()->windowMenu());
119         setTitle("SysMenu");
120         break;
121     case YFrameTitleBar::Close:
122         setAction(actionClose);
123         setToolTip(_("Close"));
124         setTitle("Close");
125         break;
126     }
127 }
128 
handleButton(const XButtonEvent & button)129 void YFrameButton::handleButton(const XButtonEvent &button) {
130     if (button.type == ButtonPress &&
131         getAction() != actionRollup &&
132         (buttonRaiseMask & (1 << (button.button - Button1))))
133     {
134         if (!(button.state & ControlMask) && raiseOnClickButton) {
135             getFrame()->activate();
136             if (raiseOnClickButton && getAction() != actionDepth)
137                 getFrame()->wmRaise();
138         }
139     }
140     YButton::handleButton(button);
141 }
142 
handleClick(const XButtonEvent & up,int count)143 void YFrameButton::handleClick(const XButtonEvent &up, int count) {
144     if (getAction() == actionNull && up.button == Button1 && !(count % 2)) {
145         setArmed(false, false);
146         getFrame()->wmClose();
147     }
148     else if (up.button == Button3 && notbit(up.state, xapp->AltMask)) {
149         if (!isPopupActive())
150             getFrame()->popupSystemMenu(this, up.x_root, up.y_root,
151                                         YPopupWindow::pfCanFlipVertical |
152                                         YPopupWindow::pfCanFlipHorizontal);
153     }
154     else if (getAction() == actionRollup && up.button == Button1) {
155         actionPerformed(getAction(), up.state);
156     }
157     else {
158         YButton::handleClick(up, count);
159     }
160 }
161 
handleBeginDrag(const XButtonEvent & down,const XMotionEvent &)162 bool YFrameButton::handleBeginDrag(const XButtonEvent &down, const XMotionEvent &/*motion*/) {
163     bool dragButton = inrange(int(down.button), Button2, Button3);
164     if (dragButton && getFrame()->canMove()) {
165         if (!isPopupActive()) {
166             YFrameTitleBar* tbar = titlebar();
167             getFrame()->startMoveSize(true, true,
168                                       0, 0,
169                                       down.x + x() + (tbar ? tbar->x() : 0),
170                                       down.y + y() + (tbar ? tbar->y() : 0));
171             return true;
172         }
173     }
174     return false;
175 }
176 
handleVisibility(const XVisibilityEvent & visib)177 void YFrameButton::handleVisibility(const XVisibilityEvent& visib) {
178     bool prev = fVisible;
179     fVisible = (visib.state != VisibilityFullyObscured);
180     if (prev < fVisible)
181         repaint();
182 }
183 
updatePopup()184 void YFrameButton::updatePopup() {
185     getFrame()->updateMenu();
186 }
187 
actionPerformed(YAction action,unsigned int modifiers)188 void YFrameButton::actionPerformed(YAction action, unsigned int modifiers) {
189     if (hasbit(modifiers, ShiftMask)) {
190         switch (action.ident()) {
191             case actionMaximize: action = actionMaximizeVert; break;
192             case actionMinimize: action = actionHide; break;
193             case actionClose: action = actionKill; break;
194             default: break;
195         }
196     }
197     getFrame()->actionPerformed(action, modifiers);
198 }
199 
getPixmap(int pn) const200 ref<YPixmap> YFrameButton::getPixmap(int pn) const {
201     if (fKind == YFrameTitleBar::Maxi) {
202         if (getFrame()->isMaximized() && restorePixmap[pn] != null)
203             return restorePixmap[pn];
204         else
205             return maximizePixmap[pn];
206     }
207     else if (fKind == YFrameTitleBar::Mini)
208         return minimizePixmap[pn];
209     else if (fKind == YFrameTitleBar::Close)
210         return closePixmap[pn];
211     else if (fKind == YFrameTitleBar::Hide)
212         return hidePixmap[pn];
213     else if (fKind == YFrameTitleBar::Roll)
214         return getFrame()->isRollup() ? rolldownPixmap[pn] : rollupPixmap[pn];
215     else if (fKind == YFrameTitleBar::Depth)
216         return depthPixmap[pn];
217     else if (fKind == YFrameTitleBar::Menu &&
218              LOOK(lookPixmap | lookMetal | lookGtk | lookFlat | lookMotif))
219         return menuButton[pn];
220     else
221         return null;
222 }
223 
configure(const YRect2 & r)224 void YFrameButton::configure(const YRect2& r) {
225     if (r.resized()) {
226         repaint();
227     }
228 }
229 
repaint()230 void YFrameButton::repaint() {
231     if (fVisible && visible() && width() > 1 && height() > 1) {
232         GraphicsBuffer(this).paint();
233     }
234 }
235 
paint(Graphics & g,const YRect &)236 void YFrameButton::paint(Graphics &g, const YRect &/*r*/) {
237     int xPos = 1, yPos = 1;
238     int pn = LOOK(lookPixmap | lookMetal | lookGtk | lookFlat) && focused();
239     const bool armed(isArmed());
240 
241     g.setColor(titleButtonBg);
242 
243     if (fOver && rolloverTitleButtons) {
244         if (pn == 1) {
245             pn = 2;
246         } else {
247             pn = 0;
248         }
249     }
250 
251     int iconSize = YIcon::smallSize();
252     ref<YIcon> icon = (getAction() == actionNull)
253                     ? getFrame()->clientIcon() : null;
254 
255     ref<YPixmap> pixmap = getPixmap(pn);
256     if (pixmap == null && pn) {
257         pixmap = getPixmap(0);
258     }
259 
260     if (pixmap != null && pixmap->depth() != g.rdepth()) {
261         tlog("YFrameButton::%s: attempt to use pixmap 0x%lx of depth %d with gc of depth %d\n",
262                 __func__, pixmap->pixmap(), pixmap->depth(), g.rdepth());
263     }
264 
265     if (wmLook == lookWarp4) {
266         g.fillRect(0, 0, width(), height());
267 
268         if (armed) {
269             g.setColor(background(true));
270             g.fillRect(1, 1, width() - 2, height() - 2);
271         }
272 
273         if (getAction() == actionNull) {
274             if (icon != null && showFrameIcon) {
275                 icon->draw(g,
276                            (int(width()) - iconSize) / 2,
277                            (int(height()) - iconSize
278                             + MenuButtonIconVertOffset) / 2,
279                            iconSize);
280             }
281         } else {
282             if (pixmap != null)
283                 g.copyPixmap(pixmap, 0, armed ? 20 : 0,
284                              pixmap->width(), pixmap->height() / 2,
285                              (int(width()) - int(pixmap->width())) / 2,
286                              (int(height()) - int(pixmap->height()) / 2));
287         }
288     }
289     else if (LOOK(lookMotif | lookWarp3 | lookNice)) {
290         g.draw3DRect(0, 0, width() - 1, height() - 1, !armed);
291 
292         if (wmLook != lookMotif) {
293             if (armed) {
294                 xPos = 3;
295                 yPos = 3;
296                 g.drawLine(1, 1, width() - 2, 1);
297                 g.drawLine(1, 1, 1, height() - 2);
298                 g.drawLine(2, 2, width() - 3, 2);
299                 g.drawLine(2, 2, 2, height() - 3);
300             } else {
301                 xPos = 2;
302                 yPos = 2;
303                 g.drawRect(1, 1, width() - 3, width() - 3);
304             }
305         }
306 
307         unsigned const w(LOOK(lookMotif) ? width() - 2 : width() - 4);
308         unsigned const h(LOOK(lookMotif) ? height() - 2 : height() - 4);
309 
310         g.fillRect(xPos, yPos, w, h);
311         if (getAction() == actionNull) {
312             if (icon != null && showFrameIcon) {
313                 icon->draw(g,
314                            xPos + (int(w) - iconSize) / 2,
315                            yPos + (int(h) - iconSize
316                                + MenuButtonIconVertOffset) / 2,
317                            iconSize);
318             }
319             else if (pixmap != null) {
320                 g.drawCenteredPixmap(xPos, yPos, w, h, pixmap);
321             }
322         } else {
323             if (pixmap != null)
324                 g.drawCenteredPixmap(xPos, yPos, w, h, pixmap);
325         }
326     }
327     else if (wmLook == lookWin95) {
328         if (getAction() == actionNull) {
329             g.setColor(background(focused()));
330             g.fillRect(0, 0, width(), height());
331             if (icon != null && showFrameIcon) {
332                 icon->draw(g,
333                            (int(width()) - iconSize) / 2,
334                            (int(height()) - iconSize
335                             + MenuButtonIconVertOffset) / 2,
336                            iconSize);
337             }
338         } else {
339             g.fillRect(0, 0, width(), height());
340             g.drawBorderW(0, 0, width() - 1, height() - 1, !armed);
341 
342             if (armed)
343                 xPos = yPos = 2;
344 
345             if (pixmap != null)
346                 g.drawCenteredPixmap(xPos, yPos, width() - 3, height() - 3,
347                                      pixmap);
348         }
349     }
350     else if (LOOK(lookPixmap | lookMetal | lookFlat | lookGtk)) {
351         if (pixmap != null && getPixmap(1) != null) {
352             int const h(pixmap->height() / 2);
353             g.copyPixmap(pixmap, 0, armed ? h : 0, pixmap->width(), h, 0, 0);
354         } else {
355             // If we have only an image we change
356             // the over or armed color and paint it.
357            g.fillRect(0, 0, width(), height());
358            if (armed)
359                g.setColor(background(true).darker());
360            else if (rolloverTitleButtons && fOver)
361                g.setColor(background(true).brighter());
362            g.fillRect(1, 1, width()-2, height()-3);
363            if (pixmap != null) {
364                int x((int(width())  - int(pixmap->width()))  / 2);
365                int y((int(height()) - int(pixmap->height())) / 2);
366                g.drawPixmap(pixmap, x, y);
367             }
368         }
369 
370         if (getAction() == actionNull && icon != null && showFrameIcon) {
371             icon->draw(g,
372                        (int(width()) - iconSize) / 2,
373                        (int(height()) - iconSize
374                         + MenuButtonIconVertOffset) / 2,
375                        iconSize);
376         }
377     }
378 }
379 
380 
paintFocus(Graphics &,const YRect &)381 void YFrameButton::paintFocus(Graphics &/*g*/, const YRect &/*r*/) {
382 }
383 
384 // vim: set sw=4 ts=4 et:
385