New titlebar button style
[wmaker-crm.git] / src / framewin.c
blob17d607200bc81a07de93d592d616faf561b61559
1 /*
2 * Window Maker window manager
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 * USA.
22 #include "wconfig.h"
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 #ifdef KEEP_XKB_LOCK_STATUS
27 #include <X11/XKBlib.h>
28 #endif /* KEEP_XKB_LOCK_STATUS */
30 #include <stdlib.h>
31 #include <string.h>
33 #include <wraster.h>
35 #include "WindowMaker.h"
36 #include "GNUstep.h"
37 #include "texture.h"
38 #include "screen.h"
39 #include "wcore.h"
40 #include "framewin.h"
41 #include "stacking.h"
42 #include "funcs.h"
44 #define DBLCLICK_TIME wPreferences.dblclick_time
46 extern WPreferences wPreferences;
48 static void handleExpose(WObjDescriptor * desc, XEvent * event);
49 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event);
51 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event);
52 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event);
53 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event);
55 static void checkTitleSize(WFrameWindow * fwin);
57 static void paintButton(WCoreWindow * button, WTexture * texture,
58 unsigned long color, WPixmap * image, int pushed);
60 static void updateTitlebar(WFrameWindow * fwin);
62 WFrameWindow *wFrameWindowCreate(WScreen * scr, int wlevel, int x, int y,
63 int width, int height, int *clearance, int flags,
64 WTexture ** title_texture, WTexture ** resize_texture,
65 WMColor ** color, WMFont ** font)
67 WFrameWindow *fwin;
69 fwin = wmalloc(sizeof(WFrameWindow));
70 memset(fwin, 0, sizeof(WFrameWindow));
72 fwin->screen_ptr = scr;
74 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
76 fwin->title_texture = title_texture;
77 fwin->resizebar_texture = resize_texture;
78 fwin->title_color = color;
79 fwin->title_clearance = clearance;
80 fwin->font = font;
81 #ifdef KEEP_XKB_LOCK_STATUS
82 fwin->languagemode = XkbGroup1Index;
83 fwin->last_languagemode = XkbGroup2Index;
84 #endif
86 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height, (flags & WFF_BORDER)
87 ? FRAME_BORDER_WIDTH : 0);
88 if (wPreferences.use_saveunders) {
89 unsigned long vmask;
90 XSetWindowAttributes attribs;
92 vmask = CWSaveUnder;
93 attribs.save_under = True;
94 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
97 /* setup stacking information */
98 fwin->core->stacking = wmalloc(sizeof(WStacking));
99 fwin->core->stacking->above = NULL;
100 fwin->core->stacking->under = NULL;
101 fwin->core->stacking->child_of = NULL;
102 fwin->core->stacking->window_level = wlevel;
104 AddToStackList(fwin->core);
106 wFrameWindowUpdateBorders(fwin, flags);
108 return fwin;
111 void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
113 int theight;
114 int bsize;
115 int width, height;
116 int i;
117 WScreen *scr = fwin->screen_ptr;
119 width = fwin->core->width;
120 if (flags & WFF_IS_SHADED)
121 height = -1;
122 else
123 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
125 if (flags & WFF_TITLEBAR)
126 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
127 else
128 theight = 0;
130 if (wPreferences.new_style == TS_NEW) {
131 bsize = theight;
132 } else if (wPreferences.new_style == TS_OLD) {
133 bsize = theight - 7;
134 } else {
135 bsize = theight - 8;
138 if (fwin->titlebar) {
139 /* if we had a titlebar and is requesting for one,
140 * check if the size has changed and resize it */
141 if (flags & WFF_TITLEBAR) {
142 fwin->top_width = theight;
144 fwin->flags.need_texture_remake = 1;
146 if (wPreferences.new_style == TS_NEW) {
147 if (fwin->left_button) {
148 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
150 #ifdef XKB_BUTTON_HINT
151 if (fwin->language_button) {
152 if (fwin->flags.hide_left_button || !fwin->left_button
153 || fwin->flags.lbutton_dont_fit) {
154 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
155 } else {
156 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
159 #endif
161 if (fwin->right_button) {
162 wCoreConfigure(fwin->right_button, width - bsize + 1, 0, bsize, bsize);
164 } else { /* !new_style */
165 if (fwin->left_button) {
166 wCoreConfigure(fwin->left_button, 3, (theight - bsize) / 2, bsize, bsize);
168 #ifdef XKB_BUTTON_HINT
169 if (fwin->language_button) {
170 wCoreConfigure(fwin->language_button, 6 + bsize, (theight - bsize) / 2,
171 bsize, bsize);
173 #endif
175 if (fwin->right_button) {
176 wCoreConfigure(fwin->right_button, width - bsize - 3,
177 (theight - bsize) / 2, bsize, bsize);
180 updateTitlebar(fwin);
181 } else {
182 /* we had a titlebar, but now we don't need it anymore */
183 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
184 FREE_PIXMAP(fwin->title_back[i]);
185 if (wPreferences.new_style == TS_NEW) {
186 FREE_PIXMAP(fwin->lbutton_back[i]);
187 FREE_PIXMAP(fwin->rbutton_back[i]);
188 #ifdef XKB_BUTTON_HINT
189 FREE_PIXMAP(fwin->languagebutton_back[i]);
190 #endif
193 if (fwin->left_button)
194 wCoreDestroy(fwin->left_button);
195 fwin->left_button = NULL;
197 #ifdef XKB_BUTTON_HINT
198 if (fwin->language_button)
199 wCoreDestroy(fwin->language_button);
200 fwin->language_button = NULL;
201 #endif
203 if (fwin->right_button)
204 wCoreDestroy(fwin->right_button);
205 fwin->right_button = NULL;
207 wCoreDestroy(fwin->titlebar);
208 fwin->titlebar = NULL;
210 fwin->top_width = 0;
212 } else {
213 /* if we didn't have a titlebar and are being requested for
214 * one, create it */
215 if (flags & WFF_TITLEBAR) {
216 fwin->top_width = theight;
218 fwin->flags.titlebar = 1;
219 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width + 1, theight);
221 if (flags & WFF_LEFT_BUTTON) {
222 fwin->flags.left_button = 1;
223 if (wPreferences.new_style == TS_NEW) {
224 fwin->left_button = wCoreCreate(fwin->core, 0, 0, bsize, bsize);
225 if (width < theight * 4) {
226 fwin->flags.lbutton_dont_fit = 1;
227 } else {
228 XMapRaised(dpy, fwin->left_button->window);
230 } else if (wPreferences.new_style == TS_OLD) {
231 fwin->left_button =
232 wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
234 XSetWindowBackground(dpy, fwin->left_button->window,
235 scr->widget_texture->normal.pixel);
237 if (width < theight * 3) {
238 fwin->flags.lbutton_dont_fit = 1;
239 } else {
240 XMapRaised(dpy, fwin->left_button->window);
242 } else {
243 fwin->left_button =
244 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
245 bsize, bsize);
247 XSetWindowBackground(dpy, fwin->left_button->window,
248 scr->widget_texture->dark.pixel);
250 if (width < theight*3) {
251 fwin->flags.lbutton_dont_fit = 1;
252 } else {
253 XMapRaised(dpy, fwin->left_button->window);
257 #ifdef XKB_BUTTON_HINT
258 if (flags & WFF_LANGUAGE_BUTTON) {
259 fwin->flags.language_button = 1;
260 if (wPreferences.new_style == TS_NEW) {
261 fwin->language_button = wCoreCreate(fwin->core, bsize, 0, bsize, bsize);
263 if (width < theight * 4) {
264 fwin->flags.languagebutton_dont_fit = 1;
265 } else {
266 XMapRaised(dpy, fwin->language_button->window);
268 } else {
269 fwin->language_button =
270 wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
271 bsize, bsize);
273 XSetWindowBackground(dpy, fwin->language_button->window,
274 scr->widget_texture->normal.pixel);
276 if (width < theight * 3) {
277 fwin->flags.languagebutton_dont_fit = 1;
278 } else {
279 XMapRaised(dpy, fwin->language_button->window);
283 #endif
285 if (flags & WFF_RIGHT_BUTTON) {
286 fwin->flags.right_button = 1;
287 if (wPreferences.new_style == TS_NEW) {
288 fwin->right_button =
289 wCoreCreate(fwin->core, width - bsize + 1, 0, bsize, bsize);
290 } else if (wPreferences.new_style == TS_OLD) {
291 fwin->right_button =
292 wCoreCreate(fwin->titlebar, width - bsize - 3,
293 (theight - bsize) / 2, bsize, bsize);
294 XSetWindowBackground(dpy, fwin->right_button->window,
295 scr->widget_texture->normal.pixel);
296 } else {
297 fwin->right_button =
298 wCoreCreate(fwin->titlebar, width-bsize-3,
299 (theight-bsize)/2, bsize, bsize);
300 XSetWindowBackground(dpy, fwin->right_button->window,
301 scr->widget_texture->dark.pixel);
304 if (width < theight * 2) {
305 fwin->flags.rbutton_dont_fit = 1;
306 } else {
307 XMapRaised(dpy, fwin->right_button->window);
311 if (wPreferences.new_style == TS_NEW)
312 updateTitlebar(fwin);
314 XMapRaised(dpy, fwin->titlebar->window);
316 fwin->flags.need_texture_remake = 1;
319 checkTitleSize(fwin);
321 if (flags & WFF_RESIZEBAR) {
322 fwin->bottom_width = RESIZEBAR_HEIGHT;
324 if (!fwin->resizebar) {
325 fwin->flags.resizebar = 1;
326 fwin->resizebar = wCoreCreate(fwin->core, 0,
327 height + fwin->top_width, width, RESIZEBAR_HEIGHT);
328 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
329 if (width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
330 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH) / 2;
331 if (fwin->resizebar_corner_width < 0)
332 fwin->resizebar_corner_width = 0;
335 XMapWindow(dpy, fwin->resizebar->window);
336 XLowerWindow(dpy, fwin->resizebar->window);
338 fwin->flags.need_texture_remake = 1;
339 } else {
340 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height) {
341 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
342 width, RESIZEBAR_HEIGHT);
345 } else {
346 fwin->bottom_width = 0;
348 if (fwin->resizebar) {
349 fwin->bottom_width = 0;
350 wCoreDestroy(fwin->resizebar);
351 fwin->resizebar = NULL;
355 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED)) {
356 wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
359 if (flags & WFF_BORDER) {
360 XSetWindowBorderWidth(dpy, fwin->core->window, FRAME_BORDER_WIDTH);
361 } else {
362 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
365 /* setup object descriptors */
367 if (fwin->titlebar) {
368 fwin->titlebar->descriptor.handle_expose = handleExpose;
369 fwin->titlebar->descriptor.parent = fwin;
370 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
371 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
374 if (fwin->resizebar) {
375 fwin->resizebar->descriptor.handle_expose = handleExpose;
376 fwin->resizebar->descriptor.parent = fwin;
377 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
378 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
381 if (fwin->left_button) {
382 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
383 fwin->left_button->descriptor.parent = fwin;
384 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
385 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
387 #ifdef XKB_BUTTON_HINT
388 if (fwin->language_button) {
389 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
390 fwin->language_button->descriptor.parent = fwin;
391 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
392 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
394 #endif
396 if (fwin->right_button) {
397 fwin->right_button->descriptor.parent = fwin;
398 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
399 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
400 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
403 checkTitleSize(fwin);
406 void wFrameWindowDestroy(WFrameWindow * fwin)
408 int i;
410 if (fwin->left_button)
411 wCoreDestroy(fwin->left_button);
413 #ifdef XKB_BUTTON_HINT
414 if (fwin->language_button)
415 wCoreDestroy(fwin->language_button);
416 #endif
418 if (fwin->right_button)
419 wCoreDestroy(fwin->right_button);
421 if (fwin->resizebar)
422 wCoreDestroy(fwin->resizebar);
424 if (fwin->titlebar)
425 wCoreDestroy(fwin->titlebar);
427 RemoveFromStackList(fwin->core);
429 wCoreDestroy(fwin->core);
431 if (fwin->title)
432 wfree(fwin->title);
434 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
435 FREE_PIXMAP(fwin->title_back[i]);
436 if (wPreferences.new_style == TS_NEW) {
437 FREE_PIXMAP(fwin->lbutton_back[i]);
438 #ifdef XKB_BUTTON_HINT
439 FREE_PIXMAP(fwin->languagebutton_back[i]);
440 #endif
441 FREE_PIXMAP(fwin->rbutton_back[i]);
445 wfree(fwin);
448 void wFrameWindowChangeState(WFrameWindow * fwin, int state)
450 if (fwin->flags.state == state)
451 return;
453 fwin->flags.state = state;
454 fwin->flags.need_texture_change = 1;
456 wFrameWindowPaint(fwin);
459 static void updateTitlebar(WFrameWindow * fwin)
461 int x, w;
462 int theight;
464 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
466 x = 0;
467 w = fwin->core->width + 1;
469 if (wPreferences.new_style == TS_NEW) {
470 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
471 x = 0;
472 #ifdef XKB_BUTTON_HINT
473 if (fwin->language_button)
474 wCoreConfigure(fwin->language_button, 0, 0,
475 fwin->language_button->width, fwin->language_button->width);
476 #endif
477 } else {
478 #ifdef XKB_BUTTON_HINT
479 if (fwin->language_button)
480 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
481 fwin->language_button->width, fwin->language_button->width);
482 #endif
483 x = fwin->left_button->width;
484 w -= fwin->left_button->width;
486 #ifdef XKB_BUTTON_HINT
487 if (fwin->flags.hide_language_button || !fwin->language_button
488 || fwin->flags.languagebutton_dont_fit) {
489 } else {
490 x += fwin->language_button->width;
491 w -= fwin->language_button->width;
493 #endif
495 #ifdef XKB_BUTTON_HINT
496 else {
497 int bsize = theight - 7;
498 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
499 if (fwin->language_button)
500 wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
501 fwin->language_button->width, fwin->language_button->width);
502 } else {
503 if (fwin->language_button)
504 wCoreConfigure(fwin->language_button,
505 6 + fwin->left_button->width, (theight - bsize) / 2,
506 fwin->language_button->width, fwin->language_button->width);
509 #endif
511 if (wPreferences.new_style == TS_NEW) {
512 if (!fwin->flags.hide_right_button && fwin->right_button && !fwin->flags.rbutton_dont_fit) {
513 w -= fwin->right_button->width;
517 if (wPreferences.new_style == TS_NEW || fwin->titlebar->width != w)
518 fwin->flags.need_texture_remake = 1;
520 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
523 void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
525 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
526 XUnmapWindow(dpy, fwin->right_button->window);
527 fwin->flags.hide_right_button = 1;
530 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
531 XUnmapWindow(dpy, fwin->left_button->window);
532 fwin->flags.hide_left_button = 1;
534 #ifdef XKB_BUTTON_HINT
535 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
536 XUnmapWindow(dpy, fwin->language_button->window);
537 fwin->flags.hide_language_button = 1;
539 #endif
541 if (fwin->titlebar) {
542 if (wPreferences.new_style == TS_NEW) {
543 updateTitlebar(fwin);
544 } else {
545 #ifdef XKB_BUTTON_HINT
546 updateTitlebar(fwin);
547 #else
548 XClearWindow(dpy, fwin->titlebar->window);
549 wFrameWindowPaint(fwin);
550 #endif
552 checkTitleSize(fwin);
556 void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
558 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
560 if (!fwin->flags.rbutton_dont_fit)
561 XMapWindow(dpy, fwin->right_button->window);
563 fwin->flags.hide_right_button = 0;
565 #ifdef XKB_BUTTON_HINT
566 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
568 if (!fwin->flags.languagebutton_dont_fit)
569 XMapWindow(dpy, fwin->language_button->window);
571 fwin->flags.hide_language_button = 0;
573 #endif
575 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
577 if (!fwin->flags.lbutton_dont_fit)
578 XMapWindow(dpy, fwin->left_button->window);
580 fwin->flags.hide_left_button = 0;
583 if (fwin->titlebar) {
584 if (wPreferences.new_style == TS_NEW) {
585 updateTitlebar(fwin);
586 } else {
587 XClearWindow(dpy, fwin->titlebar->window);
588 wFrameWindowPaint(fwin);
590 checkTitleSize(fwin);
594 static void
595 #ifdef XKB_BUTTON_HINT
596 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
597 int bwidth, int bheight, int left, int language, int right,
598 Pixmap * title, Pixmap * lbutton, Pixmap * languagebutton, Pixmap * rbutton)
599 #else
600 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
601 int bwidth, int bheight, int left, int right, Pixmap * title, Pixmap * lbutton, Pixmap * rbutton)
602 #endif
604 RImage *img;
605 RImage *limg, *rimg, *mimg;
606 #ifdef XKB_BUTTON_HINT
607 RImage *timg;
608 #endif
609 int x, w;
611 *title = None;
612 *lbutton = None;
613 *rbutton = None;
614 #ifdef XKB_BUTTON_HINT
615 *languagebutton = None;
616 #endif
618 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
619 if (!img) {
620 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
621 return;
624 if (wPreferences.new_style == TS_NEW) {
625 if (left) {
626 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
627 } else
628 limg = NULL;
630 x = 0;
631 w = img->width;
633 #ifdef XKB_BUTTON_HINT
634 if (language) {
635 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
636 } else
637 timg = NULL;
638 #endif
640 if (limg) {
641 RBevelImage(limg, RBEV_RAISED2);
642 if (!RConvertImage(scr->rcontext, limg, lbutton)) {
643 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
645 x += limg->width;
646 w -= limg->width;
647 RReleaseImage(limg);
649 #ifdef XKB_BUTTON_HINT
650 if (timg) {
651 RBevelImage(timg, RBEV_RAISED2);
652 if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
653 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
655 x += timg->width;
656 w -= timg->width;
657 RReleaseImage(timg);
659 #endif
661 if (right) {
662 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
663 } else
664 rimg = NULL;
666 if (rimg) {
667 RBevelImage(rimg, RBEV_RAISED2);
668 if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
669 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
671 w -= rimg->width;
672 RReleaseImage(rimg);
675 if (w != width) {
676 mimg = RGetSubImage(img, x, 0, w, img->height);
677 RBevelImage(mimg, RBEV_RAISED2);
679 if (!RConvertImage(scr->rcontext, mimg, title)) {
680 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
682 RReleaseImage(mimg);
683 } else {
684 RBevelImage(img, RBEV_RAISED2);
686 if (!RConvertImage(scr->rcontext, img, title)) {
687 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
690 } else {
691 RBevelImage(img, RBEV_RAISED2);
693 if (!RConvertImage(scr->rcontext, img, title)) {
694 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
698 RReleaseImage(img);
701 static void
702 renderResizebarTexture(WScreen * scr, WTexture * texture, int width, int height, int cwidth, Pixmap * pmap)
704 RImage *img;
705 RColor light;
706 RColor dark;
708 *pmap = None;
710 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
711 if (!img) {
712 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
713 return;
716 light.alpha = 0;
717 light.red = light.green = light.blue = 80;
719 dark.alpha = 0;
720 dark.red = dark.green = dark.blue = 40;
722 ROperateLine(img, RSubtractOperation, 0, 0, width - 1, 0, &dark);
723 ROperateLine(img, RAddOperation, 0, 1, width - 1, 1, &light);
725 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height - 1, &dark);
726 ROperateLine(img, RAddOperation, cwidth + 1, 2, cwidth + 1, height - 1, &light);
728 if (width > 1)
729 ROperateLine(img, RSubtractOperation, width - cwidth - 2, 2,
730 width - cwidth - 2, height - 1, &dark);
731 ROperateLine(img, RAddOperation, width - cwidth - 1, 2, width - cwidth - 1, height - 1, &light);
733 #ifdef SHADOW_RESIZEBAR
734 ROperateLine(img, RAddOperation, 0, 1, 0, height - 1, &light);
735 ROperateLine(img, RSubtractOperation, width - 1, 1, width - 1, height - 1, &dark);
736 ROperateLine(img, RSubtractOperation, 0, height - 1, width - 1, height - 1, &dark);
737 #endif /* SHADOW_RESIZEBAR */
739 if (!RConvertImage(scr->rcontext, img, pmap)) {
740 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
743 RReleaseImage(img);
746 static void updateTexture(WFrameWindow * fwin)
748 int i;
749 unsigned long pixel;
751 i = fwin->flags.state;
752 if (fwin->titlebar) {
753 if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
754 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window, fwin->title_back[i]);
755 if (wPreferences.new_style == TS_NEW) {
756 if (fwin->left_button && fwin->lbutton_back[i])
757 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
758 fwin->lbutton_back[i]);
760 #ifdef XKB_BUTTON_HINT
761 if (fwin->language_button && fwin->languagebutton_back[i]) {
762 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
763 fwin->languagebutton_back[i]);
765 #endif
767 if (fwin->right_button && fwin->rbutton_back[i])
768 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
769 fwin->rbutton_back[i]);
771 } else {
772 pixel = fwin->title_texture[i]->solid.normal.pixel;
773 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
774 if (wPreferences.new_style == TS_NEW) {
775 if (fwin->left_button)
776 XSetWindowBackground(dpy, fwin->left_button->window, pixel);
777 #ifdef XKB_BUTTON_HINT
778 if (fwin->language_button)
779 XSetWindowBackground(dpy, fwin->language_button->window, pixel);
780 #endif
781 if (fwin->right_button)
782 XSetWindowBackground(dpy, fwin->right_button->window, pixel);
785 XClearWindow(dpy, fwin->titlebar->window);
787 if (fwin->left_button) {
788 XClearWindow(dpy, fwin->left_button->window);
789 handleButtonExpose(&fwin->left_button->descriptor, NULL);
791 #ifdef XKB_BUTTON_HINT
792 if (fwin->language_button) {
793 XClearWindow(dpy, fwin->language_button->window);
794 handleButtonExpose(&fwin->language_button->descriptor, NULL);
796 #endif
797 if (fwin->right_button) {
798 XClearWindow(dpy, fwin->right_button->window);
799 handleButtonExpose(&fwin->right_button->descriptor, NULL);
804 static void remakeTexture(WFrameWindow * fwin, int state)
806 Pixmap pmap, lpmap, rpmap;
807 #ifdef XKB_BUTTON_HINT
808 Pixmap tpmap;
809 #endif
811 if (fwin->title_texture[state] && fwin->titlebar) {
812 FREE_PIXMAP(fwin->title_back[state]);
813 if (wPreferences.new_style == TS_NEW) {
814 FREE_PIXMAP(fwin->lbutton_back[state]);
815 FREE_PIXMAP(fwin->rbutton_back[state]);
816 #ifdef XKB_BUTTON_HINT
817 FREE_PIXMAP(fwin->languagebutton_back[state]);
818 #endif
821 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
822 int left, right;
823 int width;
824 #ifdef XKB_BUTTON_HINT
825 int language;
826 #endif
828 /* eventually surrounded by if new_style */
829 left = fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit;
830 #ifdef XKB_BUTTON_HINT
831 language = fwin->language_button && !fwin->flags.hide_language_button
832 && !fwin->flags.languagebutton_dont_fit;
833 #endif
834 right = fwin->right_button && !fwin->flags.hide_right_button
835 && !fwin->flags.rbutton_dont_fit;
837 width = fwin->core->width + 1;
839 #ifdef XKB_BUTTON_HINT
840 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
841 width, fwin->titlebar->height,
842 fwin->titlebar->height, fwin->titlebar->height,
843 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
844 #else
845 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
846 width, fwin->titlebar->height,
847 fwin->titlebar->height, fwin->titlebar->height,
848 left, right, &pmap, &lpmap, &rpmap);
849 #endif
851 fwin->title_back[state] = pmap;
852 if (wPreferences.new_style == TS_NEW) {
853 fwin->lbutton_back[state] = lpmap;
854 fwin->rbutton_back[state] = rpmap;
855 #ifdef XKB_BUTTON_HINT
856 fwin->languagebutton_back[state] = tpmap;
857 #endif
861 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
862 && fwin->resizebar && state == 0) {
864 FREE_PIXMAP(fwin->resizebar_back[0]);
866 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
868 renderResizebarTexture(fwin->screen_ptr,
869 fwin->resizebar_texture[0],
870 fwin->resizebar->width,
871 fwin->resizebar->height, fwin->resizebar_corner_width, &pmap);
873 fwin->resizebar_back[0] = pmap;
876 /* this part should be in updateTexture() */
877 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
878 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
879 } else {
880 XSetWindowBackground(dpy, fwin->resizebar->window,
881 fwin->resizebar_texture[0]->solid.normal.pixel);
883 XClearWindow(dpy, fwin->resizebar->window);
887 void wFrameWindowPaint(WFrameWindow * fwin)
889 WScreen *scr = fwin->screen_ptr;
890 int state;
892 state = fwin->flags.state;
894 if (fwin->flags.is_client_window_frame)
895 fwin->flags.justification = wPreferences.title_justification;
897 if (fwin->flags.need_texture_remake) {
898 int i;
900 fwin->flags.need_texture_remake = 0;
901 fwin->flags.need_texture_change = 0;
903 if (fwin->flags.single_texture) {
904 remakeTexture(fwin, 0);
905 updateTexture(fwin);
906 } else {
907 /* first render the texture for the current state... */
908 remakeTexture(fwin, state);
909 /* ... and paint it */
910 updateTexture(fwin);
912 for (i = 0; i < 3; i++) {
913 if (i != state) {
914 remakeTexture(fwin, i);
920 if (fwin->flags.need_texture_change) {
921 fwin->flags.need_texture_change = 0;
923 updateTexture(fwin);
926 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
927 && fwin->title_texture[state]->any.type == WTEX_SOLID) {
928 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
929 fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
932 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
933 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
934 Window win;
935 int w, h;
936 int cw;
937 GC light_gc, dim_gc;
938 WTexSolid *texture = (WTexSolid *) fwin->resizebar_texture[0];
940 w = fwin->resizebar->width;
941 h = fwin->resizebar->height;
942 cw = fwin->resizebar_corner_width;
943 light_gc = texture->light_gc;
944 dim_gc = texture->dim_gc;
945 win = fwin->resizebar->window;
947 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
948 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
950 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
951 XDrawLine(dpy, win, light_gc, cw + 1, 2, cw + 1, h);
953 XDrawLine(dpy, win, dim_gc, w - cw - 2, 2, w - cw - 2, h);
954 XDrawLine(dpy, win, light_gc, w - cw - 1, 2, w - cw - 1, h);
956 #ifdef SHADOW_RESIZEBAR
957 XDrawLine(dpy, win, light_gc, 0, 1, 0, h - 1);
958 XDrawLine(dpy, win, dim_gc, w - 1, 2, w - 1, h - 1);
959 XDrawLine(dpy, win, dim_gc, 1, h - 1, cw, h - 1);
960 XDrawLine(dpy, win, dim_gc, cw + 2, h - 1, w - cw - 2, h - 1);
961 XDrawLine(dpy, win, dim_gc, w - cw, h - 1, w - 1, h - 1);
962 #endif /* SHADOW_RESIZEBAR */
965 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
966 int x, y, w, h;
967 int lofs = 6, rofs = 6;
968 int titlelen;
969 int allButtons = 1;
971 if (!wPreferences.new_style == TS_NEW) {
972 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
973 lofs += fwin->left_button->width + 3;
974 else
975 allButtons = 0;
977 #ifdef XKB_BUTTON_HINT
978 if (fwin->language_button && !fwin->flags.hide_language_button
979 && !fwin->flags.languagebutton_dont_fit)
980 lofs += fwin->language_button->width;
981 else
982 allButtons = 0;
983 #endif
985 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
986 rofs += fwin->right_button->width + 3;
987 else
988 allButtons = 0;
990 #ifdef XKB_BUTTON_HINT
991 fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
992 #endif
994 if (fwin->title) {
995 Drawable buf;
996 char *title;
998 title = ShrinkString(*fwin->font, fwin->title, fwin->titlebar->width - lofs - rofs);
999 titlelen = strlen(title);
1000 w = WMWidthOfString(*fwin->font, title, titlelen);
1002 switch (fwin->flags.justification) {
1003 case WTJ_LEFT:
1004 x = lofs;
1005 break;
1007 case WTJ_RIGHT:
1008 x = fwin->titlebar->width - w - rofs;
1009 break;
1011 default:
1012 if (!allButtons)
1013 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1014 else
1015 x = (fwin->titlebar->width - w) / 2;
1016 break;
1019 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1020 h = WMFontHeight(*fwin->font);
1022 /* We use a w+2 buffer to have an extra pixel on the left and
1023 * another one on the right. This is because for some odd reason,
1024 * sometimes when using AA fonts (when libfreetype2 is compiled
1025 * with bytecode interpreter turned off), some fonts are drawn
1026 * starting from x = -1 not from 0 as requested. Observed with
1027 * capital A letter on the bold 'trebuchet ms' font. -Dan
1029 buf = XCreatePixmap(dpy, fwin->titlebar->window, w + 2, h, scr->w_depth);
1031 XSetClipMask(dpy, scr->copy_gc, None);
1033 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
1034 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1035 x - 1, y, w + 2, h, 0, 0);
1036 } else {
1037 XSetForeground(dpy, scr->copy_gc, fwin->title_texture[state]->solid.normal.pixel);
1038 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w + 2, h);
1041 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1); */
1042 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1043 *fwin->font, 1, 0, title, titlelen);
1045 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc, 0, 0, w + 2, h, x - 1, y);
1047 XFreePixmap(dpy, buf);
1049 wfree(title);
1052 if (fwin->left_button)
1053 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1054 if (fwin->right_button)
1055 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1056 #ifdef XKB_BUTTON_HINT
1057 if (fwin->language_button)
1058 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1059 #endif
1063 static void reconfigure(WFrameWindow * fwin, int x, int y, int width, int height, Bool dontMove)
1065 int k = (wPreferences.new_style == TS_NEW ? 4 : 3);
1066 int resizedHorizontally = 0;
1068 if (dontMove)
1069 XResizeWindow(dpy, fwin->core->window, width, height);
1070 else
1071 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1074 if (fwin->core->height != height && fwin->resizebar)
1075 XMoveWindow(dpy, fwin->resizebar->window, 0,
1076 height - fwin->resizebar->height);
1078 if (fwin->core->width != width) {
1079 fwin->flags.need_texture_remake = 1;
1080 resizedHorizontally = 1;
1083 fwin->core->width = width;
1084 fwin->core->height = height;
1086 if (fwin->titlebar && resizedHorizontally) {
1087 /* Check if the titlebar is wide enough to hold the buttons.
1088 * Temporarily remove them if can't
1090 if (fwin->left_button) {
1091 if (width < fwin->top_width * k && !fwin->flags.lbutton_dont_fit) {
1093 if (!fwin->flags.hide_left_button) {
1094 XUnmapWindow(dpy, fwin->left_button->window);
1096 fwin->flags.lbutton_dont_fit = 1;
1097 } else if (width >= fwin->top_width * k && fwin->flags.lbutton_dont_fit) {
1099 if (!fwin->flags.hide_left_button) {
1100 XMapWindow(dpy, fwin->left_button->window);
1102 fwin->flags.lbutton_dont_fit = 0;
1105 #ifdef XKB_BUTTON_HINT
1106 if (fwin->language_button) {
1107 if (width < fwin->top_width * k && !fwin->flags.languagebutton_dont_fit) {
1109 if (!fwin->flags.hide_language_button) {
1110 XUnmapWindow(dpy, fwin->language_button->window);
1112 fwin->flags.languagebutton_dont_fit = 1;
1113 } else if (width >= fwin->top_width * k && fwin->flags.languagebutton_dont_fit) {
1115 if (!fwin->flags.hide_language_button) {
1116 XMapWindow(dpy, fwin->language_button->window);
1118 fwin->flags.languagebutton_dont_fit = 0;
1121 #endif
1123 if (fwin->right_button) {
1124 if (width < fwin->top_width * 2 && !fwin->flags.rbutton_dont_fit) {
1126 if (!fwin->flags.hide_right_button) {
1127 XUnmapWindow(dpy, fwin->right_button->window);
1129 fwin->flags.rbutton_dont_fit = 1;
1130 } else if (width >= fwin->top_width * 2 && fwin->flags.rbutton_dont_fit) {
1132 if (!fwin->flags.hide_right_button) {
1133 XMapWindow(dpy, fwin->right_button->window);
1135 fwin->flags.rbutton_dont_fit = 0;
1139 if (wPreferences.new_style == TS_NEW) {
1140 if (fwin->right_button)
1141 XMoveWindow(dpy, fwin->right_button->window,
1142 width - fwin->right_button->width + 1, 0);
1143 } else {
1144 if (fwin->right_button)
1145 XMoveWindow(dpy, fwin->right_button->window,
1146 width - fwin->right_button->width - 3,
1147 (fwin->titlebar->height - fwin->right_button->height) / 2);
1149 updateTitlebar(fwin);
1150 checkTitleSize(fwin);
1153 if (fwin->resizebar) {
1154 wCoreConfigure(fwin->resizebar, 0,
1155 fwin->core->height - fwin->resizebar->height,
1156 fwin->core->width, fwin->resizebar->height);
1158 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1159 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
1160 fwin->resizebar_corner_width = fwin->core->width / 2;
1165 void wFrameWindowConfigure(WFrameWindow * fwin, int x, int y, int width, int height)
1167 reconfigure(fwin, x, y, width, height, False);
1170 void wFrameWindowResize(WFrameWindow * fwin, int width, int height)
1172 reconfigure(fwin, 0, 0, width, height, True);
1175 int wFrameWindowChangeTitle(WFrameWindow * fwin, char *new_title)
1177 /* check if the title is the same as before */
1178 if (fwin->title) {
1179 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1180 return 0;
1182 } else {
1183 if (!new_title)
1184 return 0;
1187 if (fwin->title)
1188 wfree(fwin->title);
1190 fwin->title = wstrdup(new_title);
1192 if (fwin->titlebar) {
1193 XClearWindow(dpy, fwin->titlebar->window);
1195 wFrameWindowPaint(fwin);
1197 checkTitleSize(fwin);
1199 return 1;
1202 #ifdef XKB_BUTTON_HINT
1203 void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
1205 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1206 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
1208 #endif /* XKB_BUTTON_HINT */
1210 /*********************************************************************/
1212 static void handleExpose(WObjDescriptor * desc, XEvent * event)
1214 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1216 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1217 fwin->flags.repaint_only_titlebar = 1;
1218 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1219 fwin->flags.repaint_only_resizebar = 1;
1220 wFrameWindowPaint(fwin);
1221 fwin->flags.repaint_only_titlebar = 0;
1222 fwin->flags.repaint_only_resizebar = 0;
1225 static void checkTitleSize(WFrameWindow * fwin)
1227 int width;
1229 if (!fwin->title) {
1230 fwin->flags.incomplete_title = 0;
1231 return;
1234 if (!fwin->titlebar) {
1235 fwin->flags.incomplete_title = 1;
1236 return;
1237 } else {
1238 width = fwin->titlebar->width - 6 - 6;
1241 if (!wPreferences.new_style == TS_NEW) {
1242 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1243 width -= fwin->left_button->width + 3;
1245 #ifdef XKB_BUTTON_HINT
1246 if (fwin->language_button && !fwin->flags.hide_language_button
1247 && !fwin->flags.languagebutton_dont_fit)
1248 width -= fwin->language_button->width + 3;
1249 #endif
1251 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1252 width -= fwin->right_button->width + 3;
1254 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1255 fwin->flags.incomplete_title = 1;
1256 } else {
1257 fwin->flags.incomplete_title = 0;
1261 static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
1263 WScreen *scr = button->screen_ptr;
1264 GC copy_gc = scr->copy_gc;
1265 int x = 0, y = 0, d = 0;
1266 int left = 0, width = 0;
1268 /* setup stuff according to the state */
1269 if (pushed) {
1270 if (image) {
1271 if (image->width >= image->height * 2) {
1272 /* the image contains 2 pictures: the second is for the
1273 * pushed state */
1274 width = image->width / 2;
1275 left = image->width / 2;
1276 } else {
1277 width = image->width;
1280 XSetClipMask(dpy, copy_gc, None);
1281 if (wPreferences.new_style == TS_NEXT) {
1282 XSetForeground(dpy, copy_gc, scr->black_pixel);
1283 } else {
1284 XSetForeground(dpy, copy_gc, scr->white_pixel);
1286 d = 1;
1287 if (wPreferences.new_style == TS_NEW) {
1288 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1289 XSetForeground(dpy, copy_gc, scr->black_pixel);
1290 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1291 } else if (wPreferences.new_style == TS_OLD) {
1292 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1293 XSetForeground(dpy, copy_gc, scr->black_pixel);
1294 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1295 } else {
1296 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1297 XSetForeground(dpy, copy_gc, scr->black_pixel);
1298 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1300 } else {
1301 XClearWindow(dpy, button->window);
1303 if (image) {
1304 if (image->width >= image->height * 2)
1305 width = image->width / 2;
1306 else
1307 width = image->width;
1309 d = 0;
1311 if (wPreferences.new_style == TS_NEW) {
1312 if (texture->any.type == WTEX_SOLID || pushed) {
1313 wDrawBevel(button->window, button->width, button->height,
1314 (WTexSolid *) texture, WREL_RAISED);
1316 } else {
1317 wDrawBevel(button->window, button->width, button->height,
1318 scr->widget_texture, WREL_RAISED);
1322 if (image) {
1323 /* display image */
1324 XSetClipMask(dpy, copy_gc, image->mask);
1325 x = (button->width - width) / 2 + d;
1326 y = (button->height - image->height) / 2 + d;
1327 XSetClipOrigin(dpy, copy_gc, x - left, y);
1328 if (!wPreferences.new_style == TS_NEW) {
1329 XSetForeground(dpy, copy_gc, scr->black_pixel);
1330 if (!pushed) {
1331 if (image->depth == 1)
1332 XCopyPlane(dpy, image->image, button->window, copy_gc,
1333 left, 0, width, image->height, x, y, 1);
1334 else
1335 XCopyArea(dpy, image->image, button->window, copy_gc,
1336 left, 0, width, image->height, x, y);
1337 } else {
1338 if (wPreferences.new_style == TS_OLD) {
1339 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1340 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1341 button->width, button->height);
1342 } else {
1343 XSetForeground(dpy, copy_gc, scr->black_pixel);
1344 XCopyArea(dpy, image->image, button->window, copy_gc,
1345 left, 0, width, image->height, x, y);
1348 } else {
1349 if (pushed) {
1350 XSetForeground(dpy, copy_gc, scr->black_pixel);
1351 } else {
1352 XSetForeground(dpy, copy_gc, color);
1353 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1355 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1360 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
1362 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1363 WCoreWindow *button = (WCoreWindow *) desc->self;
1365 #ifdef XKB_BUTTON_HINT
1366 if (button == fwin->language_button) {
1367 if (wPreferences.modelock) {
1368 paintButton(button, fwin->title_texture[fwin->flags.state],
1369 WMColorPixel(fwin->title_color[fwin->flags.state]),
1370 fwin->languagebutton_image, False);
1372 } else
1373 #endif
1374 if (button == fwin->left_button) {
1375 paintButton(button, fwin->title_texture[fwin->flags.state],
1376 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
1377 } else {
1378 paintButton(button, fwin->title_texture[fwin->flags.state],
1379 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
1383 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
1385 WFrameWindow *fwin = desc->parent;
1386 WCoreWindow *titlebar = desc->self;
1388 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1389 if (fwin->on_dblclick_titlebar) {
1390 (*fwin->on_dblclick_titlebar) (titlebar, fwin->child, event);
1392 } else {
1393 if (fwin->on_mousedown_titlebar) {
1394 (*fwin->on_mousedown_titlebar) (titlebar, fwin->child, event);
1399 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event)
1401 WFrameWindow *fwin = desc->parent;
1402 WCoreWindow *resizebar = desc->self;
1404 if (fwin->on_mousedown_resizebar)
1405 (*fwin->on_mousedown_resizebar) (resizebar, fwin->child, event);
1408 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
1410 WFrameWindow *fwin = desc->parent;
1411 WCoreWindow *button = desc->self;
1412 WPixmap *image;
1413 XEvent ev;
1414 int done = 0, execute = 1;
1415 WTexture *texture;
1416 unsigned long pixel;
1417 int clickButton = event->xbutton.button;
1419 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1420 if (button == fwin->right_button && fwin->on_dblclick_right) {
1421 (*fwin->on_dblclick_right) (button, fwin->child, event);
1423 return;
1426 if (button == fwin->left_button) {
1427 image = fwin->lbutton_image;
1428 } else {
1429 image = fwin->rbutton_image;
1431 #ifdef XKB_BUTTON_HINT
1432 if (button == fwin->language_button) {
1433 if (!wPreferences.modelock)
1434 return;
1435 image = fwin->languagebutton_image;
1437 #endif
1439 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1440 texture = fwin->title_texture[fwin->flags.state];
1441 paintButton(button, texture, pixel, image, True);
1443 while (!done) {
1444 WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
1445 | ButtonPressMask | ExposureMask, &ev);
1446 switch (ev.type) {
1447 case LeaveNotify:
1448 execute = 0;
1449 paintButton(button, texture, pixel, image, False);
1450 break;
1452 case EnterNotify:
1453 execute = 1;
1454 paintButton(button, texture, pixel, image, True);
1455 break;
1457 case ButtonPress:
1458 break;
1460 case ButtonRelease:
1461 if (ev.xbutton.button == clickButton)
1462 done = 1;
1463 break;
1465 default:
1466 WMHandleEvent(&ev);
1469 paintButton(button, texture, pixel, image, False);
1471 if (execute) {
1472 if (button == fwin->left_button) {
1473 if (fwin->on_click_left)
1474 (*fwin->on_click_left) (button, fwin->child, &ev);
1475 } else if (button == fwin->right_button) {
1476 if (fwin->on_click_right)
1477 (*fwin->on_click_right) (button, fwin->child, &ev);
1479 #ifdef XKB_BUTTON_HINT
1480 else if (button == fwin->language_button) {
1481 if (fwin->on_click_language)
1482 (*fwin->on_click_language) (button, fwin->child, &ev);
1484 #endif