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