Allow setting separate border color for focused windows
[wmaker-crm.git] / src / framewin.c
blob13fe1e09e64ebaf8519f5b6757af6a67f0639432
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 along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "wconfig.h"
23 #include <X11/Xlib.h>
24 #include <X11/Xutil.h>
25 #ifdef KEEP_XKB_LOCK_STATUS
26 #include <X11/XKBlib.h>
27 #endif /* KEEP_XKB_LOCK_STATUS */
29 #include <stdlib.h>
30 #include <string.h>
32 #include <wraster.h>
34 #include "WindowMaker.h"
35 #include "GNUstep.h"
36 #include "texture.h"
37 #include "resources.h"
38 #include "screen.h"
39 #include "wcore.h"
40 #include "window.h"
41 #include "framewin.h"
42 #include "stacking.h"
43 #include "misc.h"
44 #include "event.h"
46 #define DBLCLICK_TIME wPreferences.dblclick_time
49 static void handleExpose(WObjDescriptor * desc, XEvent * event);
50 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event);
52 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event);
53 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event);
54 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event);
56 static void checkTitleSize(WFrameWindow * fwin);
58 static void paintButton(WCoreWindow * button, WTexture * texture,
59 unsigned long color, WPixmap * image, int pushed);
61 static void updateTitlebar(WFrameWindow * fwin);
63 static void allocFrameBorderPixel(Colormap colormap, const char *color_name, unsigned long **pixel);
65 static void allocFrameBorderPixel(Colormap colormap, const char *color_name, unsigned long **pixel) {
66 XColor xcol;
68 *pixel = NULL;
70 if (! wGetColorForColormap(colormap, color_name, &xcol))
71 return;
73 *pixel = wmalloc(sizeof(unsigned long));
74 if (*pixel)
75 **pixel = xcol.pixel;
78 WFrameWindow *wFrameWindowCreate(WScreen * scr, int wlevel, int x, int y,
79 int width, int height, int *clearance,
80 int *title_min, int *title_max, int flags,
81 WTexture ** title_texture, WTexture ** resize_texture,
82 WMColor ** color, WMFont ** font,
83 int depth, Visual *visual, Colormap colormap)
85 WFrameWindow *fwin;
87 fwin = wmalloc(sizeof(WFrameWindow));
89 fwin->screen_ptr = scr;
91 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
93 fwin->title_texture = title_texture;
94 fwin->resizebar_texture = resize_texture;
95 fwin->title_color = color;
96 fwin->title_clearance = clearance;
97 fwin->title_min_height = title_min;
98 fwin->title_max_height = title_max;
99 fwin->font = font;
100 #ifdef KEEP_XKB_LOCK_STATUS
101 fwin->languagemode = XkbGroup1Index;
102 fwin->last_languagemode = XkbGroup2Index;
103 #endif
105 fwin->depth = depth;
106 fwin->visual = visual;
107 fwin->colormap = colormap;
109 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height, (flags & WFF_BORDER)
110 ? scr->frame_border_width : 0, fwin->depth, fwin->visual, fwin->colormap, scr->frame_border_pixel);
112 /* setup stacking information */
113 fwin->core->stacking = wmalloc(sizeof(WStacking));
114 fwin->core->stacking->above = NULL;
115 fwin->core->stacking->under = NULL;
116 fwin->core->stacking->child_of = NULL;
117 fwin->core->stacking->window_level = wlevel;
119 AddToStackList(fwin->core);
121 wFrameWindowUpdateBorders(fwin, flags);
123 return fwin;
126 void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
128 int theight;
129 int bsize;
130 int width, height;
131 int i;
132 WScreen *scr = fwin->screen_ptr;
134 width = fwin->core->width;
135 if (flags & WFF_IS_SHADED)
136 height = -1;
137 else
138 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
140 if (flags & WFF_TITLEBAR) {
141 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
143 if (theight > *fwin->title_max_height)
144 theight = *fwin->title_max_height;
146 if (theight < *fwin->title_min_height)
147 theight = *fwin->title_min_height;
148 } else {
149 theight = 0;
152 if (wPreferences.new_style == TS_NEW) {
153 bsize = theight;
154 } else if (wPreferences.new_style == TS_OLD) {
155 bsize = theight - 7;
156 } else {
157 bsize = theight - 8;
160 if (fwin->titlebar) {
161 /* if we had a titlebar and is requesting for one,
162 * check if the size has changed and resize it */
163 if (flags & WFF_TITLEBAR) {
164 fwin->top_width = theight;
166 fwin->flags.need_texture_remake = 1;
168 if (wPreferences.new_style == TS_NEW) {
169 if (fwin->left_button)
170 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
171 #ifdef XKB_BUTTON_HINT
172 if (fwin->language_button) {
173 if (fwin->flags.hide_left_button || !fwin->left_button
174 || fwin->flags.lbutton_dont_fit)
175 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
176 else
177 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
179 #endif
181 if (fwin->right_button)
182 wCoreConfigure(fwin->right_button, width - bsize + 1, 0, bsize, bsize);
184 } else { /* !new_style */
185 if (fwin->left_button)
186 wCoreConfigure(fwin->left_button, 3, (theight - bsize) / 2, bsize, bsize);
187 #ifdef XKB_BUTTON_HINT
188 if (fwin->language_button)
189 wCoreConfigure(fwin->language_button, 6 + bsize, (theight - bsize) / 2,
190 bsize, bsize);
191 #endif
193 if (fwin->right_button)
194 wCoreConfigure(fwin->right_button, width - bsize - 3,
195 (theight - bsize) / 2, bsize, bsize);
197 updateTitlebar(fwin);
198 } else {
199 /* we had a titlebar, but now we don't need it anymore */
200 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
201 FREE_PIXMAP(fwin->title_back[i]);
202 if (wPreferences.new_style == TS_NEW) {
203 FREE_PIXMAP(fwin->lbutton_back[i]);
204 FREE_PIXMAP(fwin->rbutton_back[i]);
205 #ifdef XKB_BUTTON_HINT
206 FREE_PIXMAP(fwin->languagebutton_back[i]);
207 #endif
210 if (fwin->left_button)
211 wCoreDestroy(fwin->left_button);
212 fwin->left_button = NULL;
214 #ifdef XKB_BUTTON_HINT
215 if (fwin->language_button)
216 wCoreDestroy(fwin->language_button);
217 fwin->language_button = NULL;
218 #endif
220 if (fwin->right_button)
221 wCoreDestroy(fwin->right_button);
222 fwin->right_button = NULL;
224 wCoreDestroy(fwin->titlebar);
225 fwin->titlebar = NULL;
227 fwin->top_width = 0;
229 } else {
230 /* if we didn't have a titlebar and are being requested for
231 * one, create it */
232 if (flags & WFF_TITLEBAR) {
233 fwin->top_width = theight;
235 fwin->flags.titlebar = 1;
236 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width + 1, theight);
238 if (flags & WFF_LEFT_BUTTON) {
239 fwin->flags.left_button = 1;
240 if (wPreferences.new_style == TS_NEW) {
241 fwin->left_button = wCoreCreate(fwin->core, 0, 0, bsize, bsize);
243 if (width < theight * 4)
244 fwin->flags.lbutton_dont_fit = 1;
245 else
246 XMapRaised(dpy, fwin->left_button->window);
248 } else if (wPreferences.new_style == TS_OLD) {
249 fwin->left_button =
250 wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
252 XSetWindowBackground(dpy, fwin->left_button->window,
253 scr->widget_texture->normal.pixel);
255 if (width < theight * 3)
256 fwin->flags.lbutton_dont_fit = 1;
257 else
258 XMapRaised(dpy, fwin->left_button->window);
260 } else {
261 fwin->left_button =
262 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
263 bsize, bsize);
265 XSetWindowBackground(dpy, fwin->left_button->window,
266 scr->widget_texture->dark.pixel);
268 if (width < theight * 3)
269 fwin->flags.lbutton_dont_fit = 1;
270 else
271 XMapRaised(dpy, fwin->left_button->window);
275 #ifdef XKB_BUTTON_HINT
276 if (flags & WFF_LANGUAGE_BUTTON) {
277 fwin->flags.language_button = 1;
278 if (wPreferences.new_style == TS_NEW) {
279 fwin->language_button = wCoreCreate(fwin->core, bsize, 0, bsize, bsize);
281 if (width < theight * 4)
282 fwin->flags.languagebutton_dont_fit = 1;
283 else
284 XMapRaised(dpy, fwin->language_button->window);
285 } else {
286 fwin->language_button =
287 wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
288 bsize, bsize);
290 XSetWindowBackground(dpy, fwin->language_button->window,
291 scr->widget_texture->normal.pixel);
293 if (width < theight * 3)
294 fwin->flags.languagebutton_dont_fit = 1;
295 else
296 XMapRaised(dpy, fwin->language_button->window);
299 #endif
301 if (flags & WFF_RIGHT_BUTTON) {
302 fwin->flags.right_button = 1;
303 if (wPreferences.new_style == TS_NEW) {
304 fwin->right_button =
305 wCoreCreate(fwin->core, width - bsize + 1, 0, bsize, bsize);
306 } else if (wPreferences.new_style == TS_OLD) {
307 fwin->right_button =
308 wCoreCreate(fwin->titlebar, width - bsize - 3,
309 (theight - bsize) / 2, bsize, bsize);
310 XSetWindowBackground(dpy, fwin->right_button->window,
311 scr->widget_texture->normal.pixel);
312 } else {
313 fwin->right_button =
314 wCoreCreate(fwin->titlebar, width-bsize-3,
315 (theight-bsize)/2, bsize, bsize);
316 XSetWindowBackground(dpy, fwin->right_button->window,
317 scr->widget_texture->dark.pixel);
320 if (width < theight * 2)
321 fwin->flags.rbutton_dont_fit = 1;
322 else
323 XMapRaised(dpy, fwin->right_button->window);
326 if (wPreferences.new_style == TS_NEW)
327 updateTitlebar(fwin);
329 XMapRaised(dpy, fwin->titlebar->window);
331 fwin->flags.need_texture_remake = 1;
334 checkTitleSize(fwin);
336 if (flags & WFF_RESIZEBAR) {
337 fwin->bottom_width = RESIZEBAR_HEIGHT;
339 if (!fwin->resizebar) {
340 fwin->flags.resizebar = 1;
341 fwin->resizebar = wCoreCreate(fwin->core, 0,
342 height + fwin->top_width, width, RESIZEBAR_HEIGHT);
343 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
344 if (width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
345 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH) / 2;
346 if (fwin->resizebar_corner_width < 0)
347 fwin->resizebar_corner_width = 0;
350 XMapWindow(dpy, fwin->resizebar->window);
351 XLowerWindow(dpy, fwin->resizebar->window);
353 fwin->flags.need_texture_remake = 1;
354 } else {
355 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height)
356 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
357 width, RESIZEBAR_HEIGHT);
359 } else {
360 fwin->bottom_width = 0;
362 if (fwin->resizebar) {
363 fwin->bottom_width = 0;
364 wCoreDestroy(fwin->resizebar);
365 fwin->resizebar = NULL;
369 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED))
370 wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
372 if (flags & WFF_BORDER)
373 XSetWindowBorderWidth(dpy, fwin->core->window, scr->frame_border_width);
374 else
375 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
377 /* setup object descriptors */
378 if (fwin->titlebar) {
379 fwin->titlebar->descriptor.handle_expose = handleExpose;
380 fwin->titlebar->descriptor.parent = fwin;
381 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
382 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
385 if (fwin->resizebar) {
386 fwin->resizebar->descriptor.handle_expose = handleExpose;
387 fwin->resizebar->descriptor.parent = fwin;
388 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
389 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
392 if (fwin->left_button) {
393 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
394 fwin->left_button->descriptor.parent = fwin;
395 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
396 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
399 #ifdef XKB_BUTTON_HINT
400 if (fwin->language_button) {
401 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
402 fwin->language_button->descriptor.parent = fwin;
403 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
404 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
406 #endif
408 if (fwin->right_button) {
409 fwin->right_button->descriptor.parent = fwin;
410 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
411 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
412 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
415 checkTitleSize(fwin);
417 allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_border_color), &fwin->border_pixel);
418 allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_focused_border_color), &fwin->focused_border_pixel);
419 allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_selected_border_color), &fwin->selected_border_pixel);
421 if (flags & WFF_SELECTED) {
422 if (fwin->selected_border_pixel)
423 XSetWindowBorder(dpy, fwin->core->window, *fwin->selected_border_pixel);
425 else {
426 if (fwin->flags.state == WS_FOCUSED) {
427 if (fwin->focused_border_pixel)
428 XSetWindowBorder(dpy, fwin->core->window, *fwin->focused_border_pixel);
429 } else {
430 if (fwin->border_pixel)
431 XSetWindowBorder(dpy, fwin->core->window, *fwin->border_pixel);
436 void wFrameWindowDestroy(WFrameWindow * fwin)
438 int i;
440 if (fwin->left_button)
441 wCoreDestroy(fwin->left_button);
443 #ifdef XKB_BUTTON_HINT
444 if (fwin->language_button)
445 wCoreDestroy(fwin->language_button);
446 #endif
448 if (fwin->right_button)
449 wCoreDestroy(fwin->right_button);
451 if (fwin->resizebar)
452 wCoreDestroy(fwin->resizebar);
454 if (fwin->titlebar)
455 wCoreDestroy(fwin->titlebar);
457 RemoveFromStackList(fwin->core);
459 wCoreDestroy(fwin->core);
461 if (fwin->title)
462 wfree(fwin->title);
464 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
465 FREE_PIXMAP(fwin->title_back[i]);
466 if (wPreferences.new_style == TS_NEW) {
467 FREE_PIXMAP(fwin->lbutton_back[i]);
468 #ifdef XKB_BUTTON_HINT
469 FREE_PIXMAP(fwin->languagebutton_back[i]);
470 #endif
471 FREE_PIXMAP(fwin->rbutton_back[i]);
475 wfree(fwin);
478 void wFrameWindowChangeState(WFrameWindow * fwin, int state)
480 if (fwin->flags.state == state)
481 return;
483 fwin->flags.state = state;
484 fwin->flags.need_texture_change = 1;
486 if (fwin->flags.state == WS_FOCUSED) {
487 if (fwin->focused_border_pixel)
488 XSetWindowBorder(dpy, fwin->core->window, *fwin->focused_border_pixel);
489 } else {
490 if (fwin->border_pixel)
491 XSetWindowBorder(dpy, fwin->core->window, *fwin->border_pixel);
493 wFrameWindowPaint(fwin);
496 static void updateTitlebar(WFrameWindow * fwin)
498 int x, w;
499 int theight;
501 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
503 if (theight > *fwin->title_max_height)
504 theight = *fwin->title_max_height;
506 if (theight < *fwin->title_min_height)
507 theight = *fwin->title_min_height;
509 x = 0;
510 w = fwin->core->width + 1;
512 if (wPreferences.new_style == TS_NEW) {
513 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
514 x = 0;
515 #ifdef XKB_BUTTON_HINT
516 if (fwin->language_button)
517 wCoreConfigure(fwin->language_button, 0, 0,
518 fwin->language_button->width, fwin->language_button->width);
519 #endif
520 } else {
521 #ifdef XKB_BUTTON_HINT
522 if (fwin->language_button)
523 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
524 fwin->language_button->width, fwin->language_button->width);
525 #endif
526 x = fwin->left_button->width;
527 w -= fwin->left_button->width;
529 #ifdef XKB_BUTTON_HINT
530 if (fwin->flags.hide_language_button || !fwin->language_button
531 || fwin->flags.languagebutton_dont_fit) {
532 } else {
533 x += fwin->language_button->width;
534 w -= fwin->language_button->width;
536 #endif
538 #ifdef XKB_BUTTON_HINT
539 else {
540 int bsize = theight - 7;
541 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
542 if (fwin->language_button)
543 wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
544 fwin->language_button->width, fwin->language_button->width);
545 } else {
546 if (fwin->language_button)
547 wCoreConfigure(fwin->language_button,
548 6 + fwin->left_button->width, (theight - bsize) / 2,
549 fwin->language_button->width, fwin->language_button->width);
552 #endif
554 if (wPreferences.new_style == TS_NEW) {
555 if (!fwin->flags.hide_right_button && fwin->right_button && !fwin->flags.rbutton_dont_fit)
556 w -= fwin->right_button->width;
559 if (wPreferences.new_style == TS_NEW || fwin->titlebar->width != w)
560 fwin->flags.need_texture_remake = 1;
562 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
565 void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
567 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
568 XUnmapWindow(dpy, fwin->right_button->window);
569 fwin->flags.hide_right_button = 1;
572 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
573 XUnmapWindow(dpy, fwin->left_button->window);
574 fwin->flags.hide_left_button = 1;
576 #ifdef XKB_BUTTON_HINT
577 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
578 XUnmapWindow(dpy, fwin->language_button->window);
579 fwin->flags.hide_language_button = 1;
581 #endif
583 if (fwin->titlebar) {
584 if (wPreferences.new_style == TS_NEW) {
585 updateTitlebar(fwin);
586 } else {
587 #ifdef XKB_BUTTON_HINT
588 updateTitlebar(fwin);
589 #else
590 XClearWindow(dpy, fwin->titlebar->window);
591 wFrameWindowPaint(fwin);
592 #endif
594 checkTitleSize(fwin);
598 void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
600 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
602 if (!fwin->flags.rbutton_dont_fit)
603 XMapWindow(dpy, fwin->right_button->window);
605 fwin->flags.hide_right_button = 0;
607 #ifdef XKB_BUTTON_HINT
608 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
610 if (!fwin->flags.languagebutton_dont_fit)
611 XMapWindow(dpy, fwin->language_button->window);
613 fwin->flags.hide_language_button = 0;
615 #endif
617 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
619 if (!fwin->flags.lbutton_dont_fit)
620 XMapWindow(dpy, fwin->left_button->window);
622 fwin->flags.hide_left_button = 0;
625 if (fwin->titlebar) {
626 if (wPreferences.new_style == TS_NEW) {
627 updateTitlebar(fwin);
628 } else {
629 XClearWindow(dpy, fwin->titlebar->window);
630 wFrameWindowPaint(fwin);
632 checkTitleSize(fwin);
636 static void
637 #ifdef XKB_BUTTON_HINT
638 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
639 int bwidth, int bheight, int left, int language, int right,
640 Pixmap * title, Pixmap * lbutton, Pixmap * languagebutton, Pixmap * rbutton)
641 #else
642 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
643 int bwidth, int bheight, int left, int right, Pixmap * title, Pixmap * lbutton, Pixmap * rbutton)
644 #endif
646 RImage *img;
647 RImage *limg, *rimg, *mimg;
648 #ifdef XKB_BUTTON_HINT
649 RImage *timg;
650 #endif
651 int x, w;
653 *title = None;
654 *lbutton = None;
655 *rbutton = None;
656 #ifdef XKB_BUTTON_HINT
657 *languagebutton = None;
658 #endif
660 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
661 if (!img) {
662 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
663 return;
666 if (wPreferences.new_style == TS_NEW) {
667 if (left)
668 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
669 else
670 limg = NULL;
672 x = 0;
673 w = img->width;
675 #ifdef XKB_BUTTON_HINT
676 if (language)
677 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
678 else
679 timg = NULL;
680 #endif
682 if (limg) {
683 RBevelImage(limg, RBEV_RAISED2);
684 if (!RConvertImage(scr->rcontext, limg, lbutton))
685 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
687 x += limg->width;
688 w -= limg->width;
689 RReleaseImage(limg);
691 #ifdef XKB_BUTTON_HINT
692 if (timg) {
693 RBevelImage(timg, RBEV_RAISED2);
694 if (!RConvertImage(scr->rcontext, timg, languagebutton))
695 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
697 x += timg->width;
698 w -= timg->width;
699 RReleaseImage(timg);
701 #endif
703 if (right)
704 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
705 else
706 rimg = NULL;
708 if (rimg) {
709 RBevelImage(rimg, RBEV_RAISED2);
710 if (!RConvertImage(scr->rcontext, rimg, rbutton))
711 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
713 w -= rimg->width;
714 RReleaseImage(rimg);
717 if (w != width) {
718 mimg = RGetSubImage(img, x, 0, w, img->height);
719 RBevelImage(mimg, RBEV_RAISED2);
721 if (!RConvertImage(scr->rcontext, mimg, title))
722 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
724 RReleaseImage(mimg);
725 } else {
726 RBevelImage(img, RBEV_RAISED2);
728 if (!RConvertImage(scr->rcontext, img, title))
729 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
731 } else {
732 RBevelImage(img, RBEV_RAISED2);
734 if (!RConvertImage(scr->rcontext, img, title))
735 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
738 RReleaseImage(img);
741 static void
742 renderResizebarTexture(WScreen * scr, WTexture * texture, int width, int height, int cwidth, Pixmap * pmap)
744 RImage *img;
745 RColor light;
746 RColor dark;
748 *pmap = None;
750 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
751 if (!img) {
752 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
753 return;
756 light.alpha = 0;
757 light.red = light.green = light.blue = 80;
759 dark.alpha = 0;
760 dark.red = dark.green = dark.blue = 40;
762 ROperateLine(img, RSubtractOperation, 0, 0, width - 1, 0, &dark);
763 ROperateLine(img, RAddOperation, 0, 1, width - 1, 1, &light);
765 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height - 1, &dark);
766 ROperateLine(img, RAddOperation, cwidth + 1, 2, cwidth + 1, height - 1, &light);
768 if (width > 1)
769 ROperateLine(img, RSubtractOperation, width - cwidth - 2, 2,
770 width - cwidth - 2, height - 1, &dark);
771 ROperateLine(img, RAddOperation, width - cwidth - 1, 2, width - cwidth - 1, height - 1, &light);
773 #ifdef SHADOW_RESIZEBAR
774 ROperateLine(img, RAddOperation, 0, 1, 0, height - 1, &light);
775 ROperateLine(img, RSubtractOperation, width - 1, 1, width - 1, height - 1, &dark);
776 ROperateLine(img, RSubtractOperation, 0, height - 1, width - 1, height - 1, &dark);
777 #endif /* SHADOW_RESIZEBAR */
779 if (!RConvertImage(scr->rcontext, img, pmap))
780 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
782 RReleaseImage(img);
785 static void updateTexture(WFrameWindow * fwin)
787 int i;
788 unsigned long pixel;
790 i = fwin->flags.state;
791 if (fwin->titlebar) {
792 if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
793 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window, fwin->title_back[i]);
794 if (wPreferences.new_style == TS_NEW) {
795 if (fwin->left_button && fwin->lbutton_back[i])
796 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
797 fwin->lbutton_back[i]);
799 #ifdef XKB_BUTTON_HINT
800 if (fwin->language_button && fwin->languagebutton_back[i])
801 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
802 fwin->languagebutton_back[i]);
803 #endif
805 if (fwin->right_button && fwin->rbutton_back[i])
806 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
807 fwin->rbutton_back[i]);
809 } else {
810 pixel = fwin->title_texture[i]->solid.normal.pixel;
811 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
812 if (wPreferences.new_style == TS_NEW) {
813 if (fwin->left_button)
814 XSetWindowBackground(dpy, fwin->left_button->window, pixel);
815 #ifdef XKB_BUTTON_HINT
816 if (fwin->language_button)
817 XSetWindowBackground(dpy, fwin->language_button->window, pixel);
818 #endif
819 if (fwin->right_button)
820 XSetWindowBackground(dpy, fwin->right_button->window, pixel);
823 XClearWindow(dpy, fwin->titlebar->window);
825 if (fwin->left_button) {
826 XClearWindow(dpy, fwin->left_button->window);
827 handleButtonExpose(&fwin->left_button->descriptor, NULL);
829 #ifdef XKB_BUTTON_HINT
830 if (fwin->language_button) {
831 XClearWindow(dpy, fwin->language_button->window);
832 handleButtonExpose(&fwin->language_button->descriptor, NULL);
834 #endif
835 if (fwin->right_button) {
836 XClearWindow(dpy, fwin->right_button->window);
837 handleButtonExpose(&fwin->right_button->descriptor, NULL);
842 static void remakeTexture(WFrameWindow * fwin, int state)
844 Pixmap pmap, lpmap, rpmap;
845 #ifdef XKB_BUTTON_HINT
846 Pixmap tpmap;
847 #endif
849 if (fwin->title_texture[state] && fwin->titlebar) {
850 FREE_PIXMAP(fwin->title_back[state]);
851 if (wPreferences.new_style == TS_NEW) {
852 FREE_PIXMAP(fwin->lbutton_back[state]);
853 FREE_PIXMAP(fwin->rbutton_back[state]);
854 #ifdef XKB_BUTTON_HINT
855 FREE_PIXMAP(fwin->languagebutton_back[state]);
856 #endif
859 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
860 int left, right;
861 int width;
862 #ifdef XKB_BUTTON_HINT
863 int language;
864 #endif
866 /* eventually surrounded by if new_style */
867 left = fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit;
868 #ifdef XKB_BUTTON_HINT
869 language = fwin->language_button && !fwin->flags.hide_language_button
870 && !fwin->flags.languagebutton_dont_fit;
871 #endif
872 right = fwin->right_button && !fwin->flags.hide_right_button
873 && !fwin->flags.rbutton_dont_fit;
875 width = fwin->core->width + 1;
877 #ifdef XKB_BUTTON_HINT
878 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
879 width, fwin->titlebar->height,
880 fwin->titlebar->height, fwin->titlebar->height,
881 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
882 #else
883 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
884 width, fwin->titlebar->height,
885 fwin->titlebar->height, fwin->titlebar->height,
886 left, right, &pmap, &lpmap, &rpmap);
887 #endif
889 fwin->title_back[state] = pmap;
890 if (wPreferences.new_style == TS_NEW) {
891 fwin->lbutton_back[state] = lpmap;
892 fwin->rbutton_back[state] = rpmap;
893 #ifdef XKB_BUTTON_HINT
894 fwin->languagebutton_back[state] = tpmap;
895 #endif
899 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
900 && fwin->resizebar && state == 0) {
902 FREE_PIXMAP(fwin->resizebar_back[0]);
904 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
906 renderResizebarTexture(fwin->screen_ptr,
907 fwin->resizebar_texture[0],
908 fwin->resizebar->width,
909 fwin->resizebar->height, fwin->resizebar_corner_width, &pmap);
911 fwin->resizebar_back[0] = pmap;
914 /* this part should be in updateTexture() */
915 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID)
916 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
917 else
918 XSetWindowBackground(dpy, fwin->resizebar->window,
919 fwin->resizebar_texture[0]->solid.normal.pixel);
921 XClearWindow(dpy, fwin->resizebar->window);
925 void wFrameWindowPaint(WFrameWindow * fwin)
927 WScreen *scr = fwin->screen_ptr;
928 int state;
930 state = fwin->flags.state;
932 if (fwin->flags.is_client_window_frame)
933 fwin->flags.justification = wPreferences.title_justification;
935 if (fwin->flags.need_texture_remake) {
936 int i;
938 fwin->flags.need_texture_remake = 0;
939 fwin->flags.need_texture_change = 0;
941 if (fwin->flags.single_texture) {
942 remakeTexture(fwin, 0);
943 updateTexture(fwin);
944 } else {
945 /* first render the texture for the current state... */
946 remakeTexture(fwin, state);
947 /* ... and paint it */
948 updateTexture(fwin);
950 for (i = 0; i < 3; i++) {
951 if (i != state)
952 remakeTexture(fwin, i);
957 if (fwin->flags.need_texture_change) {
958 fwin->flags.need_texture_change = 0;
960 updateTexture(fwin);
963 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
964 && fwin->title_texture[state]->any.type == WTEX_SOLID) {
965 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
966 fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
969 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
970 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
971 Window win;
972 int w, h;
973 int cw;
974 GC light_gc, dim_gc;
975 WTexSolid *texture = (WTexSolid *) fwin->resizebar_texture[0];
977 w = fwin->resizebar->width;
978 h = fwin->resizebar->height;
979 cw = fwin->resizebar_corner_width;
980 light_gc = texture->light_gc;
981 dim_gc = texture->dim_gc;
982 win = fwin->resizebar->window;
984 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
985 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
987 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
988 XDrawLine(dpy, win, light_gc, cw + 1, 2, cw + 1, h);
990 XDrawLine(dpy, win, dim_gc, w - cw - 2, 2, w - cw - 2, h);
991 XDrawLine(dpy, win, light_gc, w - cw - 1, 2, w - cw - 1, h);
993 #ifdef SHADOW_RESIZEBAR
994 XDrawLine(dpy, win, light_gc, 0, 1, 0, h - 1);
995 XDrawLine(dpy, win, dim_gc, w - 1, 2, w - 1, h - 1);
996 XDrawLine(dpy, win, dim_gc, 1, h - 1, cw, h - 1);
997 XDrawLine(dpy, win, dim_gc, cw + 2, h - 1, w - cw - 2, h - 1);
998 XDrawLine(dpy, win, dim_gc, w - cw, h - 1, w - 1, h - 1);
999 #endif /* SHADOW_RESIZEBAR */
1002 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
1003 int x, y, w, h;
1004 int lofs = 6, rofs = 6;
1005 int titlelen;
1006 int allButtons = 1;
1008 if (!wPreferences.new_style == TS_NEW) {
1009 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1010 lofs += fwin->left_button->width + 3;
1011 else
1012 allButtons = 0;
1014 #ifdef XKB_BUTTON_HINT
1015 if (fwin->language_button && !fwin->flags.hide_language_button
1016 && !fwin->flags.languagebutton_dont_fit)
1017 lofs += fwin->language_button->width;
1018 else
1019 allButtons = 0;
1020 #endif
1022 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1023 rofs += fwin->right_button->width + 3;
1024 else
1025 allButtons = 0;
1027 #ifdef XKB_BUTTON_HINT
1028 fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1029 #endif
1031 if (fwin->title) {
1032 Drawable buf;
1033 char *title;
1035 title = ShrinkString(*fwin->font, fwin->title, fwin->titlebar->width - lofs - rofs);
1036 titlelen = strlen(title);
1037 w = WMWidthOfString(*fwin->font, title, titlelen);
1039 switch (fwin->flags.justification) {
1040 case WTJ_LEFT:
1041 x = lofs;
1042 break;
1044 case WTJ_RIGHT:
1045 x = fwin->titlebar->width - w - rofs;
1046 break;
1048 default:
1049 if (!allButtons)
1050 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1051 else
1052 x = (fwin->titlebar->width - w) / 2;
1053 break;
1056 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1057 h = WMFontHeight(*fwin->font);
1059 if (y*2 + h > *fwin->title_max_height)
1060 y = (*fwin->title_max_height - h) / 2;
1062 if (y*2 + h < *fwin->title_min_height)
1063 y = (*fwin->title_min_height - h) / 2;
1065 /* We use a w+2 buffer to have an extra pixel on the left and
1066 * another one on the right. This is because for some odd reason,
1067 * sometimes when using AA fonts (when libfreetype2 is compiled
1068 * with bytecode interpreter turned off), some fonts are drawn
1069 * starting from x = -1 not from 0 as requested. Observed with
1070 * capital A letter on the bold 'trebuchet ms' font. -Dan
1072 buf = XCreatePixmap(dpy, fwin->titlebar->window, w + 2, h, scr->w_depth);
1074 XSetClipMask(dpy, scr->copy_gc, None);
1076 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
1077 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1078 x - 1, y, w + 2, h, 0, 0);
1079 } else {
1080 XSetForeground(dpy, scr->copy_gc, fwin->title_texture[state]->solid.normal.pixel);
1081 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w + 2, h);
1084 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1); */
1085 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1086 *fwin->font, 1, 0, title, titlelen);
1088 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc, 0, 0, w + 2, h, x - 1, y);
1090 XFreePixmap(dpy, buf);
1092 wfree(title);
1095 if (fwin->left_button)
1096 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1097 if (fwin->right_button)
1098 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1099 #ifdef XKB_BUTTON_HINT
1100 if (fwin->language_button)
1101 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1102 #endif
1106 static void reconfigure(WFrameWindow * fwin, int x, int y, int width, int height, Bool dontMove)
1108 int k = (wPreferences.new_style == TS_NEW ? 4 : 3);
1109 int resizedHorizontally = 0;
1111 if (dontMove)
1112 XResizeWindow(dpy, fwin->core->window, width, height);
1113 else
1114 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1116 if (fwin->core->width != width) {
1117 fwin->flags.need_texture_remake = 1;
1118 resizedHorizontally = 1;
1121 fwin->core->width = width;
1122 fwin->core->height = height;
1124 if (fwin->titlebar && resizedHorizontally) {
1125 /* Check if the titlebar is wide enough to hold the buttons.
1126 * Temporarily remove them if can't
1128 if (fwin->left_button) {
1129 if (width < fwin->top_width * k && !fwin->flags.lbutton_dont_fit) {
1130 if (!fwin->flags.hide_left_button)
1131 XUnmapWindow(dpy, fwin->left_button->window);
1133 fwin->flags.lbutton_dont_fit = 1;
1134 } else if (width >= fwin->top_width * k && fwin->flags.lbutton_dont_fit) {
1135 if (!fwin->flags.hide_left_button)
1136 XMapWindow(dpy, fwin->left_button->window);
1138 fwin->flags.lbutton_dont_fit = 0;
1141 #ifdef XKB_BUTTON_HINT
1142 if (fwin->language_button) {
1143 if (width < fwin->top_width * k && !fwin->flags.languagebutton_dont_fit) {
1144 if (!fwin->flags.hide_language_button)
1145 XUnmapWindow(dpy, fwin->language_button->window);
1147 fwin->flags.languagebutton_dont_fit = 1;
1148 } else if (width >= fwin->top_width * k && fwin->flags.languagebutton_dont_fit) {
1149 if (!fwin->flags.hide_language_button)
1150 XMapWindow(dpy, fwin->language_button->window);
1152 fwin->flags.languagebutton_dont_fit = 0;
1155 #endif
1157 if (fwin->right_button) {
1158 if (width < fwin->top_width * 2 && !fwin->flags.rbutton_dont_fit) {
1159 if (!fwin->flags.hide_right_button)
1160 XUnmapWindow(dpy, fwin->right_button->window);
1162 fwin->flags.rbutton_dont_fit = 1;
1163 } else if (width >= fwin->top_width * 2 && fwin->flags.rbutton_dont_fit) {
1164 if (!fwin->flags.hide_right_button)
1165 XMapWindow(dpy, fwin->right_button->window);
1167 fwin->flags.rbutton_dont_fit = 0;
1171 if (wPreferences.new_style == TS_NEW) {
1172 if (fwin->right_button)
1173 XMoveWindow(dpy, fwin->right_button->window,
1174 width - fwin->right_button->width + 1, 0);
1175 } else {
1176 if (fwin->right_button)
1177 XMoveWindow(dpy, fwin->right_button->window,
1178 width - fwin->right_button->width - 3,
1179 (fwin->titlebar->height - fwin->right_button->height) / 2);
1181 updateTitlebar(fwin);
1182 checkTitleSize(fwin);
1185 if (fwin->resizebar) {
1186 wCoreConfigure(fwin->resizebar, 0,
1187 fwin->core->height - fwin->resizebar->height,
1188 fwin->core->width, fwin->resizebar->height);
1190 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1191 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH)
1192 fwin->resizebar_corner_width = fwin->core->width / 2;
1196 void wFrameWindowConfigure(WFrameWindow * fwin, int x, int y, int width, int height)
1198 reconfigure(fwin, x, y, width, height, False);
1201 void wFrameWindowResize(WFrameWindow * fwin, int width, int height)
1203 reconfigure(fwin, 0, 0, width, height, True);
1206 int wFrameWindowChangeTitle(WFrameWindow *fwin, const char *new_title)
1208 /* check if the title is the same as before */
1209 if (fwin->title) {
1210 if (new_title && (strcmp(fwin->title, new_title) == 0))
1211 return 0;
1212 } else {
1213 if (!new_title)
1214 return 0;
1217 if (fwin->title)
1218 wfree(fwin->title);
1220 fwin->title = wstrdup(new_title);
1222 if (fwin->titlebar) {
1223 XClearWindow(dpy, fwin->titlebar->window);
1225 wFrameWindowPaint(fwin);
1227 checkTitleSize(fwin);
1229 return 1;
1232 #ifdef XKB_BUTTON_HINT
1233 void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
1235 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1236 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
1238 #endif /* XKB_BUTTON_HINT */
1240 /*********************************************************************/
1242 static void handleExpose(WObjDescriptor * desc, XEvent * event)
1244 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1246 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1247 fwin->flags.repaint_only_titlebar = 1;
1248 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1249 fwin->flags.repaint_only_resizebar = 1;
1250 wFrameWindowPaint(fwin);
1251 fwin->flags.repaint_only_titlebar = 0;
1252 fwin->flags.repaint_only_resizebar = 0;
1255 static void checkTitleSize(WFrameWindow * fwin)
1257 int width;
1259 if (!fwin->title) {
1260 fwin->flags.incomplete_title = 0;
1261 return;
1264 if (!fwin->titlebar) {
1265 fwin->flags.incomplete_title = 1;
1266 return;
1267 } else {
1268 width = fwin->titlebar->width - 6 - 6;
1271 if (!wPreferences.new_style == TS_NEW) {
1272 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1273 width -= fwin->left_button->width + 3;
1275 #ifdef XKB_BUTTON_HINT
1276 if (fwin->language_button && !fwin->flags.hide_language_button
1277 && !fwin->flags.languagebutton_dont_fit)
1278 width -= fwin->language_button->width + 3;
1279 #endif
1281 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1282 width -= fwin->right_button->width + 3;
1285 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width)
1286 fwin->flags.incomplete_title = 1;
1287 else
1288 fwin->flags.incomplete_title = 0;
1291 static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
1293 WScreen *scr = button->screen_ptr;
1294 GC copy_gc = scr->copy_gc;
1295 int x = 0, y = 0, d = 0;
1296 int left = 0, width = 0;
1298 /* setup stuff according to the state */
1299 if (pushed) {
1300 if (image) {
1301 if (image->width >= image->height * 2) {
1302 /* the image contains 2 pictures: the second is for the
1303 * pushed state */
1304 width = image->width / 2;
1305 left = image->width / 2;
1306 } else {
1307 width = image->width;
1310 XSetClipMask(dpy, copy_gc, None);
1311 if (wPreferences.new_style == TS_NEXT)
1312 XSetForeground(dpy, copy_gc, scr->black_pixel);
1313 else
1314 XSetForeground(dpy, copy_gc, scr->white_pixel);
1316 d = 1;
1317 if (wPreferences.new_style == TS_NEW) {
1318 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1319 XSetForeground(dpy, copy_gc, scr->black_pixel);
1320 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1321 } else if (wPreferences.new_style == TS_OLD) {
1322 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1323 XSetForeground(dpy, copy_gc, scr->black_pixel);
1324 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1325 } else {
1326 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1327 XSetForeground(dpy, copy_gc, scr->black_pixel);
1328 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1330 } else {
1331 XClearWindow(dpy, button->window);
1333 if (image) {
1334 if (image->width >= image->height * 2)
1335 width = image->width / 2;
1336 else
1337 width = image->width;
1339 d = 0;
1341 if (wPreferences.new_style == TS_NEW) {
1342 if (texture->any.type == WTEX_SOLID || pushed)
1343 wDrawBevel(button->window, button->width, button->height,
1344 (WTexSolid *) texture, WREL_RAISED);
1345 } else {
1346 wDrawBevel(button->window, button->width, button->height,
1347 scr->widget_texture, WREL_RAISED);
1351 if (image) {
1352 /* display image */
1353 XSetClipMask(dpy, copy_gc, image->mask);
1354 x = (button->width - width) / 2 + d;
1355 y = (button->height - image->height) / 2 + d;
1356 XSetClipOrigin(dpy, copy_gc, x - left, y);
1357 if (!wPreferences.new_style == TS_NEW) {
1358 XSetForeground(dpy, copy_gc, scr->black_pixel);
1359 if (!pushed) {
1360 if (image->depth == 1)
1361 XCopyPlane(dpy, image->image, button->window, copy_gc,
1362 left, 0, width, image->height, x, y, 1);
1363 else
1364 XCopyArea(dpy, image->image, button->window, copy_gc,
1365 left, 0, width, image->height, x, y);
1366 } else {
1367 if (wPreferences.new_style == TS_OLD) {
1368 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1369 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1370 button->width, button->height);
1371 } else {
1372 XSetForeground(dpy, copy_gc, scr->black_pixel);
1373 XCopyArea(dpy, image->image, button->window, copy_gc,
1374 left, 0, width, image->height, x, y);
1377 } else {
1378 if (pushed) {
1379 XSetForeground(dpy, copy_gc, scr->black_pixel);
1380 } else {
1381 XSetForeground(dpy, copy_gc, color);
1382 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1384 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1389 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
1391 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1392 WCoreWindow *button = (WCoreWindow *) desc->self;
1394 /* Parameter not used, but tell the compiler that it is ok */
1395 (void) event;
1397 #ifdef XKB_BUTTON_HINT
1398 if (button == fwin->language_button) {
1399 if (wPreferences.modelock)
1400 paintButton(button, fwin->title_texture[fwin->flags.state],
1401 WMColorPixel(fwin->title_color[fwin->flags.state]),
1402 fwin->languagebutton_image, False);
1403 } else
1404 #endif
1405 if (button == fwin->left_button)
1406 paintButton(button, fwin->title_texture[fwin->flags.state],
1407 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
1408 else
1409 paintButton(button, fwin->title_texture[fwin->flags.state],
1410 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
1413 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
1415 WFrameWindow *fwin = desc->parent;
1416 WCoreWindow *titlebar = desc->self;
1418 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1419 if (fwin->on_dblclick_titlebar)
1420 (*fwin->on_dblclick_titlebar) (titlebar, fwin->child, event);
1421 } else {
1422 if (fwin->on_mousedown_titlebar)
1423 (*fwin->on_mousedown_titlebar) (titlebar, fwin->child, event);
1427 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event)
1429 WFrameWindow *fwin = desc->parent;
1430 WCoreWindow *resizebar = desc->self;
1432 if (fwin->on_mousedown_resizebar)
1433 (*fwin->on_mousedown_resizebar) (resizebar, fwin->child, event);
1436 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
1438 WFrameWindow *fwin = desc->parent;
1439 WCoreWindow *button = desc->self;
1440 WPixmap *image;
1441 XEvent ev;
1442 int done = 0, execute = 1;
1443 WTexture *texture;
1444 unsigned long pixel;
1445 int clickButton = event->xbutton.button;
1447 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1448 if (button == fwin->right_button && fwin->on_dblclick_right)
1449 (*fwin->on_dblclick_right) (button, fwin->child, event);
1451 return;
1454 if (button == fwin->left_button)
1455 image = fwin->lbutton_image;
1456 else
1457 image = fwin->rbutton_image;
1459 #ifdef XKB_BUTTON_HINT
1460 if (button == fwin->language_button) {
1461 if (!wPreferences.modelock)
1462 return;
1463 image = fwin->languagebutton_image;
1465 #endif
1467 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1468 texture = fwin->title_texture[fwin->flags.state];
1469 paintButton(button, texture, pixel, image, True);
1471 while (!done) {
1472 WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
1473 | ButtonPressMask | ExposureMask, &ev);
1474 switch (ev.type) {
1475 case LeaveNotify:
1476 execute = 0;
1477 paintButton(button, texture, pixel, image, False);
1478 break;
1480 case EnterNotify:
1481 execute = 1;
1482 paintButton(button, texture, pixel, image, True);
1483 break;
1485 case ButtonPress:
1486 break;
1488 case ButtonRelease:
1489 if (ev.xbutton.button == clickButton)
1490 done = 1;
1491 break;
1493 default:
1494 WMHandleEvent(&ev);
1497 paintButton(button, texture, pixel, image, False);
1499 if (execute) {
1500 if (button == fwin->left_button) {
1501 if (fwin->on_click_left)
1502 (*fwin->on_click_left) (button, fwin->child, &ev);
1503 } else if (button == fwin->right_button) {
1504 if (fwin->on_click_right)
1505 (*fwin->on_click_right) (button, fwin->child, &ev);
1507 #ifdef XKB_BUTTON_HINT
1508 else if (button == fwin->language_button) {
1509 if (fwin->on_click_language)
1510 (*fwin->on_click_language) (button, fwin->child, &ev);
1512 #endif