Prevent crash when switchpanel is not initialised.
[wmaker-crm.git] / src / framewin.c
blob39f55d6f0e3e57ddd6d3808cc2047503b5444680
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 "framewin.h"
41 #include "stacking.h"
42 #include "misc.h"
44 #define DBLCLICK_TIME wPreferences.dblclick_time
46 extern WPreferences wPreferences;
48 static void handleExpose(WObjDescriptor * desc, XEvent * event);
49 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event);
51 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event);
52 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event);
53 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event);
55 static void checkTitleSize(WFrameWindow * fwin);
57 static void paintButton(WCoreWindow * button, WTexture * texture,
58 unsigned long color, WPixmap * image, int pushed);
60 static void updateTitlebar(WFrameWindow * fwin);
62 static void allocFrameBorderPixel(Colormap colormap, char *color_name, unsigned long **pixel);
64 static void allocFrameBorderPixel(Colormap colormap, char *color_name, unsigned long **pixel) {
65 XColor xcol;
67 *pixel = NULL;
69 if (! wGetColorForColormap(colormap, color_name, &xcol))
70 return;
72 *pixel = wmalloc(sizeof(unsigned long));
73 if (*pixel)
74 **pixel = xcol.pixel;
77 WFrameWindow *wFrameWindowCreate(WScreen * scr, int wlevel, int x, int y,
78 int width, int height, int *clearance,
79 int *title_min, int *title_max, int flags,
80 WTexture ** title_texture, WTexture ** resize_texture,
81 WMColor ** color, WMFont ** font,
82 int depth, Visual *visual, Colormap colormap)
84 WFrameWindow *fwin;
86 fwin = wmalloc(sizeof(WFrameWindow));
88 fwin->screen_ptr = scr;
90 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
92 fwin->title_texture = title_texture;
93 fwin->resizebar_texture = resize_texture;
94 fwin->title_color = color;
95 fwin->title_clearance = clearance;
96 fwin->title_min_height = title_min;
97 fwin->title_max_height = title_max;
98 fwin->font = font;
99 #ifdef KEEP_XKB_LOCK_STATUS
100 fwin->languagemode = XkbGroup1Index;
101 fwin->last_languagemode = XkbGroup2Index;
102 #endif
104 fwin->depth = depth;
105 fwin->visual = visual;
106 fwin->colormap = colormap;
108 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height, (flags & WFF_BORDER)
109 ? scr->frame_border_width : 0, fwin->depth, fwin->visual, fwin->colormap, scr->frame_border_pixel);
111 /* setup stacking information */
112 fwin->core->stacking = wmalloc(sizeof(WStacking));
113 fwin->core->stacking->above = NULL;
114 fwin->core->stacking->under = NULL;
115 fwin->core->stacking->child_of = NULL;
116 fwin->core->stacking->window_level = wlevel;
118 AddToStackList(fwin->core);
120 wFrameWindowUpdateBorders(fwin, flags);
122 return fwin;
125 void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
127 int theight;
128 int bsize;
129 int width, height;
130 int i;
131 WScreen *scr = fwin->screen_ptr;
133 width = fwin->core->width;
134 if (flags & WFF_IS_SHADED)
135 height = -1;
136 else
137 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
139 if (flags & WFF_TITLEBAR) {
140 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
142 if (theight > *fwin->title_max_height)
143 theight = *fwin->title_max_height;
145 if (theight < *fwin->title_min_height)
146 theight = *fwin->title_min_height;
147 } else {
148 theight = 0;
151 if (wPreferences.new_style == TS_NEW) {
152 bsize = theight;
153 } else if (wPreferences.new_style == TS_OLD) {
154 bsize = theight - 7;
155 } else {
156 bsize = theight - 8;
159 if (fwin->titlebar) {
160 /* if we had a titlebar and is requesting for one,
161 * check if the size has changed and resize it */
162 if (flags & WFF_TITLEBAR) {
163 fwin->top_width = theight;
165 fwin->flags.need_texture_remake = 1;
167 if (wPreferences.new_style == TS_NEW) {
168 if (fwin->left_button)
169 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
170 #ifdef XKB_BUTTON_HINT
171 if (fwin->language_button) {
172 if (fwin->flags.hide_left_button || !fwin->left_button
173 || fwin->flags.lbutton_dont_fit)
174 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
175 else
176 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
178 #endif
180 if (fwin->right_button)
181 wCoreConfigure(fwin->right_button, width - bsize + 1, 0, bsize, bsize);
183 } else { /* !new_style */
184 if (fwin->left_button)
185 wCoreConfigure(fwin->left_button, 3, (theight - bsize) / 2, bsize, bsize);
186 #ifdef XKB_BUTTON_HINT
187 if (fwin->language_button)
188 wCoreConfigure(fwin->language_button, 6 + bsize, (theight - bsize) / 2,
189 bsize, bsize);
190 #endif
192 if (fwin->right_button)
193 wCoreConfigure(fwin->right_button, width - bsize - 3,
194 (theight - bsize) / 2, bsize, bsize);
196 updateTitlebar(fwin);
197 } else {
198 /* we had a titlebar, but now we don't need it anymore */
199 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
200 FREE_PIXMAP(fwin->title_back[i]);
201 if (wPreferences.new_style == TS_NEW) {
202 FREE_PIXMAP(fwin->lbutton_back[i]);
203 FREE_PIXMAP(fwin->rbutton_back[i]);
204 #ifdef XKB_BUTTON_HINT
205 FREE_PIXMAP(fwin->languagebutton_back[i]);
206 #endif
209 if (fwin->left_button)
210 wCoreDestroy(fwin->left_button);
211 fwin->left_button = NULL;
213 #ifdef XKB_BUTTON_HINT
214 if (fwin->language_button)
215 wCoreDestroy(fwin->language_button);
216 fwin->language_button = NULL;
217 #endif
219 if (fwin->right_button)
220 wCoreDestroy(fwin->right_button);
221 fwin->right_button = NULL;
223 wCoreDestroy(fwin->titlebar);
224 fwin->titlebar = NULL;
226 fwin->top_width = 0;
228 } else {
229 /* if we didn't have a titlebar and are being requested for
230 * one, create it */
231 if (flags & WFF_TITLEBAR) {
232 fwin->top_width = theight;
234 fwin->flags.titlebar = 1;
235 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width + 1, theight);
237 if (flags & WFF_LEFT_BUTTON) {
238 fwin->flags.left_button = 1;
239 if (wPreferences.new_style == TS_NEW) {
240 fwin->left_button = wCoreCreate(fwin->core, 0, 0, bsize, bsize);
242 if (width < theight * 4)
243 fwin->flags.lbutton_dont_fit = 1;
244 else
245 XMapRaised(dpy, fwin->left_button->window);
247 } else if (wPreferences.new_style == TS_OLD) {
248 fwin->left_button =
249 wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
251 XSetWindowBackground(dpy, fwin->left_button->window,
252 scr->widget_texture->normal.pixel);
254 if (width < theight * 3)
255 fwin->flags.lbutton_dont_fit = 1;
256 else
257 XMapRaised(dpy, fwin->left_button->window);
259 } else {
260 fwin->left_button =
261 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
262 bsize, bsize);
264 XSetWindowBackground(dpy, fwin->left_button->window,
265 scr->widget_texture->dark.pixel);
267 if (width < theight * 3)
268 fwin->flags.lbutton_dont_fit = 1;
269 else
270 XMapRaised(dpy, fwin->left_button->window);
274 #ifdef XKB_BUTTON_HINT
275 if (flags & WFF_LANGUAGE_BUTTON) {
276 fwin->flags.language_button = 1;
277 if (wPreferences.new_style == TS_NEW) {
278 fwin->language_button = wCoreCreate(fwin->core, bsize, 0, bsize, bsize);
280 if (width < theight * 4)
281 fwin->flags.languagebutton_dont_fit = 1;
282 else
283 XMapRaised(dpy, fwin->language_button->window);
284 } else {
285 fwin->language_button =
286 wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
287 bsize, bsize);
289 XSetWindowBackground(dpy, fwin->language_button->window,
290 scr->widget_texture->normal.pixel);
292 if (width < theight * 3)
293 fwin->flags.languagebutton_dont_fit = 1;
294 else
295 XMapRaised(dpy, fwin->language_button->window);
298 #endif
300 if (flags & WFF_RIGHT_BUTTON) {
301 fwin->flags.right_button = 1;
302 if (wPreferences.new_style == TS_NEW) {
303 fwin->right_button =
304 wCoreCreate(fwin->core, width - bsize + 1, 0, bsize, bsize);
305 } else if (wPreferences.new_style == TS_OLD) {
306 fwin->right_button =
307 wCoreCreate(fwin->titlebar, width - bsize - 3,
308 (theight - bsize) / 2, bsize, bsize);
309 XSetWindowBackground(dpy, fwin->right_button->window,
310 scr->widget_texture->normal.pixel);
311 } else {
312 fwin->right_button =
313 wCoreCreate(fwin->titlebar, width-bsize-3,
314 (theight-bsize)/2, bsize, bsize);
315 XSetWindowBackground(dpy, fwin->right_button->window,
316 scr->widget_texture->dark.pixel);
319 if (width < theight * 2)
320 fwin->flags.rbutton_dont_fit = 1;
321 else
322 XMapRaised(dpy, fwin->right_button->window);
325 if (wPreferences.new_style == TS_NEW)
326 updateTitlebar(fwin);
328 XMapRaised(dpy, fwin->titlebar->window);
330 fwin->flags.need_texture_remake = 1;
333 checkTitleSize(fwin);
335 if (flags & WFF_RESIZEBAR) {
336 fwin->bottom_width = RESIZEBAR_HEIGHT;
338 if (!fwin->resizebar) {
339 fwin->flags.resizebar = 1;
340 fwin->resizebar = wCoreCreate(fwin->core, 0,
341 height + fwin->top_width, width, RESIZEBAR_HEIGHT);
342 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
343 if (width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
344 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH) / 2;
345 if (fwin->resizebar_corner_width < 0)
346 fwin->resizebar_corner_width = 0;
349 XMapWindow(dpy, fwin->resizebar->window);
350 XLowerWindow(dpy, fwin->resizebar->window);
352 fwin->flags.need_texture_remake = 1;
353 } else {
354 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height)
355 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
356 width, RESIZEBAR_HEIGHT);
358 } else {
359 fwin->bottom_width = 0;
361 if (fwin->resizebar) {
362 fwin->bottom_width = 0;
363 wCoreDestroy(fwin->resizebar);
364 fwin->resizebar = NULL;
368 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED))
369 wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
371 if (flags & WFF_BORDER)
372 XSetWindowBorderWidth(dpy, fwin->core->window, scr->frame_border_width);
373 else
374 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
376 /* setup object descriptors */
377 if (fwin->titlebar) {
378 fwin->titlebar->descriptor.handle_expose = handleExpose;
379 fwin->titlebar->descriptor.parent = fwin;
380 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
381 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
384 if (fwin->resizebar) {
385 fwin->resizebar->descriptor.handle_expose = handleExpose;
386 fwin->resizebar->descriptor.parent = fwin;
387 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
388 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
391 if (fwin->left_button) {
392 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
393 fwin->left_button->descriptor.parent = fwin;
394 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
395 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
398 #ifdef XKB_BUTTON_HINT
399 if (fwin->language_button) {
400 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
401 fwin->language_button->descriptor.parent = fwin;
402 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
403 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
405 #endif
407 if (fwin->right_button) {
408 fwin->right_button->descriptor.parent = fwin;
409 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
410 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
411 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
414 checkTitleSize(fwin);
416 allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_border_color), &fwin->border_pixel);
417 allocFrameBorderPixel(fwin->colormap, WMGetColorRGBDescription(scr->frame_selected_border_color), &fwin->selected_border_pixel);
419 if (flags & WFF_SELECTED) {
420 if (fwin->selected_border_pixel)
421 XSetWindowBorder(dpy, fwin->core->window, *fwin->selected_border_pixel);
423 else {
424 if (fwin->border_pixel)
425 XSetWindowBorder(dpy, fwin->core->window, *fwin->border_pixel);
429 void wFrameWindowDestroy(WFrameWindow * fwin)
431 int i;
433 if (fwin->left_button)
434 wCoreDestroy(fwin->left_button);
436 #ifdef XKB_BUTTON_HINT
437 if (fwin->language_button)
438 wCoreDestroy(fwin->language_button);
439 #endif
441 if (fwin->right_button)
442 wCoreDestroy(fwin->right_button);
444 if (fwin->resizebar)
445 wCoreDestroy(fwin->resizebar);
447 if (fwin->titlebar)
448 wCoreDestroy(fwin->titlebar);
450 RemoveFromStackList(fwin->core);
452 wCoreDestroy(fwin->core);
454 if (fwin->title)
455 wfree(fwin->title);
457 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
458 FREE_PIXMAP(fwin->title_back[i]);
459 if (wPreferences.new_style == TS_NEW) {
460 FREE_PIXMAP(fwin->lbutton_back[i]);
461 #ifdef XKB_BUTTON_HINT
462 FREE_PIXMAP(fwin->languagebutton_back[i]);
463 #endif
464 FREE_PIXMAP(fwin->rbutton_back[i]);
468 wfree(fwin);
471 void wFrameWindowChangeState(WFrameWindow * fwin, int state)
473 if (fwin->flags.state == state)
474 return;
476 fwin->flags.state = state;
477 fwin->flags.need_texture_change = 1;
479 wFrameWindowPaint(fwin);
482 static void updateTitlebar(WFrameWindow * fwin)
484 int x, w;
485 int theight;
487 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
489 if (theight > *fwin->title_max_height)
490 theight = *fwin->title_max_height;
492 if (theight < *fwin->title_min_height)
493 theight = *fwin->title_min_height;
495 x = 0;
496 w = fwin->core->width + 1;
498 if (wPreferences.new_style == TS_NEW) {
499 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
500 x = 0;
501 #ifdef XKB_BUTTON_HINT
502 if (fwin->language_button)
503 wCoreConfigure(fwin->language_button, 0, 0,
504 fwin->language_button->width, fwin->language_button->width);
505 #endif
506 } else {
507 #ifdef XKB_BUTTON_HINT
508 if (fwin->language_button)
509 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
510 fwin->language_button->width, fwin->language_button->width);
511 #endif
512 x = fwin->left_button->width;
513 w -= fwin->left_button->width;
515 #ifdef XKB_BUTTON_HINT
516 if (fwin->flags.hide_language_button || !fwin->language_button
517 || fwin->flags.languagebutton_dont_fit) {
518 } else {
519 x += fwin->language_button->width;
520 w -= fwin->language_button->width;
522 #endif
524 #ifdef XKB_BUTTON_HINT
525 else {
526 int bsize = theight - 7;
527 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
528 if (fwin->language_button)
529 wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
530 fwin->language_button->width, fwin->language_button->width);
531 } else {
532 if (fwin->language_button)
533 wCoreConfigure(fwin->language_button,
534 6 + fwin->left_button->width, (theight - bsize) / 2,
535 fwin->language_button->width, fwin->language_button->width);
538 #endif
540 if (wPreferences.new_style == TS_NEW) {
541 if (!fwin->flags.hide_right_button && fwin->right_button && !fwin->flags.rbutton_dont_fit)
542 w -= fwin->right_button->width;
545 if (wPreferences.new_style == TS_NEW || fwin->titlebar->width != w)
546 fwin->flags.need_texture_remake = 1;
548 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
551 void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
553 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
554 XUnmapWindow(dpy, fwin->right_button->window);
555 fwin->flags.hide_right_button = 1;
558 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
559 XUnmapWindow(dpy, fwin->left_button->window);
560 fwin->flags.hide_left_button = 1;
562 #ifdef XKB_BUTTON_HINT
563 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
564 XUnmapWindow(dpy, fwin->language_button->window);
565 fwin->flags.hide_language_button = 1;
567 #endif
569 if (fwin->titlebar) {
570 if (wPreferences.new_style == TS_NEW) {
571 updateTitlebar(fwin);
572 } else {
573 #ifdef XKB_BUTTON_HINT
574 updateTitlebar(fwin);
575 #else
576 XClearWindow(dpy, fwin->titlebar->window);
577 wFrameWindowPaint(fwin);
578 #endif
580 checkTitleSize(fwin);
584 void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
586 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
588 if (!fwin->flags.rbutton_dont_fit)
589 XMapWindow(dpy, fwin->right_button->window);
591 fwin->flags.hide_right_button = 0;
593 #ifdef XKB_BUTTON_HINT
594 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
596 if (!fwin->flags.languagebutton_dont_fit)
597 XMapWindow(dpy, fwin->language_button->window);
599 fwin->flags.hide_language_button = 0;
601 #endif
603 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
605 if (!fwin->flags.lbutton_dont_fit)
606 XMapWindow(dpy, fwin->left_button->window);
608 fwin->flags.hide_left_button = 0;
611 if (fwin->titlebar) {
612 if (wPreferences.new_style == TS_NEW) {
613 updateTitlebar(fwin);
614 } else {
615 XClearWindow(dpy, fwin->titlebar->window);
616 wFrameWindowPaint(fwin);
618 checkTitleSize(fwin);
622 static void
623 #ifdef XKB_BUTTON_HINT
624 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
625 int bwidth, int bheight, int left, int language, int right,
626 Pixmap * title, Pixmap * lbutton, Pixmap * languagebutton, Pixmap * rbutton)
627 #else
628 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
629 int bwidth, int bheight, int left, int right, Pixmap * title, Pixmap * lbutton, Pixmap * rbutton)
630 #endif
632 RImage *img;
633 RImage *limg, *rimg, *mimg;
634 #ifdef XKB_BUTTON_HINT
635 RImage *timg;
636 #endif
637 int x, w;
639 *title = None;
640 *lbutton = None;
641 *rbutton = None;
642 #ifdef XKB_BUTTON_HINT
643 *languagebutton = None;
644 #endif
646 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
647 if (!img) {
648 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
649 return;
652 if (wPreferences.new_style == TS_NEW) {
653 if (left)
654 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
655 else
656 limg = NULL;
658 x = 0;
659 w = img->width;
661 #ifdef XKB_BUTTON_HINT
662 if (language)
663 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
664 else
665 timg = NULL;
666 #endif
668 if (limg) {
669 RBevelImage(limg, RBEV_RAISED2);
670 if (!RConvertImage(scr->rcontext, limg, lbutton))
671 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
673 x += limg->width;
674 w -= limg->width;
675 RReleaseImage(limg);
677 #ifdef XKB_BUTTON_HINT
678 if (timg) {
679 RBevelImage(timg, RBEV_RAISED2);
680 if (!RConvertImage(scr->rcontext, timg, languagebutton))
681 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
683 x += timg->width;
684 w -= timg->width;
685 RReleaseImage(timg);
687 #endif
689 if (right)
690 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
691 else
692 rimg = NULL;
694 if (rimg) {
695 RBevelImage(rimg, RBEV_RAISED2);
696 if (!RConvertImage(scr->rcontext, rimg, rbutton))
697 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
699 w -= rimg->width;
700 RReleaseImage(rimg);
703 if (w != width) {
704 mimg = RGetSubImage(img, x, 0, w, img->height);
705 RBevelImage(mimg, RBEV_RAISED2);
707 if (!RConvertImage(scr->rcontext, mimg, title))
708 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
710 RReleaseImage(mimg);
711 } else {
712 RBevelImage(img, RBEV_RAISED2);
714 if (!RConvertImage(scr->rcontext, img, title))
715 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
717 } else {
718 RBevelImage(img, RBEV_RAISED2);
720 if (!RConvertImage(scr->rcontext, img, title))
721 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
724 RReleaseImage(img);
727 static void
728 renderResizebarTexture(WScreen * scr, WTexture * texture, int width, int height, int cwidth, Pixmap * pmap)
730 RImage *img;
731 RColor light;
732 RColor dark;
734 *pmap = None;
736 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
737 if (!img) {
738 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
739 return;
742 light.alpha = 0;
743 light.red = light.green = light.blue = 80;
745 dark.alpha = 0;
746 dark.red = dark.green = dark.blue = 40;
748 ROperateLine(img, RSubtractOperation, 0, 0, width - 1, 0, &dark);
749 ROperateLine(img, RAddOperation, 0, 1, width - 1, 1, &light);
751 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height - 1, &dark);
752 ROperateLine(img, RAddOperation, cwidth + 1, 2, cwidth + 1, height - 1, &light);
754 if (width > 1)
755 ROperateLine(img, RSubtractOperation, width - cwidth - 2, 2,
756 width - cwidth - 2, height - 1, &dark);
757 ROperateLine(img, RAddOperation, width - cwidth - 1, 2, width - cwidth - 1, height - 1, &light);
759 #ifdef SHADOW_RESIZEBAR
760 ROperateLine(img, RAddOperation, 0, 1, 0, height - 1, &light);
761 ROperateLine(img, RSubtractOperation, width - 1, 1, width - 1, height - 1, &dark);
762 ROperateLine(img, RSubtractOperation, 0, height - 1, width - 1, height - 1, &dark);
763 #endif /* SHADOW_RESIZEBAR */
765 if (!RConvertImage(scr->rcontext, img, pmap))
766 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
768 RReleaseImage(img);
771 static void updateTexture(WFrameWindow * fwin)
773 int i;
774 unsigned long pixel;
776 i = fwin->flags.state;
777 if (fwin->titlebar) {
778 if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
779 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window, fwin->title_back[i]);
780 if (wPreferences.new_style == TS_NEW) {
781 if (fwin->left_button && fwin->lbutton_back[i])
782 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
783 fwin->lbutton_back[i]);
785 #ifdef XKB_BUTTON_HINT
786 if (fwin->language_button && fwin->languagebutton_back[i])
787 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
788 fwin->languagebutton_back[i]);
789 #endif
791 if (fwin->right_button && fwin->rbutton_back[i])
792 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
793 fwin->rbutton_back[i]);
795 } else {
796 pixel = fwin->title_texture[i]->solid.normal.pixel;
797 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
798 if (wPreferences.new_style == TS_NEW) {
799 if (fwin->left_button)
800 XSetWindowBackground(dpy, fwin->left_button->window, pixel);
801 #ifdef XKB_BUTTON_HINT
802 if (fwin->language_button)
803 XSetWindowBackground(dpy, fwin->language_button->window, pixel);
804 #endif
805 if (fwin->right_button)
806 XSetWindowBackground(dpy, fwin->right_button->window, pixel);
809 XClearWindow(dpy, fwin->titlebar->window);
811 if (fwin->left_button) {
812 XClearWindow(dpy, fwin->left_button->window);
813 handleButtonExpose(&fwin->left_button->descriptor, NULL);
815 #ifdef XKB_BUTTON_HINT
816 if (fwin->language_button) {
817 XClearWindow(dpy, fwin->language_button->window);
818 handleButtonExpose(&fwin->language_button->descriptor, NULL);
820 #endif
821 if (fwin->right_button) {
822 XClearWindow(dpy, fwin->right_button->window);
823 handleButtonExpose(&fwin->right_button->descriptor, NULL);
828 static void remakeTexture(WFrameWindow * fwin, int state)
830 Pixmap pmap, lpmap, rpmap;
831 #ifdef XKB_BUTTON_HINT
832 Pixmap tpmap;
833 #endif
835 if (fwin->title_texture[state] && fwin->titlebar) {
836 FREE_PIXMAP(fwin->title_back[state]);
837 if (wPreferences.new_style == TS_NEW) {
838 FREE_PIXMAP(fwin->lbutton_back[state]);
839 FREE_PIXMAP(fwin->rbutton_back[state]);
840 #ifdef XKB_BUTTON_HINT
841 FREE_PIXMAP(fwin->languagebutton_back[state]);
842 #endif
845 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
846 int left, right;
847 int width;
848 #ifdef XKB_BUTTON_HINT
849 int language;
850 #endif
852 /* eventually surrounded by if new_style */
853 left = fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit;
854 #ifdef XKB_BUTTON_HINT
855 language = fwin->language_button && !fwin->flags.hide_language_button
856 && !fwin->flags.languagebutton_dont_fit;
857 #endif
858 right = fwin->right_button && !fwin->flags.hide_right_button
859 && !fwin->flags.rbutton_dont_fit;
861 width = fwin->core->width + 1;
863 #ifdef XKB_BUTTON_HINT
864 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
865 width, fwin->titlebar->height,
866 fwin->titlebar->height, fwin->titlebar->height,
867 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
868 #else
869 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
870 width, fwin->titlebar->height,
871 fwin->titlebar->height, fwin->titlebar->height,
872 left, right, &pmap, &lpmap, &rpmap);
873 #endif
875 fwin->title_back[state] = pmap;
876 if (wPreferences.new_style == TS_NEW) {
877 fwin->lbutton_back[state] = lpmap;
878 fwin->rbutton_back[state] = rpmap;
879 #ifdef XKB_BUTTON_HINT
880 fwin->languagebutton_back[state] = tpmap;
881 #endif
885 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
886 && fwin->resizebar && state == 0) {
888 FREE_PIXMAP(fwin->resizebar_back[0]);
890 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
892 renderResizebarTexture(fwin->screen_ptr,
893 fwin->resizebar_texture[0],
894 fwin->resizebar->width,
895 fwin->resizebar->height, fwin->resizebar_corner_width, &pmap);
897 fwin->resizebar_back[0] = pmap;
900 /* this part should be in updateTexture() */
901 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID)
902 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
903 else
904 XSetWindowBackground(dpy, fwin->resizebar->window,
905 fwin->resizebar_texture[0]->solid.normal.pixel);
907 XClearWindow(dpy, fwin->resizebar->window);
911 void wFrameWindowPaint(WFrameWindow * fwin)
913 WScreen *scr = fwin->screen_ptr;
914 int state;
916 state = fwin->flags.state;
918 if (fwin->flags.is_client_window_frame)
919 fwin->flags.justification = wPreferences.title_justification;
921 if (fwin->flags.need_texture_remake) {
922 int i;
924 fwin->flags.need_texture_remake = 0;
925 fwin->flags.need_texture_change = 0;
927 if (fwin->flags.single_texture) {
928 remakeTexture(fwin, 0);
929 updateTexture(fwin);
930 } else {
931 /* first render the texture for the current state... */
932 remakeTexture(fwin, state);
933 /* ... and paint it */
934 updateTexture(fwin);
936 for (i = 0; i < 3; i++) {
937 if (i != state)
938 remakeTexture(fwin, i);
943 if (fwin->flags.need_texture_change) {
944 fwin->flags.need_texture_change = 0;
946 updateTexture(fwin);
949 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
950 && fwin->title_texture[state]->any.type == WTEX_SOLID) {
951 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
952 fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
955 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
956 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
957 Window win;
958 int w, h;
959 int cw;
960 GC light_gc, dim_gc;
961 WTexSolid *texture = (WTexSolid *) fwin->resizebar_texture[0];
963 w = fwin->resizebar->width;
964 h = fwin->resizebar->height;
965 cw = fwin->resizebar_corner_width;
966 light_gc = texture->light_gc;
967 dim_gc = texture->dim_gc;
968 win = fwin->resizebar->window;
970 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
971 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
973 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
974 XDrawLine(dpy, win, light_gc, cw + 1, 2, cw + 1, h);
976 XDrawLine(dpy, win, dim_gc, w - cw - 2, 2, w - cw - 2, h);
977 XDrawLine(dpy, win, light_gc, w - cw - 1, 2, w - cw - 1, h);
979 #ifdef SHADOW_RESIZEBAR
980 XDrawLine(dpy, win, light_gc, 0, 1, 0, h - 1);
981 XDrawLine(dpy, win, dim_gc, w - 1, 2, w - 1, h - 1);
982 XDrawLine(dpy, win, dim_gc, 1, h - 1, cw, h - 1);
983 XDrawLine(dpy, win, dim_gc, cw + 2, h - 1, w - cw - 2, h - 1);
984 XDrawLine(dpy, win, dim_gc, w - cw, h - 1, w - 1, h - 1);
985 #endif /* SHADOW_RESIZEBAR */
988 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
989 int x, y, w, h;
990 int lofs = 6, rofs = 6;
991 int titlelen;
992 int allButtons = 1;
994 if (!wPreferences.new_style == TS_NEW) {
995 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
996 lofs += fwin->left_button->width + 3;
997 else
998 allButtons = 0;
1000 #ifdef XKB_BUTTON_HINT
1001 if (fwin->language_button && !fwin->flags.hide_language_button
1002 && !fwin->flags.languagebutton_dont_fit)
1003 lofs += fwin->language_button->width;
1004 else
1005 allButtons = 0;
1006 #endif
1008 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1009 rofs += fwin->right_button->width + 3;
1010 else
1011 allButtons = 0;
1013 #ifdef XKB_BUTTON_HINT
1014 fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1015 #endif
1017 if (fwin->title) {
1018 Drawable buf;
1019 char *title;
1021 title = ShrinkString(*fwin->font, fwin->title, fwin->titlebar->width - lofs - rofs);
1022 titlelen = strlen(title);
1023 w = WMWidthOfString(*fwin->font, title, titlelen);
1025 switch (fwin->flags.justification) {
1026 case WTJ_LEFT:
1027 x = lofs;
1028 break;
1030 case WTJ_RIGHT:
1031 x = fwin->titlebar->width - w - rofs;
1032 break;
1034 default:
1035 if (!allButtons)
1036 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1037 else
1038 x = (fwin->titlebar->width - w) / 2;
1039 break;
1042 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1043 h = WMFontHeight(*fwin->font);
1045 if (y*2 + h > *fwin->title_max_height)
1046 y = (*fwin->title_max_height - h) / 2;
1048 if (y*2 + h < *fwin->title_min_height)
1049 y = (*fwin->title_min_height - h) / 2;
1051 /* We use a w+2 buffer to have an extra pixel on the left and
1052 * another one on the right. This is because for some odd reason,
1053 * sometimes when using AA fonts (when libfreetype2 is compiled
1054 * with bytecode interpreter turned off), some fonts are drawn
1055 * starting from x = -1 not from 0 as requested. Observed with
1056 * capital A letter on the bold 'trebuchet ms' font. -Dan
1058 buf = XCreatePixmap(dpy, fwin->titlebar->window, w + 2, h, scr->w_depth);
1060 XSetClipMask(dpy, scr->copy_gc, None);
1062 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
1063 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1064 x - 1, y, w + 2, h, 0, 0);
1065 } else {
1066 XSetForeground(dpy, scr->copy_gc, fwin->title_texture[state]->solid.normal.pixel);
1067 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w + 2, h);
1070 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1); */
1071 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1072 *fwin->font, 1, 0, title, titlelen);
1074 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc, 0, 0, w + 2, h, x - 1, y);
1076 XFreePixmap(dpy, buf);
1078 wfree(title);
1081 if (fwin->left_button)
1082 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1083 if (fwin->right_button)
1084 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1085 #ifdef XKB_BUTTON_HINT
1086 if (fwin->language_button)
1087 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1088 #endif
1092 static void reconfigure(WFrameWindow * fwin, int x, int y, int width, int height, Bool dontMove)
1094 int k = (wPreferences.new_style == TS_NEW ? 4 : 3);
1095 int resizedHorizontally = 0;
1097 if (dontMove)
1098 XResizeWindow(dpy, fwin->core->window, width, height);
1099 else
1100 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1102 if (fwin->core->width != width) {
1103 fwin->flags.need_texture_remake = 1;
1104 resizedHorizontally = 1;
1107 fwin->core->width = width;
1108 fwin->core->height = height;
1110 if (fwin->titlebar && resizedHorizontally) {
1111 /* Check if the titlebar is wide enough to hold the buttons.
1112 * Temporarily remove them if can't
1114 if (fwin->left_button) {
1115 if (width < fwin->top_width * k && !fwin->flags.lbutton_dont_fit) {
1116 if (!fwin->flags.hide_left_button)
1117 XUnmapWindow(dpy, fwin->left_button->window);
1119 fwin->flags.lbutton_dont_fit = 1;
1120 } else if (width >= fwin->top_width * k && fwin->flags.lbutton_dont_fit) {
1121 if (!fwin->flags.hide_left_button)
1122 XMapWindow(dpy, fwin->left_button->window);
1124 fwin->flags.lbutton_dont_fit = 0;
1127 #ifdef XKB_BUTTON_HINT
1128 if (fwin->language_button) {
1129 if (width < fwin->top_width * k && !fwin->flags.languagebutton_dont_fit) {
1130 if (!fwin->flags.hide_language_button)
1131 XUnmapWindow(dpy, fwin->language_button->window);
1133 fwin->flags.languagebutton_dont_fit = 1;
1134 } else if (width >= fwin->top_width * k && fwin->flags.languagebutton_dont_fit) {
1135 if (!fwin->flags.hide_language_button)
1136 XMapWindow(dpy, fwin->language_button->window);
1138 fwin->flags.languagebutton_dont_fit = 0;
1141 #endif
1143 if (fwin->right_button) {
1144 if (width < fwin->top_width * 2 && !fwin->flags.rbutton_dont_fit) {
1145 if (!fwin->flags.hide_right_button)
1146 XUnmapWindow(dpy, fwin->right_button->window);
1148 fwin->flags.rbutton_dont_fit = 1;
1149 } else if (width >= fwin->top_width * 2 && fwin->flags.rbutton_dont_fit) {
1150 if (!fwin->flags.hide_right_button)
1151 XMapWindow(dpy, fwin->right_button->window);
1153 fwin->flags.rbutton_dont_fit = 0;
1157 if (wPreferences.new_style == TS_NEW) {
1158 if (fwin->right_button)
1159 XMoveWindow(dpy, fwin->right_button->window,
1160 width - fwin->right_button->width + 1, 0);
1161 } else {
1162 if (fwin->right_button)
1163 XMoveWindow(dpy, fwin->right_button->window,
1164 width - fwin->right_button->width - 3,
1165 (fwin->titlebar->height - fwin->right_button->height) / 2);
1167 updateTitlebar(fwin);
1168 checkTitleSize(fwin);
1171 if (fwin->resizebar) {
1172 wCoreConfigure(fwin->resizebar, 0,
1173 fwin->core->height - fwin->resizebar->height,
1174 fwin->core->width, fwin->resizebar->height);
1176 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1177 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH)
1178 fwin->resizebar_corner_width = fwin->core->width / 2;
1182 void wFrameWindowConfigure(WFrameWindow * fwin, int x, int y, int width, int height)
1184 reconfigure(fwin, x, y, width, height, False);
1187 void wFrameWindowResize(WFrameWindow * fwin, int width, int height)
1189 reconfigure(fwin, 0, 0, width, height, True);
1192 int wFrameWindowChangeTitle(WFrameWindow * fwin, char *new_title)
1194 /* check if the title is the same as before */
1195 if (fwin->title) {
1196 if (new_title && (strcmp(fwin->title, new_title) == 0))
1197 return 0;
1198 } else {
1199 if (!new_title)
1200 return 0;
1203 if (fwin->title)
1204 wfree(fwin->title);
1206 fwin->title = wstrdup(new_title);
1208 if (fwin->titlebar) {
1209 XClearWindow(dpy, fwin->titlebar->window);
1211 wFrameWindowPaint(fwin);
1213 checkTitleSize(fwin);
1215 return 1;
1218 #ifdef XKB_BUTTON_HINT
1219 void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
1221 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1222 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
1224 #endif /* XKB_BUTTON_HINT */
1226 /*********************************************************************/
1228 static void handleExpose(WObjDescriptor * desc, XEvent * event)
1230 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1232 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1233 fwin->flags.repaint_only_titlebar = 1;
1234 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1235 fwin->flags.repaint_only_resizebar = 1;
1236 wFrameWindowPaint(fwin);
1237 fwin->flags.repaint_only_titlebar = 0;
1238 fwin->flags.repaint_only_resizebar = 0;
1241 static void checkTitleSize(WFrameWindow * fwin)
1243 int width;
1245 if (!fwin->title) {
1246 fwin->flags.incomplete_title = 0;
1247 return;
1250 if (!fwin->titlebar) {
1251 fwin->flags.incomplete_title = 1;
1252 return;
1253 } else {
1254 width = fwin->titlebar->width - 6 - 6;
1257 if (!wPreferences.new_style == TS_NEW) {
1258 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1259 width -= fwin->left_button->width + 3;
1261 #ifdef XKB_BUTTON_HINT
1262 if (fwin->language_button && !fwin->flags.hide_language_button
1263 && !fwin->flags.languagebutton_dont_fit)
1264 width -= fwin->language_button->width + 3;
1265 #endif
1267 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1268 width -= fwin->right_button->width + 3;
1271 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width)
1272 fwin->flags.incomplete_title = 1;
1273 else
1274 fwin->flags.incomplete_title = 0;
1277 static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
1279 WScreen *scr = button->screen_ptr;
1280 GC copy_gc = scr->copy_gc;
1281 int x = 0, y = 0, d = 0;
1282 int left = 0, width = 0;
1284 /* setup stuff according to the state */
1285 if (pushed) {
1286 if (image) {
1287 if (image->width >= image->height * 2) {
1288 /* the image contains 2 pictures: the second is for the
1289 * pushed state */
1290 width = image->width / 2;
1291 left = image->width / 2;
1292 } else {
1293 width = image->width;
1296 XSetClipMask(dpy, copy_gc, None);
1297 if (wPreferences.new_style == TS_NEXT)
1298 XSetForeground(dpy, copy_gc, scr->black_pixel);
1299 else
1300 XSetForeground(dpy, copy_gc, scr->white_pixel);
1302 d = 1;
1303 if (wPreferences.new_style == TS_NEW) {
1304 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1305 XSetForeground(dpy, copy_gc, scr->black_pixel);
1306 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1307 } else if (wPreferences.new_style == TS_OLD) {
1308 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1309 XSetForeground(dpy, copy_gc, scr->black_pixel);
1310 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1311 } else {
1312 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1313 XSetForeground(dpy, copy_gc, scr->black_pixel);
1314 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1316 } else {
1317 XClearWindow(dpy, button->window);
1319 if (image) {
1320 if (image->width >= image->height * 2)
1321 width = image->width / 2;
1322 else
1323 width = image->width;
1325 d = 0;
1327 if (wPreferences.new_style == TS_NEW) {
1328 if (texture->any.type == WTEX_SOLID || pushed)
1329 wDrawBevel(button->window, button->width, button->height,
1330 (WTexSolid *) texture, WREL_RAISED);
1331 } else {
1332 wDrawBevel(button->window, button->width, button->height,
1333 scr->widget_texture, WREL_RAISED);
1337 if (image) {
1338 /* display image */
1339 XSetClipMask(dpy, copy_gc, image->mask);
1340 x = (button->width - width) / 2 + d;
1341 y = (button->height - image->height) / 2 + d;
1342 XSetClipOrigin(dpy, copy_gc, x - left, y);
1343 if (!wPreferences.new_style == TS_NEW) {
1344 XSetForeground(dpy, copy_gc, scr->black_pixel);
1345 if (!pushed) {
1346 if (image->depth == 1)
1347 XCopyPlane(dpy, image->image, button->window, copy_gc,
1348 left, 0, width, image->height, x, y, 1);
1349 else
1350 XCopyArea(dpy, image->image, button->window, copy_gc,
1351 left, 0, width, image->height, x, y);
1352 } else {
1353 if (wPreferences.new_style == TS_OLD) {
1354 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1355 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1356 button->width, button->height);
1357 } else {
1358 XSetForeground(dpy, copy_gc, scr->black_pixel);
1359 XCopyArea(dpy, image->image, button->window, copy_gc,
1360 left, 0, width, image->height, x, y);
1363 } else {
1364 if (pushed) {
1365 XSetForeground(dpy, copy_gc, scr->black_pixel);
1366 } else {
1367 XSetForeground(dpy, copy_gc, color);
1368 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1370 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1375 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
1377 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1378 WCoreWindow *button = (WCoreWindow *) desc->self;
1380 #ifdef XKB_BUTTON_HINT
1381 if (button == fwin->language_button) {
1382 if (wPreferences.modelock)
1383 paintButton(button, fwin->title_texture[fwin->flags.state],
1384 WMColorPixel(fwin->title_color[fwin->flags.state]),
1385 fwin->languagebutton_image, False);
1386 } else
1387 #endif
1388 if (button == fwin->left_button)
1389 paintButton(button, fwin->title_texture[fwin->flags.state],
1390 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
1391 else
1392 paintButton(button, fwin->title_texture[fwin->flags.state],
1393 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
1396 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
1398 WFrameWindow *fwin = desc->parent;
1399 WCoreWindow *titlebar = desc->self;
1401 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1402 if (fwin->on_dblclick_titlebar)
1403 (*fwin->on_dblclick_titlebar) (titlebar, fwin->child, event);
1404 } else {
1405 if (fwin->on_mousedown_titlebar)
1406 (*fwin->on_mousedown_titlebar) (titlebar, fwin->child, event);
1410 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event)
1412 WFrameWindow *fwin = desc->parent;
1413 WCoreWindow *resizebar = desc->self;
1415 if (fwin->on_mousedown_resizebar)
1416 (*fwin->on_mousedown_resizebar) (resizebar, fwin->child, event);
1419 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
1421 WFrameWindow *fwin = desc->parent;
1422 WCoreWindow *button = desc->self;
1423 WPixmap *image;
1424 XEvent ev;
1425 int done = 0, execute = 1;
1426 WTexture *texture;
1427 unsigned long pixel;
1428 int clickButton = event->xbutton.button;
1430 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1431 if (button == fwin->right_button && fwin->on_dblclick_right)
1432 (*fwin->on_dblclick_right) (button, fwin->child, event);
1434 return;
1437 if (button == fwin->left_button)
1438 image = fwin->lbutton_image;
1439 else
1440 image = fwin->rbutton_image;
1442 #ifdef XKB_BUTTON_HINT
1443 if (button == fwin->language_button) {
1444 if (!wPreferences.modelock)
1445 return;
1446 image = fwin->languagebutton_image;
1448 #endif
1450 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1451 texture = fwin->title_texture[fwin->flags.state];
1452 paintButton(button, texture, pixel, image, True);
1454 while (!done) {
1455 WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
1456 | ButtonPressMask | ExposureMask, &ev);
1457 switch (ev.type) {
1458 case LeaveNotify:
1459 execute = 0;
1460 paintButton(button, texture, pixel, image, False);
1461 break;
1463 case EnterNotify:
1464 execute = 1;
1465 paintButton(button, texture, pixel, image, True);
1466 break;
1468 case ButtonPress:
1469 break;
1471 case ButtonRelease:
1472 if (ev.xbutton.button == clickButton)
1473 done = 1;
1474 break;
1476 default:
1477 WMHandleEvent(&ev);
1480 paintButton(button, texture, pixel, image, False);
1482 if (execute) {
1483 if (button == fwin->left_button) {
1484 if (fwin->on_click_left)
1485 (*fwin->on_click_left) (button, fwin->child, &ev);
1486 } else if (button == fwin->right_button) {
1487 if (fwin->on_click_right)
1488 (*fwin->on_click_right) (button, fwin->child, &ev);
1490 #ifdef XKB_BUTTON_HINT
1491 else if (button == fwin->language_button) {
1492 if (fwin->on_click_language)
1493 (*fwin->on_click_language) (button, fwin->child, &ev);
1495 #endif