Added option to 'configure' to control debug information for compilation
[wmaker-crm.git] / src / framewin.c
blobb7a6e971b030d50048d741954f1b05d109a7c42e
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 "screen.h"
38 #include "wcore.h"
39 #include "framewin.h"
40 #include "stacking.h"
41 #include "funcs.h"
43 #define DBLCLICK_TIME wPreferences.dblclick_time
45 extern WPreferences wPreferences;
47 static void handleExpose(WObjDescriptor * desc, XEvent * event);
48 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event);
50 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event);
51 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event);
52 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event);
54 static void checkTitleSize(WFrameWindow * fwin);
56 static void paintButton(WCoreWindow * button, WTexture * texture,
57 unsigned long color, WPixmap * image, int pushed);
59 static void updateTitlebar(WFrameWindow * fwin);
61 static void allocFrameBorderPixel(Colormap colormap, char *color_name, unsigned long **pixel);
63 static void allocFrameBorderPixel(Colormap colormap, char *color_name, unsigned long **pixel) {
64 XColor xcol;
66 *pixel = NULL;
68 if (!XParseColor(dpy, colormap, color_name, &xcol)) {
69 wwarning(_("could not parse color \"%s\""), color_name);
70 return;
72 if (!XAllocColor(dpy, colormap, &xcol)) {
73 wwarning(_("could not allocate color \"%s\""), color_name);
74 return;
77 *pixel = wmalloc(sizeof(unsigned long));
78 if (*pixel)
79 **pixel = xcol.pixel;
82 WFrameWindow *wFrameWindowCreate(WScreen * scr, int wlevel, int x, int y,
83 int width, int height, int *clearance,
84 int *title_min, int *title_max, int flags,
85 WTexture ** title_texture, WTexture ** resize_texture,
86 WMColor ** color, WMFont ** font,
87 int depth, Visual *visual, Colormap colormap)
89 WFrameWindow *fwin;
91 fwin = wmalloc(sizeof(WFrameWindow));
93 fwin->screen_ptr = scr;
95 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
97 fwin->title_texture = title_texture;
98 fwin->resizebar_texture = resize_texture;
99 fwin->title_color = color;
100 fwin->title_clearance = clearance;
101 fwin->title_min_height = title_min;
102 fwin->title_max_height = title_max;
103 fwin->font = font;
104 #ifdef KEEP_XKB_LOCK_STATUS
105 fwin->languagemode = XkbGroup1Index;
106 fwin->last_languagemode = XkbGroup2Index;
107 #endif
109 fwin->depth = depth;
110 fwin->visual = visual;
111 fwin->colormap = colormap;
112 allocFrameBorderPixel(fwin->colormap, FRAME_BORDER_COLOR, &fwin->border_pixel);
113 allocFrameBorderPixel(fwin->colormap, FRAME_SELECTED_BORDER_COLOR, &fwin->selected_border_pixel);
115 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height, (flags & WFF_BORDER)
116 ? FRAME_BORDER_WIDTH : 0, fwin->depth, fwin->visual, fwin->colormap);
117 if (wPreferences.use_saveunders) {
118 unsigned long vmask;
119 XSetWindowAttributes attribs;
121 vmask = CWSaveUnder;
122 attribs.save_under = True;
123 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
126 /* setup stacking information */
127 fwin->core->stacking = wmalloc(sizeof(WStacking));
128 fwin->core->stacking->above = NULL;
129 fwin->core->stacking->under = NULL;
130 fwin->core->stacking->child_of = NULL;
131 fwin->core->stacking->window_level = wlevel;
133 AddToStackList(fwin->core);
135 wFrameWindowUpdateBorders(fwin, flags);
137 return fwin;
140 void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
142 int theight;
143 int bsize;
144 int width, height;
145 int i;
146 WScreen *scr = fwin->screen_ptr;
148 width = fwin->core->width;
149 if (flags & WFF_IS_SHADED)
150 height = -1;
151 else
152 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
154 if (flags & WFF_TITLEBAR) {
155 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
157 if (theight > *fwin->title_max_height)
158 theight = *fwin->title_max_height;
160 if (theight < *fwin->title_min_height)
161 theight = *fwin->title_min_height;
162 } else {
163 theight = 0;
166 if (wPreferences.new_style == TS_NEW) {
167 bsize = theight;
168 } else if (wPreferences.new_style == TS_OLD) {
169 bsize = theight - 7;
170 } else {
171 bsize = theight - 8;
174 if (fwin->titlebar) {
175 /* if we had a titlebar and is requesting for one,
176 * check if the size has changed and resize it */
177 if (flags & WFF_TITLEBAR) {
178 fwin->top_width = theight;
180 fwin->flags.need_texture_remake = 1;
182 if (wPreferences.new_style == TS_NEW) {
183 if (fwin->left_button)
184 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
185 #ifdef XKB_BUTTON_HINT
186 if (fwin->language_button) {
187 if (fwin->flags.hide_left_button || !fwin->left_button
188 || fwin->flags.lbutton_dont_fit)
189 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
190 else
191 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
193 #endif
195 if (fwin->right_button)
196 wCoreConfigure(fwin->right_button, width - bsize + 1, 0, bsize, bsize);
198 } else { /* !new_style */
199 if (fwin->left_button)
200 wCoreConfigure(fwin->left_button, 3, (theight - bsize) / 2, bsize, bsize);
201 #ifdef XKB_BUTTON_HINT
202 if (fwin->language_button)
203 wCoreConfigure(fwin->language_button, 6 + bsize, (theight - bsize) / 2,
204 bsize, bsize);
205 #endif
207 if (fwin->right_button)
208 wCoreConfigure(fwin->right_button, width - bsize - 3,
209 (theight - bsize) / 2, bsize, bsize);
211 updateTitlebar(fwin);
212 } else {
213 /* we had a titlebar, but now we don't need it anymore */
214 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
215 FREE_PIXMAP(fwin->title_back[i]);
216 if (wPreferences.new_style == TS_NEW) {
217 FREE_PIXMAP(fwin->lbutton_back[i]);
218 FREE_PIXMAP(fwin->rbutton_back[i]);
219 #ifdef XKB_BUTTON_HINT
220 FREE_PIXMAP(fwin->languagebutton_back[i]);
221 #endif
224 if (fwin->left_button)
225 wCoreDestroy(fwin->left_button);
226 fwin->left_button = NULL;
228 #ifdef XKB_BUTTON_HINT
229 if (fwin->language_button)
230 wCoreDestroy(fwin->language_button);
231 fwin->language_button = NULL;
232 #endif
234 if (fwin->right_button)
235 wCoreDestroy(fwin->right_button);
236 fwin->right_button = NULL;
238 wCoreDestroy(fwin->titlebar);
239 fwin->titlebar = NULL;
241 fwin->top_width = 0;
243 } else {
244 /* if we didn't have a titlebar and are being requested for
245 * one, create it */
246 if (flags & WFF_TITLEBAR) {
247 fwin->top_width = theight;
249 fwin->flags.titlebar = 1;
250 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width + 1, theight);
252 if (flags & WFF_LEFT_BUTTON) {
253 fwin->flags.left_button = 1;
254 if (wPreferences.new_style == TS_NEW) {
255 fwin->left_button = wCoreCreate(fwin->core, 0, 0, bsize, bsize);
257 if (width < theight * 4)
258 fwin->flags.lbutton_dont_fit = 1;
259 else
260 XMapRaised(dpy, fwin->left_button->window);
262 } else if (wPreferences.new_style == TS_OLD) {
263 fwin->left_button =
264 wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
266 XSetWindowBackground(dpy, fwin->left_button->window,
267 scr->widget_texture->normal.pixel);
269 if (width < theight * 3)
270 fwin->flags.lbutton_dont_fit = 1;
271 else
272 XMapRaised(dpy, fwin->left_button->window);
274 } else {
275 fwin->left_button =
276 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
277 bsize, bsize);
279 XSetWindowBackground(dpy, fwin->left_button->window,
280 scr->widget_texture->dark.pixel);
282 if (width < theight * 3)
283 fwin->flags.lbutton_dont_fit = 1;
284 else
285 XMapRaised(dpy, fwin->left_button->window);
289 #ifdef XKB_BUTTON_HINT
290 if (flags & WFF_LANGUAGE_BUTTON) {
291 fwin->flags.language_button = 1;
292 if (wPreferences.new_style == TS_NEW) {
293 fwin->language_button = wCoreCreate(fwin->core, bsize, 0, bsize, bsize);
295 if (width < theight * 4)
296 fwin->flags.languagebutton_dont_fit = 1;
297 else
298 XMapRaised(dpy, fwin->language_button->window);
299 } else {
300 fwin->language_button =
301 wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
302 bsize, bsize);
304 XSetWindowBackground(dpy, fwin->language_button->window,
305 scr->widget_texture->normal.pixel);
307 if (width < theight * 3)
308 fwin->flags.languagebutton_dont_fit = 1;
309 else
310 XMapRaised(dpy, fwin->language_button->window);
313 #endif
315 if (flags & WFF_RIGHT_BUTTON) {
316 fwin->flags.right_button = 1;
317 if (wPreferences.new_style == TS_NEW) {
318 fwin->right_button =
319 wCoreCreate(fwin->core, width - bsize + 1, 0, bsize, bsize);
320 } else if (wPreferences.new_style == TS_OLD) {
321 fwin->right_button =
322 wCoreCreate(fwin->titlebar, width - bsize - 3,
323 (theight - bsize) / 2, bsize, bsize);
324 XSetWindowBackground(dpy, fwin->right_button->window,
325 scr->widget_texture->normal.pixel);
326 } else {
327 fwin->right_button =
328 wCoreCreate(fwin->titlebar, width-bsize-3,
329 (theight-bsize)/2, bsize, bsize);
330 XSetWindowBackground(dpy, fwin->right_button->window,
331 scr->widget_texture->dark.pixel);
334 if (width < theight * 2)
335 fwin->flags.rbutton_dont_fit = 1;
336 else
337 XMapRaised(dpy, fwin->right_button->window);
340 if (wPreferences.new_style == TS_NEW)
341 updateTitlebar(fwin);
343 XMapRaised(dpy, fwin->titlebar->window);
345 fwin->flags.need_texture_remake = 1;
348 checkTitleSize(fwin);
350 if (flags & WFF_RESIZEBAR) {
351 fwin->bottom_width = RESIZEBAR_HEIGHT;
353 if (!fwin->resizebar) {
354 fwin->flags.resizebar = 1;
355 fwin->resizebar = wCoreCreate(fwin->core, 0,
356 height + fwin->top_width, width, RESIZEBAR_HEIGHT);
357 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
358 if (width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
359 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH) / 2;
360 if (fwin->resizebar_corner_width < 0)
361 fwin->resizebar_corner_width = 0;
364 XMapWindow(dpy, fwin->resizebar->window);
365 XLowerWindow(dpy, fwin->resizebar->window);
367 fwin->flags.need_texture_remake = 1;
368 } else {
369 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height)
370 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
371 width, RESIZEBAR_HEIGHT);
373 } else {
374 fwin->bottom_width = 0;
376 if (fwin->resizebar) {
377 fwin->bottom_width = 0;
378 wCoreDestroy(fwin->resizebar);
379 fwin->resizebar = NULL;
383 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED))
384 wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
386 if (flags & WFF_BORDER)
387 XSetWindowBorderWidth(dpy, fwin->core->window, FRAME_BORDER_WIDTH);
388 else
389 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
391 /* setup object descriptors */
392 if (fwin->titlebar) {
393 fwin->titlebar->descriptor.handle_expose = handleExpose;
394 fwin->titlebar->descriptor.parent = fwin;
395 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
396 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
399 if (fwin->resizebar) {
400 fwin->resizebar->descriptor.handle_expose = handleExpose;
401 fwin->resizebar->descriptor.parent = fwin;
402 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
403 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
406 if (fwin->left_button) {
407 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
408 fwin->left_button->descriptor.parent = fwin;
409 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
410 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
413 #ifdef XKB_BUTTON_HINT
414 if (fwin->language_button) {
415 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
416 fwin->language_button->descriptor.parent = fwin;
417 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
418 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
420 #endif
422 if (fwin->right_button) {
423 fwin->right_button->descriptor.parent = fwin;
424 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
425 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
426 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
429 checkTitleSize(fwin);
431 if (fwin->border_pixel)
432 XSetWindowBorder(dpy, fwin->core->window, *fwin->border_pixel);
435 void wFrameWindowDestroy(WFrameWindow * fwin)
437 int i;
439 if (fwin->left_button)
440 wCoreDestroy(fwin->left_button);
442 #ifdef XKB_BUTTON_HINT
443 if (fwin->language_button)
444 wCoreDestroy(fwin->language_button);
445 #endif
447 if (fwin->right_button)
448 wCoreDestroy(fwin->right_button);
450 if (fwin->resizebar)
451 wCoreDestroy(fwin->resizebar);
453 if (fwin->titlebar)
454 wCoreDestroy(fwin->titlebar);
456 RemoveFromStackList(fwin->core);
458 wCoreDestroy(fwin->core);
460 if (fwin->title)
461 wfree(fwin->title);
463 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
464 FREE_PIXMAP(fwin->title_back[i]);
465 if (wPreferences.new_style == TS_NEW) {
466 FREE_PIXMAP(fwin->lbutton_back[i]);
467 #ifdef XKB_BUTTON_HINT
468 FREE_PIXMAP(fwin->languagebutton_back[i]);
469 #endif
470 FREE_PIXMAP(fwin->rbutton_back[i]);
474 wfree(fwin);
477 void wFrameWindowChangeState(WFrameWindow * fwin, int state)
479 if (fwin->flags.state == state)
480 return;
482 fwin->flags.state = state;
483 fwin->flags.need_texture_change = 1;
485 wFrameWindowPaint(fwin);
488 static void updateTitlebar(WFrameWindow * fwin)
490 int x, w;
491 int theight;
493 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
495 if (theight > *fwin->title_max_height)
496 theight = *fwin->title_max_height;
498 if (theight < *fwin->title_min_height)
499 theight = *fwin->title_min_height;
501 x = 0;
502 w = fwin->core->width + 1;
504 if (wPreferences.new_style == TS_NEW) {
505 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
506 x = 0;
507 #ifdef XKB_BUTTON_HINT
508 if (fwin->language_button)
509 wCoreConfigure(fwin->language_button, 0, 0,
510 fwin->language_button->width, fwin->language_button->width);
511 #endif
512 } else {
513 #ifdef XKB_BUTTON_HINT
514 if (fwin->language_button)
515 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
516 fwin->language_button->width, fwin->language_button->width);
517 #endif
518 x = fwin->left_button->width;
519 w -= fwin->left_button->width;
521 #ifdef XKB_BUTTON_HINT
522 if (fwin->flags.hide_language_button || !fwin->language_button
523 || fwin->flags.languagebutton_dont_fit) {
524 } else {
525 x += fwin->language_button->width;
526 w -= fwin->language_button->width;
528 #endif
530 #ifdef XKB_BUTTON_HINT
531 else {
532 int bsize = theight - 7;
533 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
534 if (fwin->language_button)
535 wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
536 fwin->language_button->width, fwin->language_button->width);
537 } else {
538 if (fwin->language_button)
539 wCoreConfigure(fwin->language_button,
540 6 + fwin->left_button->width, (theight - bsize) / 2,
541 fwin->language_button->width, fwin->language_button->width);
544 #endif
546 if (wPreferences.new_style == TS_NEW) {
547 if (!fwin->flags.hide_right_button && fwin->right_button && !fwin->flags.rbutton_dont_fit)
548 w -= fwin->right_button->width;
551 if (wPreferences.new_style == TS_NEW || fwin->titlebar->width != w)
552 fwin->flags.need_texture_remake = 1;
554 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
557 void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
559 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
560 XUnmapWindow(dpy, fwin->right_button->window);
561 fwin->flags.hide_right_button = 1;
564 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
565 XUnmapWindow(dpy, fwin->left_button->window);
566 fwin->flags.hide_left_button = 1;
568 #ifdef XKB_BUTTON_HINT
569 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
570 XUnmapWindow(dpy, fwin->language_button->window);
571 fwin->flags.hide_language_button = 1;
573 #endif
575 if (fwin->titlebar) {
576 if (wPreferences.new_style == TS_NEW) {
577 updateTitlebar(fwin);
578 } else {
579 #ifdef XKB_BUTTON_HINT
580 updateTitlebar(fwin);
581 #else
582 XClearWindow(dpy, fwin->titlebar->window);
583 wFrameWindowPaint(fwin);
584 #endif
586 checkTitleSize(fwin);
590 void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
592 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
594 if (!fwin->flags.rbutton_dont_fit)
595 XMapWindow(dpy, fwin->right_button->window);
597 fwin->flags.hide_right_button = 0;
599 #ifdef XKB_BUTTON_HINT
600 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
602 if (!fwin->flags.languagebutton_dont_fit)
603 XMapWindow(dpy, fwin->language_button->window);
605 fwin->flags.hide_language_button = 0;
607 #endif
609 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
611 if (!fwin->flags.lbutton_dont_fit)
612 XMapWindow(dpy, fwin->left_button->window);
614 fwin->flags.hide_left_button = 0;
617 if (fwin->titlebar) {
618 if (wPreferences.new_style == TS_NEW) {
619 updateTitlebar(fwin);
620 } else {
621 XClearWindow(dpy, fwin->titlebar->window);
622 wFrameWindowPaint(fwin);
624 checkTitleSize(fwin);
628 static void
629 #ifdef XKB_BUTTON_HINT
630 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
631 int bwidth, int bheight, int left, int language, int right,
632 Pixmap * title, Pixmap * lbutton, Pixmap * languagebutton, Pixmap * rbutton)
633 #else
634 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
635 int bwidth, int bheight, int left, int right, Pixmap * title, Pixmap * lbutton, Pixmap * rbutton)
636 #endif
638 RImage *img;
639 RImage *limg, *rimg, *mimg;
640 #ifdef XKB_BUTTON_HINT
641 RImage *timg;
642 #endif
643 int x, w;
645 *title = None;
646 *lbutton = None;
647 *rbutton = None;
648 #ifdef XKB_BUTTON_HINT
649 *languagebutton = None;
650 #endif
652 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
653 if (!img) {
654 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
655 return;
658 if (wPreferences.new_style == TS_NEW) {
659 if (left)
660 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
661 else
662 limg = NULL;
664 x = 0;
665 w = img->width;
667 #ifdef XKB_BUTTON_HINT
668 if (language)
669 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
670 else
671 timg = NULL;
672 #endif
674 if (limg) {
675 RBevelImage(limg, RBEV_RAISED2);
676 if (!RConvertImage(scr->rcontext, limg, lbutton))
677 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
679 x += limg->width;
680 w -= limg->width;
681 RReleaseImage(limg);
683 #ifdef XKB_BUTTON_HINT
684 if (timg) {
685 RBevelImage(timg, RBEV_RAISED2);
686 if (!RConvertImage(scr->rcontext, timg, languagebutton))
687 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
689 x += timg->width;
690 w -= timg->width;
691 RReleaseImage(timg);
693 #endif
695 if (right)
696 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
697 else
698 rimg = NULL;
700 if (rimg) {
701 RBevelImage(rimg, RBEV_RAISED2);
702 if (!RConvertImage(scr->rcontext, rimg, rbutton))
703 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
705 w -= rimg->width;
706 RReleaseImage(rimg);
709 if (w != width) {
710 mimg = RGetSubImage(img, x, 0, w, img->height);
711 RBevelImage(mimg, RBEV_RAISED2);
713 if (!RConvertImage(scr->rcontext, mimg, title))
714 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
716 RReleaseImage(mimg);
717 } else {
718 RBevelImage(img, RBEV_RAISED2);
720 if (!RConvertImage(scr->rcontext, img, title))
721 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
723 } else {
724 RBevelImage(img, RBEV_RAISED2);
726 if (!RConvertImage(scr->rcontext, img, title))
727 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
730 RReleaseImage(img);
733 static void
734 renderResizebarTexture(WScreen * scr, WTexture * texture, int width, int height, 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"), RMessageForError(RErrorCode));
745 return;
748 light.alpha = 0;
749 light.red = light.green = light.blue = 80;
751 dark.alpha = 0;
752 dark.red = dark.green = dark.blue = 40;
754 ROperateLine(img, RSubtractOperation, 0, 0, width - 1, 0, &dark);
755 ROperateLine(img, RAddOperation, 0, 1, width - 1, 1, &light);
757 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height - 1, &dark);
758 ROperateLine(img, RAddOperation, cwidth + 1, 2, cwidth + 1, height - 1, &light);
760 if (width > 1)
761 ROperateLine(img, RSubtractOperation, width - cwidth - 2, 2,
762 width - cwidth - 2, height - 1, &dark);
763 ROperateLine(img, RAddOperation, width - cwidth - 1, 2, width - cwidth - 1, height - 1, &light);
765 #ifdef SHADOW_RESIZEBAR
766 ROperateLine(img, RAddOperation, 0, 1, 0, height - 1, &light);
767 ROperateLine(img, RSubtractOperation, width - 1, 1, width - 1, height - 1, &dark);
768 ROperateLine(img, RSubtractOperation, 0, height - 1, width - 1, height - 1, &dark);
769 #endif /* SHADOW_RESIZEBAR */
771 if (!RConvertImage(scr->rcontext, img, pmap))
772 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
774 RReleaseImage(img);
777 static void updateTexture(WFrameWindow * fwin)
779 int i;
780 unsigned long pixel;
782 i = fwin->flags.state;
783 if (fwin->titlebar) {
784 if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
785 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window, fwin->title_back[i]);
786 if (wPreferences.new_style == TS_NEW) {
787 if (fwin->left_button && fwin->lbutton_back[i])
788 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
789 fwin->lbutton_back[i]);
791 #ifdef XKB_BUTTON_HINT
792 if (fwin->language_button && fwin->languagebutton_back[i])
793 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
794 fwin->languagebutton_back[i]);
795 #endif
797 if (fwin->right_button && fwin->rbutton_back[i])
798 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
799 fwin->rbutton_back[i]);
801 } else {
802 pixel = fwin->title_texture[i]->solid.normal.pixel;
803 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
804 if (wPreferences.new_style == TS_NEW) {
805 if (fwin->left_button)
806 XSetWindowBackground(dpy, fwin->left_button->window, pixel);
807 #ifdef XKB_BUTTON_HINT
808 if (fwin->language_button)
809 XSetWindowBackground(dpy, fwin->language_button->window, pixel);
810 #endif
811 if (fwin->right_button)
812 XSetWindowBackground(dpy, fwin->right_button->window, pixel);
815 XClearWindow(dpy, fwin->titlebar->window);
817 if (fwin->left_button) {
818 XClearWindow(dpy, fwin->left_button->window);
819 handleButtonExpose(&fwin->left_button->descriptor, NULL);
821 #ifdef XKB_BUTTON_HINT
822 if (fwin->language_button) {
823 XClearWindow(dpy, fwin->language_button->window);
824 handleButtonExpose(&fwin->language_button->descriptor, NULL);
826 #endif
827 if (fwin->right_button) {
828 XClearWindow(dpy, fwin->right_button->window);
829 handleButtonExpose(&fwin->right_button->descriptor, NULL);
834 static void remakeTexture(WFrameWindow * fwin, int state)
836 Pixmap pmap, lpmap, rpmap;
837 #ifdef XKB_BUTTON_HINT
838 Pixmap tpmap;
839 #endif
841 if (fwin->title_texture[state] && fwin->titlebar) {
842 FREE_PIXMAP(fwin->title_back[state]);
843 if (wPreferences.new_style == TS_NEW) {
844 FREE_PIXMAP(fwin->lbutton_back[state]);
845 FREE_PIXMAP(fwin->rbutton_back[state]);
846 #ifdef XKB_BUTTON_HINT
847 FREE_PIXMAP(fwin->languagebutton_back[state]);
848 #endif
851 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
852 int left, right;
853 int width;
854 #ifdef XKB_BUTTON_HINT
855 int language;
856 #endif
858 /* eventually surrounded by if new_style */
859 left = fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit;
860 #ifdef XKB_BUTTON_HINT
861 language = fwin->language_button && !fwin->flags.hide_language_button
862 && !fwin->flags.languagebutton_dont_fit;
863 #endif
864 right = fwin->right_button && !fwin->flags.hide_right_button
865 && !fwin->flags.rbutton_dont_fit;
867 width = fwin->core->width + 1;
869 #ifdef XKB_BUTTON_HINT
870 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
871 width, fwin->titlebar->height,
872 fwin->titlebar->height, fwin->titlebar->height,
873 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
874 #else
875 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
876 width, fwin->titlebar->height,
877 fwin->titlebar->height, fwin->titlebar->height,
878 left, right, &pmap, &lpmap, &rpmap);
879 #endif
881 fwin->title_back[state] = pmap;
882 if (wPreferences.new_style == TS_NEW) {
883 fwin->lbutton_back[state] = lpmap;
884 fwin->rbutton_back[state] = rpmap;
885 #ifdef XKB_BUTTON_HINT
886 fwin->languagebutton_back[state] = tpmap;
887 #endif
891 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
892 && fwin->resizebar && state == 0) {
894 FREE_PIXMAP(fwin->resizebar_back[0]);
896 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
898 renderResizebarTexture(fwin->screen_ptr,
899 fwin->resizebar_texture[0],
900 fwin->resizebar->width,
901 fwin->resizebar->height, fwin->resizebar_corner_width, &pmap);
903 fwin->resizebar_back[0] = pmap;
906 /* this part should be in updateTexture() */
907 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID)
908 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
909 else
910 XSetWindowBackground(dpy, fwin->resizebar->window,
911 fwin->resizebar_texture[0]->solid.normal.pixel);
913 XClearWindow(dpy, fwin->resizebar->window);
917 void wFrameWindowPaint(WFrameWindow * fwin)
919 WScreen *scr = fwin->screen_ptr;
920 int state;
922 state = fwin->flags.state;
924 if (fwin->flags.is_client_window_frame)
925 fwin->flags.justification = wPreferences.title_justification;
927 if (fwin->flags.need_texture_remake) {
928 int i;
930 fwin->flags.need_texture_remake = 0;
931 fwin->flags.need_texture_change = 0;
933 if (fwin->flags.single_texture) {
934 remakeTexture(fwin, 0);
935 updateTexture(fwin);
936 } else {
937 /* first render the texture for the current state... */
938 remakeTexture(fwin, state);
939 /* ... and paint it */
940 updateTexture(fwin);
942 for (i = 0; i < 3; i++) {
943 if (i != state)
944 remakeTexture(fwin, i);
949 if (fwin->flags.need_texture_change) {
950 fwin->flags.need_texture_change = 0;
952 updateTexture(fwin);
955 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
956 && fwin->title_texture[state]->any.type == WTEX_SOLID) {
957 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
958 fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
961 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
962 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
963 Window win;
964 int w, h;
965 int cw;
966 GC light_gc, dim_gc;
967 WTexSolid *texture = (WTexSolid *) fwin->resizebar_texture[0];
969 w = fwin->resizebar->width;
970 h = fwin->resizebar->height;
971 cw = fwin->resizebar_corner_width;
972 light_gc = texture->light_gc;
973 dim_gc = texture->dim_gc;
974 win = fwin->resizebar->window;
976 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
977 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
979 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
980 XDrawLine(dpy, win, light_gc, cw + 1, 2, cw + 1, h);
982 XDrawLine(dpy, win, dim_gc, w - cw - 2, 2, w - cw - 2, h);
983 XDrawLine(dpy, win, light_gc, w - cw - 1, 2, w - cw - 1, h);
985 #ifdef SHADOW_RESIZEBAR
986 XDrawLine(dpy, win, light_gc, 0, 1, 0, h - 1);
987 XDrawLine(dpy, win, dim_gc, w - 1, 2, w - 1, h - 1);
988 XDrawLine(dpy, win, dim_gc, 1, h - 1, cw, h - 1);
989 XDrawLine(dpy, win, dim_gc, cw + 2, h - 1, w - cw - 2, h - 1);
990 XDrawLine(dpy, win, dim_gc, w - cw, h - 1, w - 1, h - 1);
991 #endif /* SHADOW_RESIZEBAR */
994 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
995 int x, y, w, h;
996 int lofs = 6, rofs = 6;
997 int titlelen;
998 int allButtons = 1;
1000 if (!wPreferences.new_style == TS_NEW) {
1001 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1002 lofs += fwin->left_button->width + 3;
1003 else
1004 allButtons = 0;
1006 #ifdef XKB_BUTTON_HINT
1007 if (fwin->language_button && !fwin->flags.hide_language_button
1008 && !fwin->flags.languagebutton_dont_fit)
1009 lofs += fwin->language_button->width;
1010 else
1011 allButtons = 0;
1012 #endif
1014 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1015 rofs += fwin->right_button->width + 3;
1016 else
1017 allButtons = 0;
1019 #ifdef XKB_BUTTON_HINT
1020 fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1021 #endif
1023 if (fwin->title) {
1024 Drawable buf;
1025 char *title;
1027 title = ShrinkString(*fwin->font, fwin->title, fwin->titlebar->width - lofs - rofs);
1028 titlelen = strlen(title);
1029 w = WMWidthOfString(*fwin->font, title, titlelen);
1031 switch (fwin->flags.justification) {
1032 case WTJ_LEFT:
1033 x = lofs;
1034 break;
1036 case WTJ_RIGHT:
1037 x = fwin->titlebar->width - w - rofs;
1038 break;
1040 default:
1041 if (!allButtons)
1042 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1043 else
1044 x = (fwin->titlebar->width - w) / 2;
1045 break;
1048 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1049 h = WMFontHeight(*fwin->font);
1051 if (y*2 + h > *fwin->title_max_height)
1052 y = (*fwin->title_max_height - h) / 2;
1054 if (y*2 + h < *fwin->title_min_height)
1055 y = (*fwin->title_min_height - h) / 2;
1057 /* We use a w+2 buffer to have an extra pixel on the left and
1058 * another one on the right. This is because for some odd reason,
1059 * sometimes when using AA fonts (when libfreetype2 is compiled
1060 * with bytecode interpreter turned off), some fonts are drawn
1061 * starting from x = -1 not from 0 as requested. Observed with
1062 * capital A letter on the bold 'trebuchet ms' font. -Dan
1064 buf = XCreatePixmap(dpy, fwin->titlebar->window, w + 2, h, scr->w_depth);
1066 XSetClipMask(dpy, scr->copy_gc, None);
1068 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
1069 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1070 x - 1, y, w + 2, h, 0, 0);
1071 } else {
1072 XSetForeground(dpy, scr->copy_gc, fwin->title_texture[state]->solid.normal.pixel);
1073 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w + 2, h);
1076 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1); */
1077 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1078 *fwin->font, 1, 0, title, titlelen);
1080 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc, 0, 0, w + 2, h, x - 1, y);
1082 XFreePixmap(dpy, buf);
1084 wfree(title);
1087 if (fwin->left_button)
1088 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1089 if (fwin->right_button)
1090 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1091 #ifdef XKB_BUTTON_HINT
1092 if (fwin->language_button)
1093 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1094 #endif
1098 static void reconfigure(WFrameWindow * fwin, int x, int y, int width, int height, Bool dontMove)
1100 int k = (wPreferences.new_style == TS_NEW ? 4 : 3);
1101 int resizedHorizontally = 0;
1103 if (dontMove)
1104 XResizeWindow(dpy, fwin->core->window, width, height);
1105 else
1106 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1108 if (fwin->core->width != width) {
1109 fwin->flags.need_texture_remake = 1;
1110 resizedHorizontally = 1;
1113 fwin->core->width = width;
1114 fwin->core->height = height;
1116 if (fwin->titlebar && resizedHorizontally) {
1117 /* Check if the titlebar is wide enough to hold the buttons.
1118 * Temporarily remove them if can't
1120 if (fwin->left_button) {
1121 if (width < fwin->top_width * k && !fwin->flags.lbutton_dont_fit) {
1122 if (!fwin->flags.hide_left_button)
1123 XUnmapWindow(dpy, fwin->left_button->window);
1125 fwin->flags.lbutton_dont_fit = 1;
1126 } else if (width >= fwin->top_width * k && fwin->flags.lbutton_dont_fit) {
1127 if (!fwin->flags.hide_left_button)
1128 XMapWindow(dpy, fwin->left_button->window);
1130 fwin->flags.lbutton_dont_fit = 0;
1133 #ifdef XKB_BUTTON_HINT
1134 if (fwin->language_button) {
1135 if (width < fwin->top_width * k && !fwin->flags.languagebutton_dont_fit) {
1136 if (!fwin->flags.hide_language_button)
1137 XUnmapWindow(dpy, fwin->language_button->window);
1139 fwin->flags.languagebutton_dont_fit = 1;
1140 } else if (width >= fwin->top_width * k && fwin->flags.languagebutton_dont_fit) {
1141 if (!fwin->flags.hide_language_button)
1142 XMapWindow(dpy, fwin->language_button->window);
1144 fwin->flags.languagebutton_dont_fit = 0;
1147 #endif
1149 if (fwin->right_button) {
1150 if (width < fwin->top_width * 2 && !fwin->flags.rbutton_dont_fit) {
1151 if (!fwin->flags.hide_right_button)
1152 XUnmapWindow(dpy, fwin->right_button->window);
1154 fwin->flags.rbutton_dont_fit = 1;
1155 } else if (width >= fwin->top_width * 2 && fwin->flags.rbutton_dont_fit) {
1156 if (!fwin->flags.hide_right_button)
1157 XMapWindow(dpy, fwin->right_button->window);
1159 fwin->flags.rbutton_dont_fit = 0;
1163 if (wPreferences.new_style == TS_NEW) {
1164 if (fwin->right_button)
1165 XMoveWindow(dpy, fwin->right_button->window,
1166 width - fwin->right_button->width + 1, 0);
1167 } else {
1168 if (fwin->right_button)
1169 XMoveWindow(dpy, fwin->right_button->window,
1170 width - fwin->right_button->width - 3,
1171 (fwin->titlebar->height - fwin->right_button->height) / 2);
1173 updateTitlebar(fwin);
1174 checkTitleSize(fwin);
1177 if (fwin->resizebar) {
1178 wCoreConfigure(fwin->resizebar, 0,
1179 fwin->core->height - fwin->resizebar->height,
1180 fwin->core->width, fwin->resizebar->height);
1182 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1183 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH)
1184 fwin->resizebar_corner_width = fwin->core->width / 2;
1188 void wFrameWindowConfigure(WFrameWindow * fwin, int x, int y, int width, int height)
1190 reconfigure(fwin, x, y, width, height, False);
1193 void wFrameWindowResize(WFrameWindow * fwin, int width, int height)
1195 reconfigure(fwin, 0, 0, width, height, True);
1198 int wFrameWindowChangeTitle(WFrameWindow * fwin, char *new_title)
1200 /* check if the title is the same as before */
1201 if (fwin->title) {
1202 if (new_title && (strcmp(fwin->title, new_title) == 0))
1203 return 0;
1204 } else {
1205 if (!new_title)
1206 return 0;
1209 if (fwin->title)
1210 wfree(fwin->title);
1212 fwin->title = wstrdup(new_title);
1214 if (fwin->titlebar) {
1215 XClearWindow(dpy, fwin->titlebar->window);
1217 wFrameWindowPaint(fwin);
1219 checkTitleSize(fwin);
1221 return 1;
1224 #ifdef XKB_BUTTON_HINT
1225 void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
1227 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1228 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
1230 #endif /* XKB_BUTTON_HINT */
1232 /*********************************************************************/
1234 static void handleExpose(WObjDescriptor * desc, XEvent * event)
1236 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1238 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1239 fwin->flags.repaint_only_titlebar = 1;
1240 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1241 fwin->flags.repaint_only_resizebar = 1;
1242 wFrameWindowPaint(fwin);
1243 fwin->flags.repaint_only_titlebar = 0;
1244 fwin->flags.repaint_only_resizebar = 0;
1247 static void checkTitleSize(WFrameWindow * fwin)
1249 int width;
1251 if (!fwin->title) {
1252 fwin->flags.incomplete_title = 0;
1253 return;
1256 if (!fwin->titlebar) {
1257 fwin->flags.incomplete_title = 1;
1258 return;
1259 } else {
1260 width = fwin->titlebar->width - 6 - 6;
1263 if (!wPreferences.new_style == TS_NEW) {
1264 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1265 width -= fwin->left_button->width + 3;
1267 #ifdef XKB_BUTTON_HINT
1268 if (fwin->language_button && !fwin->flags.hide_language_button
1269 && !fwin->flags.languagebutton_dont_fit)
1270 width -= fwin->language_button->width + 3;
1271 #endif
1273 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1274 width -= fwin->right_button->width + 3;
1277 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width)
1278 fwin->flags.incomplete_title = 1;
1279 else
1280 fwin->flags.incomplete_title = 0;
1283 static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
1285 WScreen *scr = button->screen_ptr;
1286 GC copy_gc = scr->copy_gc;
1287 int x = 0, y = 0, d = 0;
1288 int left = 0, width = 0;
1290 /* setup stuff according to the state */
1291 if (pushed) {
1292 if (image) {
1293 if (image->width >= image->height * 2) {
1294 /* the image contains 2 pictures: the second is for the
1295 * pushed state */
1296 width = image->width / 2;
1297 left = image->width / 2;
1298 } else {
1299 width = image->width;
1302 XSetClipMask(dpy, copy_gc, None);
1303 if (wPreferences.new_style == TS_NEXT)
1304 XSetForeground(dpy, copy_gc, scr->black_pixel);
1305 else
1306 XSetForeground(dpy, copy_gc, scr->white_pixel);
1308 d = 1;
1309 if (wPreferences.new_style == TS_NEW) {
1310 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1311 XSetForeground(dpy, copy_gc, scr->black_pixel);
1312 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1313 } else if (wPreferences.new_style == TS_OLD) {
1314 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1315 XSetForeground(dpy, copy_gc, scr->black_pixel);
1316 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1317 } else {
1318 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1319 XSetForeground(dpy, copy_gc, scr->black_pixel);
1320 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1322 } else {
1323 XClearWindow(dpy, button->window);
1325 if (image) {
1326 if (image->width >= image->height * 2)
1327 width = image->width / 2;
1328 else
1329 width = image->width;
1331 d = 0;
1333 if (wPreferences.new_style == TS_NEW) {
1334 if (texture->any.type == WTEX_SOLID || pushed)
1335 wDrawBevel(button->window, button->width, button->height,
1336 (WTexSolid *) texture, WREL_RAISED);
1337 } else {
1338 wDrawBevel(button->window, button->width, button->height,
1339 scr->widget_texture, WREL_RAISED);
1343 if (image) {
1344 /* display image */
1345 XSetClipMask(dpy, copy_gc, image->mask);
1346 x = (button->width - width) / 2 + d;
1347 y = (button->height - image->height) / 2 + d;
1348 XSetClipOrigin(dpy, copy_gc, x - left, y);
1349 if (!wPreferences.new_style == TS_NEW) {
1350 XSetForeground(dpy, copy_gc, scr->black_pixel);
1351 if (!pushed) {
1352 if (image->depth == 1)
1353 XCopyPlane(dpy, image->image, button->window, copy_gc,
1354 left, 0, width, image->height, x, y, 1);
1355 else
1356 XCopyArea(dpy, image->image, button->window, copy_gc,
1357 left, 0, width, image->height, x, y);
1358 } else {
1359 if (wPreferences.new_style == TS_OLD) {
1360 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1361 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1362 button->width, button->height);
1363 } else {
1364 XSetForeground(dpy, copy_gc, scr->black_pixel);
1365 XCopyArea(dpy, image->image, button->window, copy_gc,
1366 left, 0, width, image->height, x, y);
1369 } else {
1370 if (pushed) {
1371 XSetForeground(dpy, copy_gc, scr->black_pixel);
1372 } else {
1373 XSetForeground(dpy, copy_gc, color);
1374 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1376 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1381 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
1383 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1384 WCoreWindow *button = (WCoreWindow *) desc->self;
1386 #ifdef XKB_BUTTON_HINT
1387 if (button == fwin->language_button) {
1388 if (wPreferences.modelock)
1389 paintButton(button, fwin->title_texture[fwin->flags.state],
1390 WMColorPixel(fwin->title_color[fwin->flags.state]),
1391 fwin->languagebutton_image, False);
1392 } else
1393 #endif
1394 if (button == fwin->left_button)
1395 paintButton(button, fwin->title_texture[fwin->flags.state],
1396 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
1397 else
1398 paintButton(button, fwin->title_texture[fwin->flags.state],
1399 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
1402 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
1404 WFrameWindow *fwin = desc->parent;
1405 WCoreWindow *titlebar = desc->self;
1407 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1408 if (fwin->on_dblclick_titlebar)
1409 (*fwin->on_dblclick_titlebar) (titlebar, fwin->child, event);
1410 } else {
1411 if (fwin->on_mousedown_titlebar)
1412 (*fwin->on_mousedown_titlebar) (titlebar, fwin->child, event);
1416 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event)
1418 WFrameWindow *fwin = desc->parent;
1419 WCoreWindow *resizebar = desc->self;
1421 if (fwin->on_mousedown_resizebar)
1422 (*fwin->on_mousedown_resizebar) (resizebar, fwin->child, event);
1425 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
1427 WFrameWindow *fwin = desc->parent;
1428 WCoreWindow *button = desc->self;
1429 WPixmap *image;
1430 XEvent ev;
1431 int done = 0, execute = 1;
1432 WTexture *texture;
1433 unsigned long pixel;
1434 int clickButton = event->xbutton.button;
1436 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1437 if (button == fwin->right_button && fwin->on_dblclick_right)
1438 (*fwin->on_dblclick_right) (button, fwin->child, event);
1440 return;
1443 if (button == fwin->left_button)
1444 image = fwin->lbutton_image;
1445 else
1446 image = fwin->rbutton_image;
1448 #ifdef XKB_BUTTON_HINT
1449 if (button == fwin->language_button) {
1450 if (!wPreferences.modelock)
1451 return;
1452 image = fwin->languagebutton_image;
1454 #endif
1456 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1457 texture = fwin->title_texture[fwin->flags.state];
1458 paintButton(button, texture, pixel, image, True);
1460 while (!done) {
1461 WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
1462 | ButtonPressMask | ExposureMask, &ev);
1463 switch (ev.type) {
1464 case LeaveNotify:
1465 execute = 0;
1466 paintButton(button, texture, pixel, image, False);
1467 break;
1469 case EnterNotify:
1470 execute = 1;
1471 paintButton(button, texture, pixel, image, True);
1472 break;
1474 case ButtonPress:
1475 break;
1477 case ButtonRelease:
1478 if (ev.xbutton.button == clickButton)
1479 done = 1;
1480 break;
1482 default:
1483 WMHandleEvent(&ev);
1486 paintButton(button, texture, pixel, image, False);
1488 if (execute) {
1489 if (button == fwin->left_button) {
1490 if (fwin->on_click_left)
1491 (*fwin->on_click_left) (button, fwin->child, &ev);
1492 } else if (button == fwin->right_button) {
1493 if (fwin->on_click_right)
1494 (*fwin->on_click_right) (button, fwin->child, &ev);
1496 #ifdef XKB_BUTTON_HINT
1497 else if (button == fwin->language_button) {
1498 if (fwin->on_click_language)
1499 (*fwin->on_click_language) (button, fwin->child, &ev);
1501 #endif