- Fixed an issue with drawing AA fonts in titlebars
[wmaker-crm.git] / src / framewin.c
blob349bdada11836a9f7c40e9b7be5e08bab10e5454
1 /*
2 * Window Maker window manager
3 *
4 * Copyright (c) 1997-2002 Alfredo K. Kojima
5 *
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 <WINGs/WINGsP.h>
37 #include "WindowMaker.h"
38 #include "GNUstep.h"
39 #include "texture.h"
40 #include "screen.h"
41 #include "wcore.h"
42 #include "framewin.h"
43 #include "stacking.h"
44 #include "funcs.h"
46 #define DBLCLICK_TIME wPreferences.dblclick_time
48 extern WPreferences wPreferences;
50 static void handleExpose(WObjDescriptor *desc, XEvent *event);
51 static void handleButtonExpose(WObjDescriptor *desc, XEvent *event);
53 static void buttonMouseDown(WObjDescriptor *desc, XEvent *event);
54 static void titlebarMouseDown(WObjDescriptor *desc, XEvent *event);
55 static void resizebarMouseDown(WObjDescriptor *desc, XEvent *event);
57 static void checkTitleSize(WFrameWindow *fwin);
60 static void paintButton(WCoreWindow *button, WTexture *texture,
61 unsigned long color, WPixmap *image, int pushed);
63 static void updateTitlebar(WFrameWindow *fwin);
66 WFrameWindow*
67 wFrameWindowCreate(WScreen *scr, int wlevel, int x, int y,
68 int width, int height, int *clearance, int flags,
69 WTexture **title_texture, WTexture **resize_texture,
70 WMColor **color, WMFont **font)
72 WFrameWindow *fwin;
74 fwin = wmalloc(sizeof(WFrameWindow));
75 memset(fwin, 0, sizeof(WFrameWindow));
77 fwin->screen_ptr = scr;
79 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
81 fwin->title_texture = title_texture;
82 fwin->resizebar_texture = resize_texture;
83 fwin->title_color = color;
84 fwin->title_clearance = clearance;
85 fwin->font = font;
86 #ifdef KEEP_XKB_LOCK_STATUS
87 fwin->languagemode = XkbGroup1Index;
88 fwin->last_languagemode = XkbGroup2Index;
89 #endif
91 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height,
92 (flags & WFF_BORDER)
93 ? FRAME_BORDER_WIDTH : 0);
94 if (wPreferences.use_saveunders) {
95 unsigned long vmask;
96 XSetWindowAttributes attribs;
98 vmask = CWSaveUnder;
99 attribs.save_under = True;
100 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
103 /* setup stacking information */
104 fwin->core->stacking = wmalloc(sizeof(WStacking));
105 fwin->core->stacking->above = NULL;
106 fwin->core->stacking->under = NULL;
107 fwin->core->stacking->child_of = NULL;
108 fwin->core->stacking->window_level = wlevel;
110 AddToStackList(fwin->core);
112 wFrameWindowUpdateBorders(fwin, flags);
114 return fwin;
119 void
120 wFrameWindowUpdateBorders(WFrameWindow *fwin, int flags)
122 int theight;
123 int bsize;
124 int width, height;
125 int i;
126 WScreen *scr = fwin->screen_ptr;
128 width = fwin->core->width;
129 if (flags & WFF_IS_SHADED)
130 height = -1;
131 else
132 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
134 if (flags & WFF_TITLEBAR)
135 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
136 else
137 theight = 0;
139 if (wPreferences.new_style) {
140 bsize = theight;
141 } else {
142 bsize = theight - 7;
145 if (fwin->titlebar) {
146 /* if we had a titlebar and is requesting for one,
147 * check if the size has changed and resize it */
148 if (flags & WFF_TITLEBAR) {
149 fwin->top_width = theight;
151 fwin->flags.need_texture_remake = 1;
153 if (wPreferences.new_style) {
154 if (fwin->left_button) {
155 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
157 #ifdef XKB_BUTTON_HINT
158 if (fwin->language_button)
159 if (fwin->flags.hide_left_button || !fwin->left_button
160 || fwin->flags.lbutton_dont_fit) {
161 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
162 } else {
163 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
165 #endif
168 if (fwin->right_button) {
169 wCoreConfigure(fwin->right_button, width-bsize+1,
170 0, bsize, bsize);
172 } else { /* !new_style */
173 if (fwin->left_button) {
174 wCoreConfigure(fwin->left_button, 3, (theight-bsize)/2,
175 bsize, bsize);
178 #ifdef XKB_BUTTON_HINT
179 if (fwin->language_button) {
180 wCoreConfigure(fwin->language_button, 6 + bsize, (theight-bsize)/2,
181 bsize, bsize);
183 #endif
185 if (fwin->right_button) {
186 wCoreConfigure(fwin->right_button, width-bsize-3,
187 (theight-bsize)/2, bsize, bsize);
190 updateTitlebar(fwin);
191 } else {
192 /* we had a titlebar, but now we don't need it anymore */
193 for (i=0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
194 FREE_PIXMAP(fwin->title_back[i]);
195 if (wPreferences.new_style) {
196 FREE_PIXMAP(fwin->lbutton_back[i]);
197 FREE_PIXMAP(fwin->rbutton_back[i]);
198 #ifdef XKB_BUTTON_HINT
199 FREE_PIXMAP(fwin->languagebutton_back[i]);
200 #endif
203 if (fwin->left_button)
204 wCoreDestroy(fwin->left_button);
205 fwin->left_button = NULL;
207 #ifdef XKB_BUTTON_HINT
208 if (fwin->language_button)
209 wCoreDestroy(fwin->language_button);
210 fwin->language_button = NULL;
211 #endif
213 if (fwin->right_button)
214 wCoreDestroy(fwin->right_button);
215 fwin->right_button = NULL;
217 wCoreDestroy(fwin->titlebar);
218 fwin->titlebar = NULL;
220 fwin->top_width = 0;
222 } else {
223 /* if we didn't have a titlebar and are being requested for
224 * one, create it */
225 if (flags & WFF_TITLEBAR) {
226 fwin->top_width = theight;
228 fwin->flags.titlebar = 1;
229 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width+1, theight);
231 if (flags & WFF_LEFT_BUTTON) {
232 fwin->flags.left_button = 1;
233 if (wPreferences.new_style) {
234 fwin->left_button = wCoreCreate(fwin->core, 0, 0,
235 bsize, bsize);
236 if (width < theight*4) {
237 fwin->flags.lbutton_dont_fit = 1;
238 } else {
239 XMapRaised(dpy, fwin->left_button->window);
241 } else {
242 fwin->left_button =
243 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
244 bsize, bsize);
246 XSetWindowBackground(dpy, fwin->left_button->window,
247 scr->widget_texture->normal.pixel);
249 if (width < theight*3) {
250 fwin->flags.lbutton_dont_fit = 1;
251 } else {
252 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) {
261 fwin->language_button = wCoreCreate(fwin->core,
262 bsize, 0, bsize, bsize);
264 if (width < theight*4) {
265 fwin->flags.languagebutton_dont_fit = 1;
266 } else {
267 XMapRaised(dpy, fwin->language_button->window);
269 } else {
270 fwin->language_button =
271 wCoreCreate(fwin->titlebar, bsize + 6, (theight-bsize)/2,
272 bsize, bsize);
274 XSetWindowBackground(dpy, fwin->language_button->window,
275 scr->widget_texture->normal.pixel);
277 if (width < theight*3) {
278 fwin->flags.languagebutton_dont_fit = 1;
279 } else {
280 XMapRaised(dpy, fwin->language_button->window);
284 #endif
286 if (flags & WFF_RIGHT_BUTTON) {
287 fwin->flags.right_button = 1;
288 if (wPreferences.new_style) {
289 fwin->right_button =
290 wCoreCreate(fwin->core, width-bsize+1, 0,
291 bsize, bsize);
292 } else {
293 fwin->right_button =
294 wCoreCreate(fwin->titlebar, width-bsize-3,
295 (theight-bsize)/2, bsize, bsize);
296 XSetWindowBackground(dpy, fwin->right_button->window,
297 scr->widget_texture->normal.pixel);
300 if (width < theight*2) {
301 fwin->flags.rbutton_dont_fit = 1;
302 } else {
303 XMapRaised(dpy, fwin->right_button->window);
307 if (wPreferences.new_style)
308 updateTitlebar(fwin);
310 XMapRaised(dpy, fwin->titlebar->window);
312 fwin->flags.need_texture_remake = 1;
315 checkTitleSize(fwin);
317 if (flags & WFF_RESIZEBAR) {
318 fwin->bottom_width = RESIZEBAR_HEIGHT;
320 if (!fwin->resizebar) {
321 fwin->flags.resizebar = 1;
322 fwin->resizebar = wCoreCreate(fwin->core, 0,
323 height + fwin->top_width,
324 width, RESIZEBAR_HEIGHT);
325 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
326 if (width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
327 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH)/2;
328 if (fwin->resizebar_corner_width < 0)
329 fwin->resizebar_corner_width = 0;
332 XMapWindow(dpy, fwin->resizebar->window);
333 XLowerWindow(dpy, fwin->resizebar->window);
335 fwin->flags.need_texture_remake = 1;
336 } else {
337 if (height+fwin->top_width+fwin->bottom_width != fwin->core->height) {
338 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
339 width, RESIZEBAR_HEIGHT);
342 } else {
343 fwin->bottom_width = 0;
345 if (fwin->resizebar) {
346 fwin->bottom_width = 0;
347 wCoreDestroy(fwin->resizebar);
348 fwin->resizebar = NULL;
352 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height
353 && !(flags & WFF_IS_SHADED)) {
354 wFrameWindowResize(fwin, width,
355 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;
388 #ifdef XKB_BUTTON_HINT
389 if (fwin->language_button) {
390 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
391 fwin->language_button->descriptor.parent = fwin;
392 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
393 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
395 #endif
398 if (fwin->right_button) {
399 fwin->right_button->descriptor.parent = fwin;
400 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
401 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
402 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
405 checkTitleSize(fwin);
410 void
411 wFrameWindowDestroy(WFrameWindow *fwin)
413 int i;
415 if (fwin->left_button)
416 wCoreDestroy(fwin->left_button);
418 #ifdef XKB_BUTTON_HINT
419 if (fwin->language_button)
420 wCoreDestroy(fwin->language_button);
421 #endif
423 if (fwin->right_button)
424 wCoreDestroy(fwin->right_button);
426 if (fwin->resizebar)
427 wCoreDestroy(fwin->resizebar);
429 if (fwin->titlebar)
430 wCoreDestroy(fwin->titlebar);
432 RemoveFromStackList(fwin->core);
434 wCoreDestroy(fwin->core);
436 if (fwin->title)
437 wfree(fwin->title);
439 for (i=0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
440 FREE_PIXMAP(fwin->title_back[i]);
441 if (wPreferences.new_style) {
442 FREE_PIXMAP(fwin->lbutton_back[i]);
443 #ifdef XKB_BUTTON_HINT
444 FREE_PIXMAP(fwin->languagebutton_back[i]);
445 #endif
446 FREE_PIXMAP(fwin->rbutton_back[i]);
450 wfree(fwin);
454 void
455 wFrameWindowChangeState(WFrameWindow *fwin, int state)
457 if (fwin->flags.state==state)
458 return;
460 fwin->flags.state = state;
461 fwin->flags.need_texture_change = 1;
463 wFrameWindowPaint(fwin);
467 static void
468 updateTitlebar(WFrameWindow *fwin)
470 int x, w;
471 int theight;
473 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
475 x = 0;
476 w = fwin->core->width + 1;
478 if (wPreferences.new_style) {
479 if (fwin->flags.hide_left_button || !fwin->left_button
480 || fwin->flags.lbutton_dont_fit) {
481 x = 0;
482 #ifdef XKB_BUTTON_HINT
483 if(fwin->language_button)
484 wCoreConfigure(fwin->language_button, 0, 0,
485 fwin->language_button->width,
486 fwin->language_button->width);
487 #endif
488 } else {
489 #ifdef XKB_BUTTON_HINT
490 if(fwin->language_button)
491 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
492 fwin->language_button->width,
493 fwin->language_button->width);
494 #endif
495 x = fwin->left_button->width;
496 w -= fwin->left_button->width;
498 #ifdef XKB_BUTTON_HINT
499 if (fwin->flags.hide_language_button || !fwin->language_button
500 || fwin->flags.languagebutton_dont_fit) {
501 } else {
502 x += fwin->language_button->width;
503 w -= fwin->language_button->width;
505 #endif
507 #ifdef XKB_BUTTON_HINT
508 else {
509 int bsize = theight - 7;
510 if (fwin->flags.hide_left_button || !fwin->left_button
511 || fwin->flags.lbutton_dont_fit) {
512 if(fwin->language_button)
513 wCoreConfigure(fwin->language_button, 3, (theight-bsize)/2,
514 fwin->language_button->width,
515 fwin->language_button->width);
517 else {
518 if(fwin->language_button)
519 wCoreConfigure(fwin->language_button,
520 6 + fwin->left_button->width, (theight-bsize)/2,
521 fwin->language_button->width,
522 fwin->language_button->width);
525 #endif
527 if (wPreferences.new_style) {
528 if (!fwin->flags.hide_right_button && fwin->right_button
529 && !fwin->flags.rbutton_dont_fit) {
530 w -= fwin->right_button->width;
534 if (wPreferences.new_style || fwin->titlebar->width!=w)
535 fwin->flags.need_texture_remake = 1;
537 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
541 void
542 wFrameWindowHideButton(WFrameWindow *fwin, int flags)
544 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
545 XUnmapWindow(dpy, fwin->right_button->window);
546 fwin->flags.hide_right_button = 1;
549 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
550 XUnmapWindow(dpy, fwin->left_button->window);
551 fwin->flags.hide_left_button = 1;
554 #ifdef XKB_BUTTON_HINT
555 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
556 XUnmapWindow(dpy, fwin->language_button->window);
557 fwin->flags.hide_language_button = 1;
559 #endif
561 if (fwin->titlebar) {
562 if (wPreferences.new_style) {
563 updateTitlebar(fwin);
564 } else {
565 #ifdef XKB_BUTTON_HINT
566 updateTitlebar(fwin);
567 #else
568 XClearWindow(dpy, fwin->titlebar->window);
569 wFrameWindowPaint(fwin);
570 #endif
572 checkTitleSize(fwin);
577 void
578 wFrameWindowShowButton(WFrameWindow *fwin, int flags)
580 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button
581 && fwin->flags.hide_right_button) {
583 if (!fwin->flags.rbutton_dont_fit)
584 XMapWindow(dpy, fwin->right_button->window);
586 fwin->flags.hide_right_button = 0;
589 #ifdef XKB_BUTTON_HINT
590 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button
591 && fwin->flags.hide_language_button) {
593 if (!fwin->flags.languagebutton_dont_fit)
594 XMapWindow(dpy, fwin->language_button->window);
596 fwin->flags.hide_language_button = 0;
598 #endif
600 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button
601 && fwin->flags.hide_left_button) {
603 if (!fwin->flags.lbutton_dont_fit)
604 XMapWindow(dpy, fwin->left_button->window);
606 fwin->flags.hide_left_button = 0;
610 if (fwin->titlebar) {
611 if (wPreferences.new_style) {
612 updateTitlebar(fwin);
613 } else {
614 XClearWindow(dpy, fwin->titlebar->window);
615 wFrameWindowPaint(fwin);
617 checkTitleSize(fwin);
622 static void
623 #ifdef XKB_BUTTON_HINT
624 renderTexture(WScreen *scr, WTexture *texture, int width, int height,
625 int bwidth, int bheight, int left, int language, int right,
626 Pixmap *title, Pixmap *lbutton, Pixmap *languagebutton, Pixmap *rbutton)
627 #else
628 renderTexture(WScreen *scr, WTexture *texture, int width, int height,
629 int bwidth, int bheight, int left, int right,
630 Pixmap *title, Pixmap *lbutton, Pixmap *rbutton)
631 #endif
633 RImage *img;
634 RImage *limg, *rimg, *mimg;
635 #ifdef XKB_BUTTON_HINT
636 RImage *timg;
637 #endif
638 int x, w;
640 *title = None;
641 *lbutton = None;
642 *rbutton = None;
643 #ifdef XKB_BUTTON_HINT
644 *languagebutton = None;
645 #endif
647 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
648 if (!img) {
649 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
650 return;
653 if (wPreferences.new_style) {
654 if (left) {
655 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
656 } else
657 limg = NULL;
659 x = 0;
660 w = img->width;
662 #ifdef XKB_BUTTON_HINT
663 if (language) {
664 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
665 } else
666 timg = NULL;
667 #endif
669 if (limg) {
670 RBevelImage(limg, RBEV_RAISED2);
671 if (!RConvertImage(scr->rcontext, limg, lbutton)) {
672 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
674 x += limg->width;
675 w -= limg->width;
676 RReleaseImage(limg);
679 #ifdef XKB_BUTTON_HINT
680 if (timg) {
681 RBevelImage(timg, RBEV_RAISED2);
682 if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
683 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
685 x += timg->width;
686 w -= timg->width;
687 RReleaseImage(timg);
689 #endif
691 if (right) {
692 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
693 } else
694 rimg = NULL;
696 if (rimg) {
697 RBevelImage(rimg, RBEV_RAISED2);
698 if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
699 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
701 w -= rimg->width;
702 RReleaseImage(rimg);
705 if (w!=width) {
706 mimg = RGetSubImage(img, x, 0, w, img->height);
707 RBevelImage(mimg, RBEV_RAISED2);
709 if (!RConvertImage(scr->rcontext, mimg, title)) {
710 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
712 RReleaseImage(mimg);
713 } else {
714 RBevelImage(img, RBEV_RAISED2);
716 if (!RConvertImage(scr->rcontext, img, title)) {
717 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
720 } else {
721 RBevelImage(img, RBEV_RAISED2);
723 if (!RConvertImage(scr->rcontext, img, title)) {
724 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
728 RReleaseImage(img);
732 static void
733 renderResizebarTexture(WScreen *scr, WTexture *texture, int width, int height,
734 int cwidth, Pixmap *pmap)
736 RImage *img;
737 RColor light;
738 RColor dark;
740 *pmap = None;
742 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
743 if (!img) {
744 wwarning(_("could not render texture: %s"),
745 RMessageForError(RErrorCode));
746 return;
749 light.alpha = 0;
750 light.red = light.green = light.blue = 80;
752 dark.alpha = 0;
753 dark.red = dark.green = dark.blue = 40;
755 ROperateLine(img, RSubtractOperation, 0, 0, width-1, 0, &dark);
756 ROperateLine(img, RAddOperation, 0, 1, width-1, 1, &light);
758 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height-1, &dark);
759 ROperateLine(img, RAddOperation, cwidth+1, 2, cwidth+1, height-1, &light);
761 if (width > 1)
762 ROperateLine(img, RSubtractOperation, width-cwidth-2, 2,
763 width-cwidth-2, height-1, &dark);
764 ROperateLine(img, RAddOperation, width-cwidth-1, 2, width-cwidth-1,
765 height-1, &light);
767 #ifdef SHADOW_RESIZEBAR
768 ROperateLine(img, RAddOperation, 0, 1, 0, height-1, &light);
769 ROperateLine(img, RSubtractOperation, width-1, 1, width-1, height-1,
770 &dark);
771 ROperateLine(img, RSubtractOperation, 0, height-1, width-1, height-1,
772 &dark);
773 #endif /* SHADOW_RESIZEBAR */
776 if (!RConvertImage(scr->rcontext, img, pmap)) {
777 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
780 RReleaseImage(img);
785 static void
786 updateTexture(WFrameWindow *fwin)
788 int i;
789 unsigned long pixel;
791 i = fwin->flags.state;
792 if (fwin->titlebar) {
793 if (fwin->title_texture[i]->any.type!=WTEX_SOLID) {
794 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window,
795 fwin->title_back[i]);
796 if (wPreferences.new_style) {
797 if (fwin->left_button && fwin->lbutton_back[i])
798 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
799 fwin->lbutton_back[i]);
801 #ifdef XKB_BUTTON_HINT
802 if (fwin->language_button && fwin->languagebutton_back[i]) {
803 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
804 fwin->languagebutton_back[i]);
806 #endif
808 if (fwin->right_button && fwin->rbutton_back[i])
809 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
810 fwin->rbutton_back[i]);
812 } else {
813 pixel = fwin->title_texture[i]->solid.normal.pixel;
814 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
815 if (wPreferences.new_style) {
816 if (fwin->left_button)
817 XSetWindowBackground(dpy, fwin->left_button->window,
818 pixel);
819 #ifdef XKB_BUTTON_HINT
820 if (fwin->language_button)
821 XSetWindowBackground(dpy, fwin->language_button->window,
822 pixel);
823 #endif
824 if (fwin->right_button)
825 XSetWindowBackground(dpy, fwin->right_button->window,
826 pixel);
829 XClearWindow(dpy, fwin->titlebar->window);
831 if (fwin->left_button) {
832 XClearWindow(dpy, fwin->left_button->window);
833 handleButtonExpose(&fwin->left_button->descriptor, NULL);
835 #ifdef XKB_BUTTON_HINT
836 if (fwin->language_button) {
837 XClearWindow(dpy, fwin->language_button->window);
838 handleButtonExpose(&fwin->language_button->descriptor, NULL);
840 #endif
841 if (fwin->right_button) {
842 XClearWindow(dpy, fwin->right_button->window);
843 handleButtonExpose(&fwin->right_button->descriptor, NULL);
850 static void
851 remakeTexture(WFrameWindow *fwin, int state)
853 Pixmap pmap, lpmap, rpmap;
854 #ifdef XKB_BUTTON_HINT
855 Pixmap tpmap;
856 #endif
858 if (fwin->title_texture[state] && fwin->titlebar) {
859 FREE_PIXMAP(fwin->title_back[state]);
860 if (wPreferences.new_style) {
861 FREE_PIXMAP(fwin->lbutton_back[state]);
862 FREE_PIXMAP(fwin->rbutton_back[state]);
863 #ifdef XKB_BUTTON_HINT
864 FREE_PIXMAP(fwin->languagebutton_back[state]);
865 #endif
868 if (fwin->title_texture[state]->any.type!=WTEX_SOLID) {
869 int left, right;
870 int width;
871 #ifdef XKB_BUTTON_HINT
872 int language;
873 #endif
875 /* eventually surrounded by if new_style */
876 left = fwin->left_button && !fwin->flags.hide_left_button
877 && !fwin->flags.lbutton_dont_fit;
878 #ifdef XKB_BUTTON_HINT
879 language = fwin->language_button && !fwin->flags.hide_language_button
880 && !fwin->flags.languagebutton_dont_fit;
881 #endif
882 right = fwin->right_button && !fwin->flags.hide_right_button
883 && !fwin->flags.rbutton_dont_fit;
885 width = fwin->core->width+1;
887 #ifdef XKB_BUTTON_HINT
888 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
889 width, fwin->titlebar->height,
890 fwin->titlebar->height, fwin->titlebar->height,
891 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
892 #else
893 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
894 width, fwin->titlebar->height,
895 fwin->titlebar->height, fwin->titlebar->height,
896 left, right, &pmap, &lpmap, &rpmap);
897 #endif
899 fwin->title_back[state] = pmap;
900 if (wPreferences.new_style) {
901 fwin->lbutton_back[state] = lpmap;
902 fwin->rbutton_back[state] = rpmap;
903 #ifdef XKB_BUTTON_HINT
904 fwin->languagebutton_back[state] = tpmap;
905 #endif
909 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
910 && fwin->resizebar && state == 0) {
912 FREE_PIXMAP(fwin->resizebar_back[0]);
914 if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
916 renderResizebarTexture(fwin->screen_ptr,
917 fwin->resizebar_texture[0],
918 fwin->resizebar->width,
919 fwin->resizebar->height,
920 fwin->resizebar_corner_width,
921 &pmap);
923 fwin->resizebar_back[0] = pmap;
926 /* this part should be in updateTexture() */
927 if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
928 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window,
929 fwin->resizebar_back[0]);
930 } else {
931 XSetWindowBackground(dpy, fwin->resizebar->window,
932 fwin->resizebar_texture[0]->solid.normal.pixel);
934 XClearWindow(dpy, fwin->resizebar->window);
939 void
940 wFrameWindowPaint(WFrameWindow *fwin)
942 WScreen *scr = fwin->screen_ptr;
943 int state;
945 state = fwin->flags.state;
947 if (fwin->flags.is_client_window_frame)
948 fwin->flags.justification = wPreferences.title_justification;
950 if (fwin->flags.need_texture_remake) {
951 int i;
953 fwin->flags.need_texture_remake = 0;
954 fwin->flags.need_texture_change = 0;
956 if (fwin->flags.single_texture) {
957 remakeTexture(fwin, 0);
958 updateTexture(fwin);
959 } else {
960 /* first render the texture for the current state... */
961 remakeTexture(fwin, state);
962 /* ... and paint it */
963 updateTexture(fwin);
965 for (i=0; i < 3; i++) {
966 if (i != state) {
967 remakeTexture(fwin, i);
973 if (fwin->flags.need_texture_change) {
974 fwin->flags.need_texture_change = 0;
976 updateTexture(fwin);
979 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
980 && fwin->title_texture[state]->any.type==WTEX_SOLID) {
981 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
982 fwin->titlebar->height,
983 (WTexSolid*)fwin->title_texture[state],
984 WREL_RAISED);
987 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
988 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
989 Window win;
990 int w, h;
991 int cw;
992 GC light_gc, dim_gc;
993 WTexSolid *texture = (WTexSolid*)fwin->resizebar_texture[0];
995 w = fwin->resizebar->width;
996 h = fwin->resizebar->height;
997 cw = fwin->resizebar_corner_width;
998 light_gc = texture->light_gc;
999 dim_gc = texture->dim_gc;
1000 win = fwin->resizebar->window;
1002 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
1003 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
1005 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
1006 XDrawLine(dpy, win, light_gc, cw+1, 2, cw+1, h);
1008 XDrawLine(dpy, win, dim_gc, w-cw-2, 2, w-cw-2, h);
1009 XDrawLine(dpy, win, light_gc, w-cw-1, 2, w-cw-1, h);
1011 #ifdef SHADOW_RESIZEBAR
1012 XDrawLine(dpy, win, light_gc, 0, 1, 0, h-1);
1013 XDrawLine(dpy, win, dim_gc, w-1, 2, w-1, h-1);
1014 XDrawLine(dpy, win, dim_gc, 1, h-1, cw, h-1);
1015 XDrawLine(dpy, win, dim_gc, cw+2, h-1, w-cw-2, h-1);
1016 XDrawLine(dpy, win, dim_gc, w-cw, h-1, w-1, h-1);
1017 #endif /* SHADOW_RESIZEBAR */
1021 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
1022 int x, y, w, h;
1023 int lofs = 6, rofs = 6;
1024 int titlelen;
1025 int allButtons = 1;
1028 if (!wPreferences.new_style) {
1029 if (fwin->left_button && !fwin->flags.hide_left_button
1030 && !fwin->flags.lbutton_dont_fit)
1031 lofs += fwin->left_button->width + 3;
1032 else
1033 allButtons = 0;
1035 #ifdef XKB_BUTTON_HINT
1036 if (fwin->language_button && !fwin->flags.hide_language_button
1037 && !fwin->flags.languagebutton_dont_fit)
1038 lofs += fwin->language_button->width;
1039 else
1040 allButtons = 0;
1041 #endif
1043 if (fwin->right_button && !fwin->flags.hide_right_button
1044 && !fwin->flags.rbutton_dont_fit)
1045 rofs += fwin->right_button->width + 3;
1046 else
1047 allButtons = 0;
1050 #ifdef XKB_BUTTON_HINT
1051 fwin->languagebutton_image =
1052 scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1053 #endif
1055 if (fwin->title) {
1056 Drawable buf;
1057 char *title;
1059 title = ShrinkString(*fwin->font, fwin->title,
1060 fwin->titlebar->width - lofs - rofs);
1061 titlelen = strlen(title);
1062 w = WMWidthOfString(*fwin->font, title, titlelen);
1064 switch (fwin->flags.justification) {
1065 case WTJ_LEFT:
1066 x = lofs;
1067 break;
1069 case WTJ_RIGHT:
1070 x = fwin->titlebar->width - w - rofs;
1071 break;
1073 default:
1074 if (!allButtons)
1075 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1076 else
1077 x = (fwin->titlebar->width - w) / 2;
1078 break;
1081 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1082 h = WMFontHeight(*fwin->font);
1084 /* We use a w+2 buffer to have an extra pixel on the left and
1085 * another one on the right. This is because for some odd reason,
1086 * sometimes when using AA fonts (when libfreetype2 is compiled
1087 * with bytecode interpreter turned off), some fonts are drawn
1088 * starting from x = -1 not from 0 as requested. Observed with
1089 * capital A letter on the bold 'trebuchet ms' font. -Dan
1091 buf = XCreatePixmap(dpy, fwin->titlebar->window, w+2, h,
1092 scr->w_depth);
1094 XSetClipMask(dpy, scr->copy_gc, None);
1096 if (fwin->title_texture[state]->any.type!=WTEX_SOLID) {
1097 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1098 x-1, y, w+2, h, 0, 0);
1099 } else {
1100 XSetForeground(dpy, scr->copy_gc,
1101 fwin->title_texture[state]->solid.normal.pixel);
1102 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w+2, h);
1105 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1);*/
1106 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1107 *fwin->font, 1, 0, title, titlelen);
1109 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc,
1110 0, 0, w+2, h, x-1, y);
1112 XFreePixmap(dpy, buf);
1114 wfree(title);
1117 if (fwin->left_button)
1118 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1119 if (fwin->right_button)
1120 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1121 #ifdef XKB_BUTTON_HINT
1122 if (fwin->language_button)
1123 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1124 #endif
1129 static void
1130 reconfigure(WFrameWindow *fwin, int x, int y, int width, int height,
1131 Bool dontMove)
1133 int k = (wPreferences.new_style ? 4 : 3);
1134 int resizedHorizontally = 0;
1136 if (dontMove)
1137 XResizeWindow(dpy, fwin->core->window, width, height);
1138 else
1139 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1142 if (fwin->core->height != height && fwin->resizebar)
1143 XMoveWindow(dpy, fwin->resizebar->window, 0,
1144 height - fwin->resizebar->height);
1146 if (fwin->core->width != width) {
1147 fwin->flags.need_texture_remake = 1;
1148 resizedHorizontally = 1;
1151 fwin->core->width = width;
1152 fwin->core->height = height;
1154 if (fwin->titlebar && resizedHorizontally) {
1155 /* Check if the titlebar is wide enough to hold the buttons.
1156 * Temporarily remove them if can't
1158 if (fwin->left_button) {
1159 if (width < fwin->top_width*k && !fwin->flags.lbutton_dont_fit) {
1161 if (!fwin->flags.hide_left_button) {
1162 XUnmapWindow(dpy, fwin->left_button->window);
1164 fwin->flags.lbutton_dont_fit = 1;
1165 } else if (width >= fwin->top_width*k && fwin->flags.lbutton_dont_fit) {
1167 if (!fwin->flags.hide_left_button) {
1168 XMapWindow(dpy, fwin->left_button->window);
1170 fwin->flags.lbutton_dont_fit = 0;
1174 #ifdef XKB_BUTTON_HINT
1175 if (fwin->language_button) {
1176 if (width < fwin->top_width*k && !fwin->flags.languagebutton_dont_fit) {
1178 if (!fwin->flags.hide_language_button) {
1179 XUnmapWindow(dpy, fwin->language_button->window);
1181 fwin->flags.languagebutton_dont_fit = 1;
1182 } else if (width >= fwin->top_width*k && fwin->flags.languagebutton_dont_fit) {
1184 if (!fwin->flags.hide_language_button) {
1185 XMapWindow(dpy, fwin->language_button->window);
1187 fwin->flags.languagebutton_dont_fit = 0;
1190 #endif
1192 if (fwin->right_button) {
1193 if (width < fwin->top_width*2 && !fwin->flags.rbutton_dont_fit) {
1195 if (!fwin->flags.hide_right_button) {
1196 XUnmapWindow(dpy, fwin->right_button->window);
1198 fwin->flags.rbutton_dont_fit = 1;
1199 } else if (width >= fwin->top_width*2 && fwin->flags.rbutton_dont_fit) {
1201 if (!fwin->flags.hide_right_button) {
1202 XMapWindow(dpy, fwin->right_button->window);
1204 fwin->flags.rbutton_dont_fit = 0;
1208 if (wPreferences.new_style) {
1209 if (fwin->right_button)
1210 XMoveWindow(dpy, fwin->right_button->window,
1211 width - fwin->right_button->width + 1, 0);
1212 } else {
1213 if (fwin->right_button)
1214 XMoveWindow(dpy, fwin->right_button->window,
1215 width - fwin->right_button->width - 3,
1216 (fwin->titlebar->height - fwin->right_button->height)/2);
1218 updateTitlebar(fwin);
1219 checkTitleSize(fwin);
1222 if (fwin->resizebar) {
1223 wCoreConfigure(fwin->resizebar, 0,
1224 fwin->core->height - fwin->resizebar->height,
1225 fwin->core->width, fwin->resizebar->height);
1227 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1228 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
1229 fwin->resizebar_corner_width = fwin->core->width/2;
1234 void
1235 wFrameWindowConfigure(WFrameWindow *fwin, int x, int y, int width, int height)
1237 reconfigure(fwin, x, y, width, height, False);
1240 void
1241 wFrameWindowResize(WFrameWindow *fwin, int width, int height)
1243 reconfigure(fwin, 0, 0, width, height, True);
1248 int
1249 wFrameWindowChangeTitle(WFrameWindow *fwin, char *new_title)
1251 /* check if the title is the same as before */
1252 if (fwin->title) {
1253 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1254 return 0;
1256 } else {
1257 if (!new_title)
1258 return 0;
1261 if (fwin->title)
1262 wfree(fwin->title);
1264 fwin->title = wstrdup(new_title);
1266 if (fwin->titlebar) {
1267 XClearWindow(dpy, fwin->titlebar->window);
1269 wFrameWindowPaint(fwin);
1271 checkTitleSize(fwin);
1273 return 1;
1277 #ifdef OLWM_HINTS
1278 void
1279 wFrameWindowUpdatePushButton(WFrameWindow *fwin, Bool pushed)
1281 fwin->flags.right_button_pushed_in = pushed;
1283 paintButton(fwin->right_button, fwin->title_texture[fwin->flags.state],
1284 WMColorPixel(fwin->title_color[fwin->flags.state]),
1285 fwin->rbutton_image, pushed);
1287 #endif /* OLWM_HINTS */
1290 #ifdef XKB_BUTTON_HINT
1291 void
1292 wFrameWindowUpdateLanguageButton(WFrameWindow *fwin)
1294 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1295 WMColorPixel(fwin->title_color[fwin->flags.state]),
1296 fwin->languagebutton_image, True);
1298 #endif /* XKB_BUTTON_HINT */
1301 /*********************************************************************/
1303 static void
1304 handleExpose(WObjDescriptor *desc, XEvent *event)
1306 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1309 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1310 fwin->flags.repaint_only_titlebar = 1;
1311 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1312 fwin->flags.repaint_only_resizebar = 1;
1313 wFrameWindowPaint(fwin);
1314 fwin->flags.repaint_only_titlebar = 0;
1315 fwin->flags.repaint_only_resizebar = 0;
1319 static void
1320 checkTitleSize(WFrameWindow *fwin)
1322 int width;
1324 if (!fwin->title) {
1325 fwin->flags.incomplete_title = 0;
1326 return;
1329 if (!fwin->titlebar) {
1330 fwin->flags.incomplete_title = 1;
1331 return;
1332 } else {
1333 width = fwin->titlebar->width - 6 - 6;
1336 if (!wPreferences.new_style) {
1337 if (fwin->left_button && !fwin->flags.hide_left_button
1338 && !fwin->flags.lbutton_dont_fit)
1339 width -= fwin->left_button->width + 3;
1341 #ifdef XKB_BUTTON_HINT
1342 if (fwin->language_button && !fwin->flags.hide_language_button
1343 && !fwin->flags.languagebutton_dont_fit)
1344 width -= fwin->language_button->width + 3;
1345 #endif
1347 if (fwin->right_button && !fwin->flags.hide_right_button
1348 && !fwin->flags.rbutton_dont_fit)
1349 width -= fwin->right_button->width + 3;
1351 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1352 fwin->flags.incomplete_title = 1;
1353 } else {
1354 fwin->flags.incomplete_title = 0;
1359 static void
1360 paintButton(WCoreWindow *button, WTexture *texture, unsigned long color,
1361 WPixmap *image, int pushed)
1363 WScreen *scr = button->screen_ptr;
1364 GC copy_gc = scr->copy_gc;
1365 int x=0, y=0, d=0;
1366 int left=0, width=0;
1368 /* setup stuff according to the state */
1369 if (pushed) {
1370 if (image) {
1371 if (image->width>=image->height*2) {
1372 /* the image contains 2 pictures: the second is for the
1373 * pushed state */
1374 width = image->width/2;
1375 left = image->width/2;
1376 } else {
1377 width = image->width;
1380 XSetClipMask(dpy, copy_gc, None);
1381 XSetForeground(dpy, copy_gc, scr->white_pixel);
1382 d=1;
1383 if (wPreferences.new_style) {
1384 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1385 button->width-1, button->height-1);
1386 XSetForeground(dpy, copy_gc, scr->black_pixel);
1387 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1388 button->width-1, button->height-1);
1389 } else {
1390 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1391 button->width, button->height);
1392 XSetForeground(dpy, copy_gc, scr->black_pixel);
1393 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1394 button->width, button->height);
1396 } else {
1397 XClearWindow(dpy, button->window);
1399 if (image) {
1400 if (image->width>=image->height*2)
1401 width = image->width/2;
1402 else
1403 width = image->width;
1405 d=0;
1407 if (wPreferences.new_style) {
1408 if (texture->any.type==WTEX_SOLID || pushed) {
1409 wDrawBevel(button->window, button->width, button->height,
1410 (WTexSolid*)texture, WREL_RAISED);
1412 } else {
1413 wDrawBevel(button->window, button->width, button->height,
1414 scr->widget_texture, WREL_RAISED);
1418 if (image) {
1419 /* display image */
1420 XSetClipMask(dpy, copy_gc, image->mask);
1421 x = (button->width - width)/2 + d;
1422 y = (button->height - image->height)/2 + d;
1423 XSetClipOrigin(dpy, copy_gc, x-left, y);
1424 if (!wPreferences.new_style) {
1425 XSetForeground(dpy, copy_gc, scr->black_pixel);
1426 if (!pushed) {
1427 if (image->depth==1)
1428 XCopyPlane(dpy, image->image, button->window, copy_gc,
1429 left, 0, width, image->height, x, y, 1);
1430 else
1431 XCopyArea(dpy, image->image, button->window, copy_gc,
1432 left, 0, width, image->height, x, y);
1433 } else {
1434 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1435 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1436 button->width, button->height);
1438 } else {
1439 if (pushed) {
1440 XSetForeground(dpy, copy_gc, scr->black_pixel);
1441 } else {
1442 XSetForeground(dpy, copy_gc, color);
1443 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1445 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1446 button->width, button->height);
1452 static void
1453 handleButtonExpose(WObjDescriptor *desc, XEvent *event)
1455 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1456 WCoreWindow *button = (WCoreWindow*)desc->self;
1458 #ifdef XKB_BUTTON_HINT
1459 if (button == fwin->language_button) {
1460 if (wPreferences.modelock){
1461 paintButton(button, fwin->title_texture[fwin->flags.state],
1462 WMColorPixel(fwin->title_color[fwin->flags.state]),
1463 fwin->languagebutton_image, False);
1465 } else
1466 #endif
1467 if (button == fwin->left_button) {
1468 paintButton(button, fwin->title_texture[fwin->flags.state],
1469 WMColorPixel(fwin->title_color[fwin->flags.state]),
1470 fwin->lbutton_image, False);
1471 } else {
1472 Bool pushed = False;
1474 #ifdef OLWM_HINTS
1475 if (fwin->flags.right_button_pushed_in)
1476 pushed = True;
1477 #endif
1478 /* emulate the olwm pushpin in the "out" state */
1479 paintButton(button, fwin->title_texture[fwin->flags.state],
1480 WMColorPixel(fwin->title_color[fwin->flags.state]),
1481 fwin->rbutton_image, pushed);
1486 static void
1487 titlebarMouseDown(WObjDescriptor *desc, XEvent *event)
1489 WFrameWindow *fwin = desc->parent;
1490 WCoreWindow *titlebar = desc->self;
1492 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1493 if (fwin->on_dblclick_titlebar)
1494 (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event);
1495 } else {
1496 if (fwin->on_mousedown_titlebar)
1497 (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event);
1502 static void
1503 resizebarMouseDown(WObjDescriptor *desc, XEvent *event)
1505 WFrameWindow *fwin = desc->parent;
1506 WCoreWindow *resizebar = desc->self;
1508 if (fwin->on_mousedown_resizebar)
1509 (*fwin->on_mousedown_resizebar)(resizebar, fwin->child, event);
1513 static void
1514 buttonMouseDown(WObjDescriptor *desc, XEvent *event)
1516 WFrameWindow *fwin = desc->parent;
1517 WCoreWindow *button = desc->self;
1518 WPixmap *image;
1519 XEvent ev;
1520 int done=0, execute=1;
1521 WTexture *texture;
1522 unsigned long pixel;
1523 int clickButton = event->xbutton.button;
1525 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1526 if (button == fwin->right_button && fwin->on_dblclick_right) {
1527 (*fwin->on_dblclick_right)(button, fwin->child, event);
1529 return;
1532 if (button == fwin->left_button) {
1533 image = fwin->lbutton_image;
1534 } else {
1535 image = fwin->rbutton_image;
1537 #ifdef XKB_BUTTON_HINT
1538 if (button == fwin->language_button) {
1539 if (!wPreferences.modelock) return;
1540 image = fwin->languagebutton_image;
1542 #endif
1544 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1545 texture = fwin->title_texture[fwin->flags.state];
1546 paintButton(button, texture, pixel, image, True);
1548 while (!done) {
1549 WMMaskEvent(dpy, LeaveWindowMask|EnterWindowMask|ButtonReleaseMask
1550 |ButtonPressMask|ExposureMask, &ev);
1551 switch (ev.type) {
1552 case LeaveNotify:
1553 execute = 0;
1554 paintButton(button, texture, pixel, image, False);
1555 break;
1557 case EnterNotify:
1558 execute = 1;
1559 paintButton(button, texture, pixel, image, True);
1560 break;
1562 case ButtonPress:
1563 break;
1565 case ButtonRelease:
1566 if (ev.xbutton.button == clickButton)
1567 done = 1;
1568 break;
1570 default:
1571 WMHandleEvent(&ev);
1574 paintButton(button, texture, pixel, image, False);
1576 if (execute) {
1577 if (button == fwin->left_button) {
1578 if (fwin->on_click_left)
1579 (*fwin->on_click_left)(button, fwin->child, &ev);
1580 } else if (button == fwin->right_button) {
1581 if (fwin->on_click_right)
1582 (*fwin->on_click_right)(button, fwin->child, &ev);
1584 #ifdef XKB_BUTTON_HINT
1585 else if (button == fwin->language_button) {
1586 if (fwin->on_click_language)
1587 (*fwin->on_click_language)(button, fwin->child, &ev);
1589 #endif