wmaker: Changed math on floating point by integer operation
[wmaker-crm.git] / src / framewin.c
blobdb0d98803af232c8e9b58191d704b2f1e7725a22
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
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);
59 static void paintButton(WCoreWindow * button, WTexture * texture,
60 unsigned long color, WPixmap * image, int pushed);
62 static void updateTitlebar(WFrameWindow * fwin);
64 static void allocFrameBorderPixel(Colormap colormap, const char *color_name, unsigned long **pixel);
66 static void allocFrameBorderPixel(Colormap colormap, const char *color_name, unsigned long **pixel) {
67 XColor xcol;
69 *pixel = NULL;
71 if (! wGetColorForColormap(colormap, color_name, &xcol))
72 return;
74 *pixel = wmalloc(sizeof(unsigned long));
75 if (*pixel)
76 **pixel = xcol.pixel;
79 WFrameWindow *wFrameWindowCreate(WScreen * scr, int wlevel, int x, int y,
80 int width, int height, int *clearance,
81 int *title_min, int *title_max, int flags,
82 WTexture ** title_texture, WTexture ** resize_texture,
83 WMColor ** color, WMFont ** font,
84 int depth, Visual *visual, Colormap colormap)
86 WFrameWindow *fwin;
88 fwin = wmalloc(sizeof(WFrameWindow));
90 fwin->screen_ptr = scr;
92 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
94 fwin->title_texture = title_texture;
95 fwin->resizebar_texture = resize_texture;
96 fwin->title_color = color;
97 fwin->title_clearance = clearance;
98 fwin->title_min_height = title_min;
99 fwin->title_max_height = title_max;
100 fwin->font = font;
101 #ifdef KEEP_XKB_LOCK_STATUS
102 fwin->languagemode = XkbGroup1Index;
103 fwin->last_languagemode = XkbGroup2Index;
104 #endif
106 fwin->depth = depth;
107 fwin->visual = visual;
108 fwin->colormap = colormap;
110 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height, (flags & WFF_BORDER)
111 ? scr->frame_border_width : 0, fwin->depth, fwin->visual, fwin->colormap, scr->frame_border_pixel);
113 /* setup stacking information */
114 fwin->core->stacking = wmalloc(sizeof(WStacking));
115 fwin->core->stacking->above = NULL;
116 fwin->core->stacking->under = NULL;
117 fwin->core->stacking->child_of = NULL;
118 fwin->core->stacking->window_level = wlevel;
120 AddToStackList(fwin->core);
122 wFrameWindowUpdateBorders(fwin, flags);
124 return fwin;
127 void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
129 int theight;
130 int bsize;
131 int width, height;
132 int i;
133 WScreen *scr = fwin->screen_ptr;
135 width = fwin->core->width;
136 if (flags & WFF_IS_SHADED)
137 height = -1;
138 else
139 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
141 if (flags & WFF_TITLEBAR) {
142 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
144 if (theight > *fwin->title_max_height)
145 theight = *fwin->title_max_height;
147 if (theight < *fwin->title_min_height)
148 theight = *fwin->title_min_height;
149 } else {
150 theight = 0;
153 if (wPreferences.new_style == TS_NEW) {
154 bsize = theight;
155 } else if (wPreferences.new_style == TS_OLD) {
156 bsize = theight - 7;
157 } else {
158 bsize = theight - 8;
161 if (fwin->titlebar) {
162 /* if we had a titlebar and is requesting for one,
163 * check if the size has changed and resize it */
164 if (flags & WFF_TITLEBAR) {
165 fwin->top_width = theight;
167 fwin->flags.need_texture_remake = 1;
169 if (wPreferences.new_style == TS_NEW) {
170 if (fwin->left_button)
171 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
172 #ifdef XKB_BUTTON_HINT
173 if (fwin->language_button) {
174 if (fwin->flags.hide_left_button || !fwin->left_button
175 || fwin->flags.lbutton_dont_fit)
176 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
177 else
178 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
180 #endif
182 if (fwin->right_button)
183 wCoreConfigure(fwin->right_button, width - bsize + 1, 0, bsize, bsize);
185 } else { /* !new_style */
186 if (fwin->left_button)
187 wCoreConfigure(fwin->left_button, 3, (theight - bsize) / 2, bsize, bsize);
188 #ifdef XKB_BUTTON_HINT
189 if (fwin->language_button)
190 wCoreConfigure(fwin->language_button, 6 + bsize, (theight - bsize) / 2,
191 bsize, bsize);
192 #endif
194 if (fwin->right_button)
195 wCoreConfigure(fwin->right_button, width - bsize - 3,
196 (theight - bsize) / 2, bsize, bsize);
198 updateTitlebar(fwin);
199 } else {
200 /* we had a titlebar, but now we don't need it anymore */
201 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
202 FREE_PIXMAP(fwin->title_back[i]);
203 if (wPreferences.new_style == TS_NEW) {
204 FREE_PIXMAP(fwin->lbutton_back[i]);
205 FREE_PIXMAP(fwin->rbutton_back[i]);
206 #ifdef XKB_BUTTON_HINT
207 FREE_PIXMAP(fwin->languagebutton_back[i]);
208 #endif
211 if (fwin->left_button)
212 wCoreDestroy(fwin->left_button);
213 fwin->left_button = NULL;
215 #ifdef XKB_BUTTON_HINT
216 if (fwin->language_button)
217 wCoreDestroy(fwin->language_button);
218 fwin->language_button = NULL;
219 #endif
221 if (fwin->right_button)
222 wCoreDestroy(fwin->right_button);
223 fwin->right_button = NULL;
225 wCoreDestroy(fwin->titlebar);
226 fwin->titlebar = NULL;
228 fwin->top_width = 0;
230 } else {
231 /* if we didn't have a titlebar and are being requested for
232 * one, create it */
233 if (flags & WFF_TITLEBAR) {
234 fwin->top_width = theight;
236 fwin->flags.titlebar = 1;
237 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width + 1, theight);
239 if (flags & WFF_LEFT_BUTTON) {
240 fwin->flags.left_button = 1;
241 if (wPreferences.new_style == TS_NEW) {
242 fwin->left_button = wCoreCreate(fwin->core, 0, 0, bsize, bsize);
244 if (width < theight * 4)
245 fwin->flags.lbutton_dont_fit = 1;
246 else
247 XMapRaised(dpy, fwin->left_button->window);
249 } else if (wPreferences.new_style == TS_OLD) {
250 fwin->left_button =
251 wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
253 XSetWindowBackground(dpy, fwin->left_button->window,
254 scr->widget_texture->normal.pixel);
256 if (width < theight * 3)
257 fwin->flags.lbutton_dont_fit = 1;
258 else
259 XMapRaised(dpy, fwin->left_button->window);
261 } else {
262 fwin->left_button =
263 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
264 bsize, bsize);
266 XSetWindowBackground(dpy, fwin->left_button->window,
267 scr->widget_texture->dark.pixel);
269 if (width < theight * 3)
270 fwin->flags.lbutton_dont_fit = 1;
271 else
272 XMapRaised(dpy, fwin->left_button->window);
276 #ifdef XKB_BUTTON_HINT
277 if (flags & WFF_LANGUAGE_BUTTON) {
278 fwin->flags.language_button = 1;
279 if (wPreferences.new_style == TS_NEW) {
280 fwin->language_button = wCoreCreate(fwin->core, bsize, 0, bsize, bsize);
282 if (width < theight * 4)
283 fwin->flags.languagebutton_dont_fit = 1;
284 else
285 XMapRaised(dpy, fwin->language_button->window);
286 } else {
287 fwin->language_button =
288 wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
289 bsize, bsize);
291 XSetWindowBackground(dpy, fwin->language_button->window,
292 scr->widget_texture->normal.pixel);
294 if (width < theight * 3)
295 fwin->flags.languagebutton_dont_fit = 1;
296 else
297 XMapRaised(dpy, fwin->language_button->window);
300 #endif
302 if (flags & WFF_RIGHT_BUTTON) {
303 fwin->flags.right_button = 1;
304 if (wPreferences.new_style == TS_NEW) {
305 fwin->right_button =
306 wCoreCreate(fwin->core, width - bsize + 1, 0, bsize, bsize);
307 } else if (wPreferences.new_style == TS_OLD) {
308 fwin->right_button =
309 wCoreCreate(fwin->titlebar, width - bsize - 3,
310 (theight - bsize) / 2, bsize, bsize);
311 XSetWindowBackground(dpy, fwin->right_button->window,
312 scr->widget_texture->normal.pixel);
313 } else {
314 fwin->right_button =
315 wCoreCreate(fwin->titlebar, width-bsize-3,
316 (theight-bsize)/2, bsize, bsize);
317 XSetWindowBackground(dpy, fwin->right_button->window,
318 scr->widget_texture->dark.pixel);
321 if (width < theight * 2)
322 fwin->flags.rbutton_dont_fit = 1;
323 else
324 XMapRaised(dpy, fwin->right_button->window);
327 if (wPreferences.new_style == TS_NEW)
328 updateTitlebar(fwin);
330 XMapRaised(dpy, fwin->titlebar->window);
332 fwin->flags.need_texture_remake = 1;
335 checkTitleSize(fwin);
337 if (flags & WFF_RESIZEBAR) {
338 fwin->bottom_width = RESIZEBAR_HEIGHT;
340 if (!fwin->resizebar) {
341 fwin->flags.resizebar = 1;
342 fwin->resizebar = wCoreCreate(fwin->core, 0,
343 height + fwin->top_width, width, RESIZEBAR_HEIGHT);
344 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
345 if (width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
346 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH) / 2;
347 if (fwin->resizebar_corner_width < 0)
348 fwin->resizebar_corner_width = 0;
351 XMapWindow(dpy, fwin->resizebar->window);
352 XLowerWindow(dpy, fwin->resizebar->window);
354 fwin->flags.need_texture_remake = 1;
355 } else {
356 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height)
357 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
358 width, RESIZEBAR_HEIGHT);
360 } else {
361 fwin->bottom_width = 0;
363 if (fwin->resizebar) {
364 fwin->bottom_width = 0;
365 wCoreDestroy(fwin->resizebar);
366 fwin->resizebar = NULL;
370 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED))
371 wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
373 if (flags & WFF_BORDER)
374 XSetWindowBorderWidth(dpy, fwin->core->window, scr->frame_border_width);
375 else
376 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
378 /* setup object descriptors */
379 if (fwin->titlebar) {
380 fwin->titlebar->descriptor.handle_expose = handleExpose;
381 fwin->titlebar->descriptor.parent = fwin;
382 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
383 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
386 if (fwin->resizebar) {
387 fwin->resizebar->descriptor.handle_expose = handleExpose;
388 fwin->resizebar->descriptor.parent = fwin;
389 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
390 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
393 if (fwin->left_button) {
394 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
395 fwin->left_button->descriptor.parent = fwin;
396 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
397 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
400 #ifdef XKB_BUTTON_HINT
401 if (fwin->language_button) {
402 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
403 fwin->language_button->descriptor.parent = fwin;
404 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
405 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
407 #endif
409 if (fwin->right_button) {
410 fwin->right_button->descriptor.parent = fwin;
411 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
412 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
413 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
416 checkTitleSize(fwin);
418 allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_border_color), &fwin->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->border_pixel)
427 XSetWindowBorder(dpy, fwin->core->window, *fwin->border_pixel);
431 void wFrameWindowDestroy(WFrameWindow * fwin)
433 int i;
435 if (fwin->left_button)
436 wCoreDestroy(fwin->left_button);
438 #ifdef XKB_BUTTON_HINT
439 if (fwin->language_button)
440 wCoreDestroy(fwin->language_button);
441 #endif
443 if (fwin->right_button)
444 wCoreDestroy(fwin->right_button);
446 if (fwin->resizebar)
447 wCoreDestroy(fwin->resizebar);
449 if (fwin->titlebar)
450 wCoreDestroy(fwin->titlebar);
452 RemoveFromStackList(fwin->core);
454 wCoreDestroy(fwin->core);
456 if (fwin->title)
457 wfree(fwin->title);
459 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
460 FREE_PIXMAP(fwin->title_back[i]);
461 if (wPreferences.new_style == TS_NEW) {
462 FREE_PIXMAP(fwin->lbutton_back[i]);
463 #ifdef XKB_BUTTON_HINT
464 FREE_PIXMAP(fwin->languagebutton_back[i]);
465 #endif
466 FREE_PIXMAP(fwin->rbutton_back[i]);
470 wfree(fwin);
473 void wFrameWindowChangeState(WFrameWindow * fwin, int state)
475 if (fwin->flags.state == state)
476 return;
478 fwin->flags.state = state;
479 fwin->flags.need_texture_change = 1;
481 wFrameWindowPaint(fwin);
484 static void updateTitlebar(WFrameWindow * fwin)
486 int x, w;
487 int theight;
489 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
491 if (theight > *fwin->title_max_height)
492 theight = *fwin->title_max_height;
494 if (theight < *fwin->title_min_height)
495 theight = *fwin->title_min_height;
497 x = 0;
498 w = fwin->core->width + 1;
500 if (wPreferences.new_style == TS_NEW) {
501 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
502 x = 0;
503 #ifdef XKB_BUTTON_HINT
504 if (fwin->language_button)
505 wCoreConfigure(fwin->language_button, 0, 0,
506 fwin->language_button->width, fwin->language_button->width);
507 #endif
508 } else {
509 #ifdef XKB_BUTTON_HINT
510 if (fwin->language_button)
511 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
512 fwin->language_button->width, fwin->language_button->width);
513 #endif
514 x = fwin->left_button->width;
515 w -= fwin->left_button->width;
517 #ifdef XKB_BUTTON_HINT
518 if (fwin->flags.hide_language_button || !fwin->language_button
519 || fwin->flags.languagebutton_dont_fit) {
520 } else {
521 x += fwin->language_button->width;
522 w -= fwin->language_button->width;
524 #endif
526 #ifdef XKB_BUTTON_HINT
527 else {
528 int bsize = theight - 7;
529 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
530 if (fwin->language_button)
531 wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
532 fwin->language_button->width, fwin->language_button->width);
533 } else {
534 if (fwin->language_button)
535 wCoreConfigure(fwin->language_button,
536 6 + fwin->left_button->width, (theight - bsize) / 2,
537 fwin->language_button->width, fwin->language_button->width);
540 #endif
542 if (wPreferences.new_style == TS_NEW) {
543 if (!fwin->flags.hide_right_button && fwin->right_button && !fwin->flags.rbutton_dont_fit)
544 w -= fwin->right_button->width;
547 if (wPreferences.new_style == TS_NEW || fwin->titlebar->width != w)
548 fwin->flags.need_texture_remake = 1;
550 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
553 void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
555 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
556 XUnmapWindow(dpy, fwin->right_button->window);
557 fwin->flags.hide_right_button = 1;
560 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
561 XUnmapWindow(dpy, fwin->left_button->window);
562 fwin->flags.hide_left_button = 1;
564 #ifdef XKB_BUTTON_HINT
565 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
566 XUnmapWindow(dpy, fwin->language_button->window);
567 fwin->flags.hide_language_button = 1;
569 #endif
571 if (fwin->titlebar) {
572 if (wPreferences.new_style == TS_NEW) {
573 updateTitlebar(fwin);
574 } else {
575 #ifdef XKB_BUTTON_HINT
576 updateTitlebar(fwin);
577 #else
578 XClearWindow(dpy, fwin->titlebar->window);
579 wFrameWindowPaint(fwin);
580 #endif
582 checkTitleSize(fwin);
586 void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
588 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
590 if (!fwin->flags.rbutton_dont_fit)
591 XMapWindow(dpy, fwin->right_button->window);
593 fwin->flags.hide_right_button = 0;
595 #ifdef XKB_BUTTON_HINT
596 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
598 if (!fwin->flags.languagebutton_dont_fit)
599 XMapWindow(dpy, fwin->language_button->window);
601 fwin->flags.hide_language_button = 0;
603 #endif
605 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
607 if (!fwin->flags.lbutton_dont_fit)
608 XMapWindow(dpy, fwin->left_button->window);
610 fwin->flags.hide_left_button = 0;
613 if (fwin->titlebar) {
614 if (wPreferences.new_style == TS_NEW) {
615 updateTitlebar(fwin);
616 } else {
617 XClearWindow(dpy, fwin->titlebar->window);
618 wFrameWindowPaint(fwin);
620 checkTitleSize(fwin);
624 static void
625 #ifdef XKB_BUTTON_HINT
626 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
627 int bwidth, int bheight, int left, int language, int right,
628 Pixmap * title, Pixmap * lbutton, Pixmap * languagebutton, Pixmap * rbutton)
629 #else
630 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
631 int bwidth, int bheight, int left, int right, Pixmap * title, Pixmap * lbutton, Pixmap * rbutton)
632 #endif
634 RImage *img;
635 RImage *limg, *rimg, *mimg;
636 #ifdef XKB_BUTTON_HINT
637 RImage *timg;
638 #endif
639 int x, w;
641 *title = None;
642 *lbutton = None;
643 *rbutton = None;
644 #ifdef XKB_BUTTON_HINT
645 *languagebutton = None;
646 #endif
648 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
649 if (!img) {
650 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
651 return;
654 if (wPreferences.new_style == TS_NEW) {
655 if (left)
656 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
657 else
658 limg = NULL;
660 x = 0;
661 w = img->width;
663 #ifdef XKB_BUTTON_HINT
664 if (language)
665 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
666 else
667 timg = NULL;
668 #endif
670 if (limg) {
671 RBevelImage(limg, RBEV_RAISED2);
672 if (!RConvertImage(scr->rcontext, limg, lbutton))
673 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
675 x += limg->width;
676 w -= limg->width;
677 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));
719 } else {
720 RBevelImage(img, RBEV_RAISED2);
722 if (!RConvertImage(scr->rcontext, img, title))
723 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
726 RReleaseImage(img);
729 static void
730 renderResizebarTexture(WScreen * scr, WTexture * texture, int width, int height, int cwidth, Pixmap * pmap)
732 RImage *img;
733 RColor light;
734 RColor dark;
736 *pmap = None;
738 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
739 if (!img) {
740 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
741 return;
744 light.alpha = 0;
745 light.red = light.green = light.blue = 80;
747 dark.alpha = 0;
748 dark.red = dark.green = dark.blue = 40;
750 ROperateLine(img, RSubtractOperation, 0, 0, width - 1, 0, &dark);
751 ROperateLine(img, RAddOperation, 0, 1, width - 1, 1, &light);
753 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height - 1, &dark);
754 ROperateLine(img, RAddOperation, cwidth + 1, 2, cwidth + 1, height - 1, &light);
756 if (width > 1)
757 ROperateLine(img, RSubtractOperation, width - cwidth - 2, 2,
758 width - cwidth - 2, height - 1, &dark);
759 ROperateLine(img, RAddOperation, width - cwidth - 1, 2, width - cwidth - 1, height - 1, &light);
761 #ifdef SHADOW_RESIZEBAR
762 ROperateLine(img, RAddOperation, 0, 1, 0, height - 1, &light);
763 ROperateLine(img, RSubtractOperation, width - 1, 1, width - 1, height - 1, &dark);
764 ROperateLine(img, RSubtractOperation, 0, height - 1, width - 1, height - 1, &dark);
765 #endif /* SHADOW_RESIZEBAR */
767 if (!RConvertImage(scr->rcontext, img, pmap))
768 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
770 RReleaseImage(img);
773 static void updateTexture(WFrameWindow * fwin)
775 int i;
776 unsigned long pixel;
778 i = fwin->flags.state;
779 if (fwin->titlebar) {
780 if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
781 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window, fwin->title_back[i]);
782 if (wPreferences.new_style == TS_NEW) {
783 if (fwin->left_button && fwin->lbutton_back[i])
784 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
785 fwin->lbutton_back[i]);
787 #ifdef XKB_BUTTON_HINT
788 if (fwin->language_button && fwin->languagebutton_back[i])
789 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
790 fwin->languagebutton_back[i]);
791 #endif
793 if (fwin->right_button && fwin->rbutton_back[i])
794 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
795 fwin->rbutton_back[i]);
797 } else {
798 pixel = fwin->title_texture[i]->solid.normal.pixel;
799 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
800 if (wPreferences.new_style == TS_NEW) {
801 if (fwin->left_button)
802 XSetWindowBackground(dpy, fwin->left_button->window, pixel);
803 #ifdef XKB_BUTTON_HINT
804 if (fwin->language_button)
805 XSetWindowBackground(dpy, fwin->language_button->window, pixel);
806 #endif
807 if (fwin->right_button)
808 XSetWindowBackground(dpy, fwin->right_button->window, pixel);
811 XClearWindow(dpy, fwin->titlebar->window);
813 if (fwin->left_button) {
814 XClearWindow(dpy, fwin->left_button->window);
815 handleButtonExpose(&fwin->left_button->descriptor, NULL);
817 #ifdef XKB_BUTTON_HINT
818 if (fwin->language_button) {
819 XClearWindow(dpy, fwin->language_button->window);
820 handleButtonExpose(&fwin->language_button->descriptor, NULL);
822 #endif
823 if (fwin->right_button) {
824 XClearWindow(dpy, fwin->right_button->window);
825 handleButtonExpose(&fwin->right_button->descriptor, NULL);
830 static void remakeTexture(WFrameWindow * fwin, int state)
832 Pixmap pmap, lpmap, rpmap;
833 #ifdef XKB_BUTTON_HINT
834 Pixmap tpmap;
835 #endif
837 if (fwin->title_texture[state] && fwin->titlebar) {
838 FREE_PIXMAP(fwin->title_back[state]);
839 if (wPreferences.new_style == TS_NEW) {
840 FREE_PIXMAP(fwin->lbutton_back[state]);
841 FREE_PIXMAP(fwin->rbutton_back[state]);
842 #ifdef XKB_BUTTON_HINT
843 FREE_PIXMAP(fwin->languagebutton_back[state]);
844 #endif
847 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
848 int left, right;
849 int width;
850 #ifdef XKB_BUTTON_HINT
851 int language;
852 #endif
854 /* eventually surrounded by if new_style */
855 left = fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit;
856 #ifdef XKB_BUTTON_HINT
857 language = fwin->language_button && !fwin->flags.hide_language_button
858 && !fwin->flags.languagebutton_dont_fit;
859 #endif
860 right = fwin->right_button && !fwin->flags.hide_right_button
861 && !fwin->flags.rbutton_dont_fit;
863 width = fwin->core->width + 1;
865 #ifdef XKB_BUTTON_HINT
866 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
867 width, fwin->titlebar->height,
868 fwin->titlebar->height, fwin->titlebar->height,
869 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
870 #else
871 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
872 width, fwin->titlebar->height,
873 fwin->titlebar->height, fwin->titlebar->height,
874 left, right, &pmap, &lpmap, &rpmap);
875 #endif
877 fwin->title_back[state] = pmap;
878 if (wPreferences.new_style == TS_NEW) {
879 fwin->lbutton_back[state] = lpmap;
880 fwin->rbutton_back[state] = rpmap;
881 #ifdef XKB_BUTTON_HINT
882 fwin->languagebutton_back[state] = tpmap;
883 #endif
887 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
888 && fwin->resizebar && state == 0) {
890 FREE_PIXMAP(fwin->resizebar_back[0]);
892 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
894 renderResizebarTexture(fwin->screen_ptr,
895 fwin->resizebar_texture[0],
896 fwin->resizebar->width,
897 fwin->resizebar->height, fwin->resizebar_corner_width, &pmap);
899 fwin->resizebar_back[0] = pmap;
902 /* this part should be in updateTexture() */
903 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID)
904 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
905 else
906 XSetWindowBackground(dpy, fwin->resizebar->window,
907 fwin->resizebar_texture[0]->solid.normal.pixel);
909 XClearWindow(dpy, fwin->resizebar->window);
913 void wFrameWindowPaint(WFrameWindow * fwin)
915 WScreen *scr = fwin->screen_ptr;
916 int state;
918 state = fwin->flags.state;
920 if (fwin->flags.is_client_window_frame)
921 fwin->flags.justification = wPreferences.title_justification;
923 if (fwin->flags.need_texture_remake) {
924 int i;
926 fwin->flags.need_texture_remake = 0;
927 fwin->flags.need_texture_change = 0;
929 if (fwin->flags.single_texture) {
930 remakeTexture(fwin, 0);
931 updateTexture(fwin);
932 } else {
933 /* first render the texture for the current state... */
934 remakeTexture(fwin, state);
935 /* ... and paint it */
936 updateTexture(fwin);
938 for (i = 0; i < 3; i++) {
939 if (i != state)
940 remakeTexture(fwin, i);
945 if (fwin->flags.need_texture_change) {
946 fwin->flags.need_texture_change = 0;
948 updateTexture(fwin);
951 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
952 && fwin->title_texture[state]->any.type == WTEX_SOLID) {
953 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
954 fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
957 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
958 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
959 Window win;
960 int w, h;
961 int cw;
962 GC light_gc, dim_gc;
963 WTexSolid *texture = (WTexSolid *) fwin->resizebar_texture[0];
965 w = fwin->resizebar->width;
966 h = fwin->resizebar->height;
967 cw = fwin->resizebar_corner_width;
968 light_gc = texture->light_gc;
969 dim_gc = texture->dim_gc;
970 win = fwin->resizebar->window;
972 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
973 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
975 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
976 XDrawLine(dpy, win, light_gc, cw + 1, 2, cw + 1, h);
978 XDrawLine(dpy, win, dim_gc, w - cw - 2, 2, w - cw - 2, h);
979 XDrawLine(dpy, win, light_gc, w - cw - 1, 2, w - cw - 1, h);
981 #ifdef SHADOW_RESIZEBAR
982 XDrawLine(dpy, win, light_gc, 0, 1, 0, h - 1);
983 XDrawLine(dpy, win, dim_gc, w - 1, 2, w - 1, h - 1);
984 XDrawLine(dpy, win, dim_gc, 1, h - 1, cw, h - 1);
985 XDrawLine(dpy, win, dim_gc, cw + 2, h - 1, w - cw - 2, h - 1);
986 XDrawLine(dpy, win, dim_gc, w - cw, h - 1, w - 1, h - 1);
987 #endif /* SHADOW_RESIZEBAR */
990 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
991 int x, y, w, h;
992 int lofs = 6, rofs = 6;
993 int titlelen;
994 int allButtons = 1;
996 if (!wPreferences.new_style == TS_NEW) {
997 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
998 lofs += fwin->left_button->width + 3;
999 else
1000 allButtons = 0;
1002 #ifdef XKB_BUTTON_HINT
1003 if (fwin->language_button && !fwin->flags.hide_language_button
1004 && !fwin->flags.languagebutton_dont_fit)
1005 lofs += fwin->language_button->width;
1006 else
1007 allButtons = 0;
1008 #endif
1010 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1011 rofs += fwin->right_button->width + 3;
1012 else
1013 allButtons = 0;
1015 #ifdef XKB_BUTTON_HINT
1016 fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1017 #endif
1019 if (fwin->title) {
1020 Drawable buf;
1021 char *title;
1023 title = ShrinkString(*fwin->font, fwin->title, fwin->titlebar->width - lofs - rofs);
1024 titlelen = strlen(title);
1025 w = WMWidthOfString(*fwin->font, title, titlelen);
1027 switch (fwin->flags.justification) {
1028 case WTJ_LEFT:
1029 x = lofs;
1030 break;
1032 case WTJ_RIGHT:
1033 x = fwin->titlebar->width - w - rofs;
1034 break;
1036 default:
1037 if (!allButtons)
1038 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1039 else
1040 x = (fwin->titlebar->width - w) / 2;
1041 break;
1044 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1045 h = WMFontHeight(*fwin->font);
1047 if (y*2 + h > *fwin->title_max_height)
1048 y = (*fwin->title_max_height - h) / 2;
1050 if (y*2 + h < *fwin->title_min_height)
1051 y = (*fwin->title_min_height - h) / 2;
1053 /* We use a w+2 buffer to have an extra pixel on the left and
1054 * another one on the right. This is because for some odd reason,
1055 * sometimes when using AA fonts (when libfreetype2 is compiled
1056 * with bytecode interpreter turned off), some fonts are drawn
1057 * starting from x = -1 not from 0 as requested. Observed with
1058 * capital A letter on the bold 'trebuchet ms' font. -Dan
1060 buf = XCreatePixmap(dpy, fwin->titlebar->window, w + 2, h, scr->w_depth);
1062 XSetClipMask(dpy, scr->copy_gc, None);
1064 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
1065 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1066 x - 1, y, w + 2, h, 0, 0);
1067 } else {
1068 XSetForeground(dpy, scr->copy_gc, fwin->title_texture[state]->solid.normal.pixel);
1069 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w + 2, h);
1072 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1); */
1073 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1074 *fwin->font, 1, 0, title, titlelen);
1076 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc, 0, 0, w + 2, h, x - 1, y);
1078 XFreePixmap(dpy, buf);
1080 wfree(title);
1083 if (fwin->left_button)
1084 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1085 if (fwin->right_button)
1086 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1087 #ifdef XKB_BUTTON_HINT
1088 if (fwin->language_button)
1089 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1090 #endif
1094 static void reconfigure(WFrameWindow * fwin, int x, int y, int width, int height, Bool dontMove)
1096 int k = (wPreferences.new_style == TS_NEW ? 4 : 3);
1097 int resizedHorizontally = 0;
1099 if (dontMove)
1100 XResizeWindow(dpy, fwin->core->window, width, height);
1101 else
1102 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1104 if (fwin->core->width != width) {
1105 fwin->flags.need_texture_remake = 1;
1106 resizedHorizontally = 1;
1109 fwin->core->width = width;
1110 fwin->core->height = height;
1112 if (fwin->titlebar && resizedHorizontally) {
1113 /* Check if the titlebar is wide enough to hold the buttons.
1114 * Temporarily remove them if can't
1116 if (fwin->left_button) {
1117 if (width < fwin->top_width * k && !fwin->flags.lbutton_dont_fit) {
1118 if (!fwin->flags.hide_left_button)
1119 XUnmapWindow(dpy, fwin->left_button->window);
1121 fwin->flags.lbutton_dont_fit = 1;
1122 } else if (width >= fwin->top_width * k && fwin->flags.lbutton_dont_fit) {
1123 if (!fwin->flags.hide_left_button)
1124 XMapWindow(dpy, fwin->left_button->window);
1126 fwin->flags.lbutton_dont_fit = 0;
1129 #ifdef XKB_BUTTON_HINT
1130 if (fwin->language_button) {
1131 if (width < fwin->top_width * k && !fwin->flags.languagebutton_dont_fit) {
1132 if (!fwin->flags.hide_language_button)
1133 XUnmapWindow(dpy, fwin->language_button->window);
1135 fwin->flags.languagebutton_dont_fit = 1;
1136 } else if (width >= fwin->top_width * k && fwin->flags.languagebutton_dont_fit) {
1137 if (!fwin->flags.hide_language_button)
1138 XMapWindow(dpy, fwin->language_button->window);
1140 fwin->flags.languagebutton_dont_fit = 0;
1143 #endif
1145 if (fwin->right_button) {
1146 if (width < fwin->top_width * 2 && !fwin->flags.rbutton_dont_fit) {
1147 if (!fwin->flags.hide_right_button)
1148 XUnmapWindow(dpy, fwin->right_button->window);
1150 fwin->flags.rbutton_dont_fit = 1;
1151 } else if (width >= fwin->top_width * 2 && fwin->flags.rbutton_dont_fit) {
1152 if (!fwin->flags.hide_right_button)
1153 XMapWindow(dpy, fwin->right_button->window);
1155 fwin->flags.rbutton_dont_fit = 0;
1159 if (wPreferences.new_style == TS_NEW) {
1160 if (fwin->right_button)
1161 XMoveWindow(dpy, fwin->right_button->window,
1162 width - fwin->right_button->width + 1, 0);
1163 } else {
1164 if (fwin->right_button)
1165 XMoveWindow(dpy, fwin->right_button->window,
1166 width - fwin->right_button->width - 3,
1167 (fwin->titlebar->height - fwin->right_button->height) / 2);
1169 updateTitlebar(fwin);
1170 checkTitleSize(fwin);
1173 if (fwin->resizebar) {
1174 wCoreConfigure(fwin->resizebar, 0,
1175 fwin->core->height - fwin->resizebar->height,
1176 fwin->core->width, fwin->resizebar->height);
1178 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1179 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH)
1180 fwin->resizebar_corner_width = fwin->core->width / 2;
1184 void wFrameWindowConfigure(WFrameWindow * fwin, int x, int y, int width, int height)
1186 reconfigure(fwin, x, y, width, height, False);
1189 void wFrameWindowResize(WFrameWindow * fwin, int width, int height)
1191 reconfigure(fwin, 0, 0, width, height, True);
1194 int wFrameWindowChangeTitle(WFrameWindow *fwin, const char *new_title)
1196 /* check if the title is the same as before */
1197 if (fwin->title) {
1198 if (new_title && (strcmp(fwin->title, new_title) == 0))
1199 return 0;
1200 } else {
1201 if (!new_title)
1202 return 0;
1205 if (fwin->title)
1206 wfree(fwin->title);
1208 fwin->title = wstrdup(new_title);
1210 if (fwin->titlebar) {
1211 XClearWindow(dpy, fwin->titlebar->window);
1213 wFrameWindowPaint(fwin);
1215 checkTitleSize(fwin);
1217 return 1;
1220 #ifdef XKB_BUTTON_HINT
1221 void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
1223 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1224 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
1226 #endif /* XKB_BUTTON_HINT */
1228 /*********************************************************************/
1230 static void handleExpose(WObjDescriptor * desc, XEvent * event)
1232 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1234 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1235 fwin->flags.repaint_only_titlebar = 1;
1236 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1237 fwin->flags.repaint_only_resizebar = 1;
1238 wFrameWindowPaint(fwin);
1239 fwin->flags.repaint_only_titlebar = 0;
1240 fwin->flags.repaint_only_resizebar = 0;
1243 static void checkTitleSize(WFrameWindow * fwin)
1245 int width;
1247 if (!fwin->title) {
1248 fwin->flags.incomplete_title = 0;
1249 return;
1252 if (!fwin->titlebar) {
1253 fwin->flags.incomplete_title = 1;
1254 return;
1255 } else {
1256 width = fwin->titlebar->width - 6 - 6;
1259 if (!wPreferences.new_style == TS_NEW) {
1260 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1261 width -= fwin->left_button->width + 3;
1263 #ifdef XKB_BUTTON_HINT
1264 if (fwin->language_button && !fwin->flags.hide_language_button
1265 && !fwin->flags.languagebutton_dont_fit)
1266 width -= fwin->language_button->width + 3;
1267 #endif
1269 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1270 width -= fwin->right_button->width + 3;
1273 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width)
1274 fwin->flags.incomplete_title = 1;
1275 else
1276 fwin->flags.incomplete_title = 0;
1279 static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
1281 WScreen *scr = button->screen_ptr;
1282 GC copy_gc = scr->copy_gc;
1283 int x = 0, y = 0, d = 0;
1284 int left = 0, width = 0;
1286 /* setup stuff according to the state */
1287 if (pushed) {
1288 if (image) {
1289 if (image->width >= image->height * 2) {
1290 /* the image contains 2 pictures: the second is for the
1291 * pushed state */
1292 width = image->width / 2;
1293 left = image->width / 2;
1294 } else {
1295 width = image->width;
1298 XSetClipMask(dpy, copy_gc, None);
1299 if (wPreferences.new_style == TS_NEXT)
1300 XSetForeground(dpy, copy_gc, scr->black_pixel);
1301 else
1302 XSetForeground(dpy, copy_gc, scr->white_pixel);
1304 d = 1;
1305 if (wPreferences.new_style == TS_NEW) {
1306 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1307 XSetForeground(dpy, copy_gc, scr->black_pixel);
1308 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1309 } else if (wPreferences.new_style == TS_OLD) {
1310 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1311 XSetForeground(dpy, copy_gc, scr->black_pixel);
1312 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1313 } else {
1314 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1315 XSetForeground(dpy, copy_gc, scr->black_pixel);
1316 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1318 } else {
1319 XClearWindow(dpy, button->window);
1321 if (image) {
1322 if (image->width >= image->height * 2)
1323 width = image->width / 2;
1324 else
1325 width = image->width;
1327 d = 0;
1329 if (wPreferences.new_style == TS_NEW) {
1330 if (texture->any.type == WTEX_SOLID || pushed)
1331 wDrawBevel(button->window, button->width, button->height,
1332 (WTexSolid *) texture, WREL_RAISED);
1333 } else {
1334 wDrawBevel(button->window, button->width, button->height,
1335 scr->widget_texture, WREL_RAISED);
1339 if (image) {
1340 /* display image */
1341 XSetClipMask(dpy, copy_gc, image->mask);
1342 x = (button->width - width) / 2 + d;
1343 y = (button->height - image->height) / 2 + d;
1344 XSetClipOrigin(dpy, copy_gc, x - left, y);
1345 if (!wPreferences.new_style == TS_NEW) {
1346 XSetForeground(dpy, copy_gc, scr->black_pixel);
1347 if (!pushed) {
1348 if (image->depth == 1)
1349 XCopyPlane(dpy, image->image, button->window, copy_gc,
1350 left, 0, width, image->height, x, y, 1);
1351 else
1352 XCopyArea(dpy, image->image, button->window, copy_gc,
1353 left, 0, width, image->height, x, y);
1354 } else {
1355 if (wPreferences.new_style == TS_OLD) {
1356 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1357 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1358 button->width, button->height);
1359 } else {
1360 XSetForeground(dpy, copy_gc, scr->black_pixel);
1361 XCopyArea(dpy, image->image, button->window, copy_gc,
1362 left, 0, width, image->height, x, y);
1365 } else {
1366 if (pushed) {
1367 XSetForeground(dpy, copy_gc, scr->black_pixel);
1368 } else {
1369 XSetForeground(dpy, copy_gc, color);
1370 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1372 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1377 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
1379 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1380 WCoreWindow *button = (WCoreWindow *) desc->self;
1382 #ifdef XKB_BUTTON_HINT
1383 if (button == fwin->language_button) {
1384 if (wPreferences.modelock)
1385 paintButton(button, fwin->title_texture[fwin->flags.state],
1386 WMColorPixel(fwin->title_color[fwin->flags.state]),
1387 fwin->languagebutton_image, False);
1388 } else
1389 #endif
1390 if (button == fwin->left_button)
1391 paintButton(button, fwin->title_texture[fwin->flags.state],
1392 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
1393 else
1394 paintButton(button, fwin->title_texture[fwin->flags.state],
1395 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
1398 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
1400 WFrameWindow *fwin = desc->parent;
1401 WCoreWindow *titlebar = desc->self;
1403 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1404 if (fwin->on_dblclick_titlebar)
1405 (*fwin->on_dblclick_titlebar) (titlebar, fwin->child, event);
1406 } else {
1407 if (fwin->on_mousedown_titlebar)
1408 (*fwin->on_mousedown_titlebar) (titlebar, fwin->child, event);
1412 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event)
1414 WFrameWindow *fwin = desc->parent;
1415 WCoreWindow *resizebar = desc->self;
1417 if (fwin->on_mousedown_resizebar)
1418 (*fwin->on_mousedown_resizebar) (resizebar, fwin->child, event);
1421 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
1423 WFrameWindow *fwin = desc->parent;
1424 WCoreWindow *button = desc->self;
1425 WPixmap *image;
1426 XEvent ev;
1427 int done = 0, execute = 1;
1428 WTexture *texture;
1429 unsigned long pixel;
1430 int clickButton = event->xbutton.button;
1432 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1433 if (button == fwin->right_button && fwin->on_dblclick_right)
1434 (*fwin->on_dblclick_right) (button, fwin->child, event);
1436 return;
1439 if (button == fwin->left_button)
1440 image = fwin->lbutton_image;
1441 else
1442 image = fwin->rbutton_image;
1444 #ifdef XKB_BUTTON_HINT
1445 if (button == fwin->language_button) {
1446 if (!wPreferences.modelock)
1447 return;
1448 image = fwin->languagebutton_image;
1450 #endif
1452 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1453 texture = fwin->title_texture[fwin->flags.state];
1454 paintButton(button, texture, pixel, image, True);
1456 while (!done) {
1457 WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
1458 | ButtonPressMask | ExposureMask, &ev);
1459 switch (ev.type) {
1460 case LeaveNotify:
1461 execute = 0;
1462 paintButton(button, texture, pixel, image, False);
1463 break;
1465 case EnterNotify:
1466 execute = 1;
1467 paintButton(button, texture, pixel, image, True);
1468 break;
1470 case ButtonPress:
1471 break;
1473 case ButtonRelease:
1474 if (ev.xbutton.button == clickButton)
1475 done = 1;
1476 break;
1478 default:
1479 WMHandleEvent(&ev);
1482 paintButton(button, texture, pixel, image, False);
1484 if (execute) {
1485 if (button == fwin->left_button) {
1486 if (fwin->on_click_left)
1487 (*fwin->on_click_left) (button, fwin->child, &ev);
1488 } else if (button == fwin->right_button) {
1489 if (fwin->on_click_right)
1490 (*fwin->on_click_right) (button, fwin->child, &ev);
1492 #ifdef XKB_BUTTON_HINT
1493 else if (button == fwin->language_button) {
1494 if (fwin->on_click_language)
1495 (*fwin->on_click_language) (button, fwin->child, &ev);
1497 #endif