WPrefs: new Docks pannel, to change auto-expand/collapse/etc delays
[wmaker-crm.git] / src / framewin.c
blob67cda92e383f2c87ceebaf500e4eb4af1f0a01bb
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, scr->frame_border_pixel);
118 /* setup stacking information */
119 fwin->core->stacking = wmalloc(sizeof(WStacking));
120 fwin->core->stacking->above = NULL;
121 fwin->core->stacking->under = NULL;
122 fwin->core->stacking->child_of = NULL;
123 fwin->core->stacking->window_level = wlevel;
125 AddToStackList(fwin->core);
127 wFrameWindowUpdateBorders(fwin, flags);
129 return fwin;
132 void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
134 int theight;
135 int bsize;
136 int width, height;
137 int i;
138 WScreen *scr = fwin->screen_ptr;
140 width = fwin->core->width;
141 if (flags & WFF_IS_SHADED)
142 height = -1;
143 else
144 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
146 if (flags & WFF_TITLEBAR) {
147 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
149 if (theight > *fwin->title_max_height)
150 theight = *fwin->title_max_height;
152 if (theight < *fwin->title_min_height)
153 theight = *fwin->title_min_height;
154 } else {
155 theight = 0;
158 if (wPreferences.new_style == TS_NEW) {
159 bsize = theight;
160 } else if (wPreferences.new_style == TS_OLD) {
161 bsize = theight - 7;
162 } else {
163 bsize = theight - 8;
166 if (fwin->titlebar) {
167 /* if we had a titlebar and is requesting for one,
168 * check if the size has changed and resize it */
169 if (flags & WFF_TITLEBAR) {
170 fwin->top_width = theight;
172 fwin->flags.need_texture_remake = 1;
174 if (wPreferences.new_style == TS_NEW) {
175 if (fwin->left_button)
176 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
177 #ifdef XKB_BUTTON_HINT
178 if (fwin->language_button) {
179 if (fwin->flags.hide_left_button || !fwin->left_button
180 || fwin->flags.lbutton_dont_fit)
181 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
182 else
183 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
185 #endif
187 if (fwin->right_button)
188 wCoreConfigure(fwin->right_button, width - bsize + 1, 0, bsize, bsize);
190 } else { /* !new_style */
191 if (fwin->left_button)
192 wCoreConfigure(fwin->left_button, 3, (theight - bsize) / 2, bsize, bsize);
193 #ifdef XKB_BUTTON_HINT
194 if (fwin->language_button)
195 wCoreConfigure(fwin->language_button, 6 + bsize, (theight - bsize) / 2,
196 bsize, bsize);
197 #endif
199 if (fwin->right_button)
200 wCoreConfigure(fwin->right_button, width - bsize - 3,
201 (theight - bsize) / 2, bsize, bsize);
203 updateTitlebar(fwin);
204 } else {
205 /* we had a titlebar, but now we don't need it anymore */
206 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
207 FREE_PIXMAP(fwin->title_back[i]);
208 if (wPreferences.new_style == TS_NEW) {
209 FREE_PIXMAP(fwin->lbutton_back[i]);
210 FREE_PIXMAP(fwin->rbutton_back[i]);
211 #ifdef XKB_BUTTON_HINT
212 FREE_PIXMAP(fwin->languagebutton_back[i]);
213 #endif
216 if (fwin->left_button)
217 wCoreDestroy(fwin->left_button);
218 fwin->left_button = NULL;
220 #ifdef XKB_BUTTON_HINT
221 if (fwin->language_button)
222 wCoreDestroy(fwin->language_button);
223 fwin->language_button = NULL;
224 #endif
226 if (fwin->right_button)
227 wCoreDestroy(fwin->right_button);
228 fwin->right_button = NULL;
230 wCoreDestroy(fwin->titlebar);
231 fwin->titlebar = NULL;
233 fwin->top_width = 0;
235 } else {
236 /* if we didn't have a titlebar and are being requested for
237 * one, create it */
238 if (flags & WFF_TITLEBAR) {
239 fwin->top_width = theight;
241 fwin->flags.titlebar = 1;
242 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width + 1, theight);
244 if (flags & WFF_LEFT_BUTTON) {
245 fwin->flags.left_button = 1;
246 if (wPreferences.new_style == TS_NEW) {
247 fwin->left_button = wCoreCreate(fwin->core, 0, 0, bsize, bsize);
249 if (width < theight * 4)
250 fwin->flags.lbutton_dont_fit = 1;
251 else
252 XMapRaised(dpy, fwin->left_button->window);
254 } else if (wPreferences.new_style == TS_OLD) {
255 fwin->left_button =
256 wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
258 XSetWindowBackground(dpy, fwin->left_button->window,
259 scr->widget_texture->normal.pixel);
261 if (width < theight * 3)
262 fwin->flags.lbutton_dont_fit = 1;
263 else
264 XMapRaised(dpy, fwin->left_button->window);
266 } else {
267 fwin->left_button =
268 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
269 bsize, bsize);
271 XSetWindowBackground(dpy, fwin->left_button->window,
272 scr->widget_texture->dark.pixel);
274 if (width < theight * 3)
275 fwin->flags.lbutton_dont_fit = 1;
276 else
277 XMapRaised(dpy, fwin->left_button->window);
281 #ifdef XKB_BUTTON_HINT
282 if (flags & WFF_LANGUAGE_BUTTON) {
283 fwin->flags.language_button = 1;
284 if (wPreferences.new_style == TS_NEW) {
285 fwin->language_button = wCoreCreate(fwin->core, bsize, 0, bsize, bsize);
287 if (width < theight * 4)
288 fwin->flags.languagebutton_dont_fit = 1;
289 else
290 XMapRaised(dpy, fwin->language_button->window);
291 } else {
292 fwin->language_button =
293 wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
294 bsize, bsize);
296 XSetWindowBackground(dpy, fwin->language_button->window,
297 scr->widget_texture->normal.pixel);
299 if (width < theight * 3)
300 fwin->flags.languagebutton_dont_fit = 1;
301 else
302 XMapRaised(dpy, fwin->language_button->window);
305 #endif
307 if (flags & WFF_RIGHT_BUTTON) {
308 fwin->flags.right_button = 1;
309 if (wPreferences.new_style == TS_NEW) {
310 fwin->right_button =
311 wCoreCreate(fwin->core, width - bsize + 1, 0, bsize, bsize);
312 } else if (wPreferences.new_style == TS_OLD) {
313 fwin->right_button =
314 wCoreCreate(fwin->titlebar, width - bsize - 3,
315 (theight - bsize) / 2, bsize, bsize);
316 XSetWindowBackground(dpy, fwin->right_button->window,
317 scr->widget_texture->normal.pixel);
318 } else {
319 fwin->right_button =
320 wCoreCreate(fwin->titlebar, width-bsize-3,
321 (theight-bsize)/2, bsize, bsize);
322 XSetWindowBackground(dpy, fwin->right_button->window,
323 scr->widget_texture->dark.pixel);
326 if (width < theight * 2)
327 fwin->flags.rbutton_dont_fit = 1;
328 else
329 XMapRaised(dpy, fwin->right_button->window);
332 if (wPreferences.new_style == TS_NEW)
333 updateTitlebar(fwin);
335 XMapRaised(dpy, fwin->titlebar->window);
337 fwin->flags.need_texture_remake = 1;
340 checkTitleSize(fwin);
342 if (flags & WFF_RESIZEBAR) {
343 fwin->bottom_width = RESIZEBAR_HEIGHT;
345 if (!fwin->resizebar) {
346 fwin->flags.resizebar = 1;
347 fwin->resizebar = wCoreCreate(fwin->core, 0,
348 height + fwin->top_width, width, RESIZEBAR_HEIGHT);
349 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
350 if (width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
351 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH) / 2;
352 if (fwin->resizebar_corner_width < 0)
353 fwin->resizebar_corner_width = 0;
356 XMapWindow(dpy, fwin->resizebar->window);
357 XLowerWindow(dpy, fwin->resizebar->window);
359 fwin->flags.need_texture_remake = 1;
360 } else {
361 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height)
362 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
363 width, RESIZEBAR_HEIGHT);
365 } else {
366 fwin->bottom_width = 0;
368 if (fwin->resizebar) {
369 fwin->bottom_width = 0;
370 wCoreDestroy(fwin->resizebar);
371 fwin->resizebar = NULL;
375 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED))
376 wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
378 if (flags & WFF_BORDER)
379 XSetWindowBorderWidth(dpy, fwin->core->window, FRAME_BORDER_WIDTH);
380 else
381 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
383 /* setup object descriptors */
384 if (fwin->titlebar) {
385 fwin->titlebar->descriptor.handle_expose = handleExpose;
386 fwin->titlebar->descriptor.parent = fwin;
387 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
388 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
391 if (fwin->resizebar) {
392 fwin->resizebar->descriptor.handle_expose = handleExpose;
393 fwin->resizebar->descriptor.parent = fwin;
394 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
395 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
398 if (fwin->left_button) {
399 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
400 fwin->left_button->descriptor.parent = fwin;
401 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
402 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
405 #ifdef XKB_BUTTON_HINT
406 if (fwin->language_button) {
407 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
408 fwin->language_button->descriptor.parent = fwin;
409 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
410 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
412 #endif
414 if (fwin->right_button) {
415 fwin->right_button->descriptor.parent = fwin;
416 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
417 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
418 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
421 checkTitleSize(fwin);
423 if (fwin->border_pixel)
424 XSetWindowBorder(dpy, fwin->core->window, *fwin->border_pixel);
427 void wFrameWindowDestroy(WFrameWindow * fwin)
429 int i;
431 if (fwin->left_button)
432 wCoreDestroy(fwin->left_button);
434 #ifdef XKB_BUTTON_HINT
435 if (fwin->language_button)
436 wCoreDestroy(fwin->language_button);
437 #endif
439 if (fwin->right_button)
440 wCoreDestroy(fwin->right_button);
442 if (fwin->resizebar)
443 wCoreDestroy(fwin->resizebar);
445 if (fwin->titlebar)
446 wCoreDestroy(fwin->titlebar);
448 RemoveFromStackList(fwin->core);
450 wCoreDestroy(fwin->core);
452 if (fwin->title)
453 wfree(fwin->title);
455 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
456 FREE_PIXMAP(fwin->title_back[i]);
457 if (wPreferences.new_style == TS_NEW) {
458 FREE_PIXMAP(fwin->lbutton_back[i]);
459 #ifdef XKB_BUTTON_HINT
460 FREE_PIXMAP(fwin->languagebutton_back[i]);
461 #endif
462 FREE_PIXMAP(fwin->rbutton_back[i]);
466 wfree(fwin);
469 void wFrameWindowChangeState(WFrameWindow * fwin, int state)
471 if (fwin->flags.state == state)
472 return;
474 fwin->flags.state = state;
475 fwin->flags.need_texture_change = 1;
477 wFrameWindowPaint(fwin);
480 static void updateTitlebar(WFrameWindow * fwin)
482 int x, w;
483 int theight;
485 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
487 if (theight > *fwin->title_max_height)
488 theight = *fwin->title_max_height;
490 if (theight < *fwin->title_min_height)
491 theight = *fwin->title_min_height;
493 x = 0;
494 w = fwin->core->width + 1;
496 if (wPreferences.new_style == TS_NEW) {
497 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
498 x = 0;
499 #ifdef XKB_BUTTON_HINT
500 if (fwin->language_button)
501 wCoreConfigure(fwin->language_button, 0, 0,
502 fwin->language_button->width, fwin->language_button->width);
503 #endif
504 } else {
505 #ifdef XKB_BUTTON_HINT
506 if (fwin->language_button)
507 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
508 fwin->language_button->width, fwin->language_button->width);
509 #endif
510 x = fwin->left_button->width;
511 w -= fwin->left_button->width;
513 #ifdef XKB_BUTTON_HINT
514 if (fwin->flags.hide_language_button || !fwin->language_button
515 || fwin->flags.languagebutton_dont_fit) {
516 } else {
517 x += fwin->language_button->width;
518 w -= fwin->language_button->width;
520 #endif
522 #ifdef XKB_BUTTON_HINT
523 else {
524 int bsize = theight - 7;
525 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
526 if (fwin->language_button)
527 wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
528 fwin->language_button->width, fwin->language_button->width);
529 } else {
530 if (fwin->language_button)
531 wCoreConfigure(fwin->language_button,
532 6 + fwin->left_button->width, (theight - bsize) / 2,
533 fwin->language_button->width, fwin->language_button->width);
536 #endif
538 if (wPreferences.new_style == TS_NEW) {
539 if (!fwin->flags.hide_right_button && fwin->right_button && !fwin->flags.rbutton_dont_fit)
540 w -= fwin->right_button->width;
543 if (wPreferences.new_style == TS_NEW || fwin->titlebar->width != w)
544 fwin->flags.need_texture_remake = 1;
546 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
549 void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
551 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
552 XUnmapWindow(dpy, fwin->right_button->window);
553 fwin->flags.hide_right_button = 1;
556 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
557 XUnmapWindow(dpy, fwin->left_button->window);
558 fwin->flags.hide_left_button = 1;
560 #ifdef XKB_BUTTON_HINT
561 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
562 XUnmapWindow(dpy, fwin->language_button->window);
563 fwin->flags.hide_language_button = 1;
565 #endif
567 if (fwin->titlebar) {
568 if (wPreferences.new_style == TS_NEW) {
569 updateTitlebar(fwin);
570 } else {
571 #ifdef XKB_BUTTON_HINT
572 updateTitlebar(fwin);
573 #else
574 XClearWindow(dpy, fwin->titlebar->window);
575 wFrameWindowPaint(fwin);
576 #endif
578 checkTitleSize(fwin);
582 void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
584 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
586 if (!fwin->flags.rbutton_dont_fit)
587 XMapWindow(dpy, fwin->right_button->window);
589 fwin->flags.hide_right_button = 0;
591 #ifdef XKB_BUTTON_HINT
592 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
594 if (!fwin->flags.languagebutton_dont_fit)
595 XMapWindow(dpy, fwin->language_button->window);
597 fwin->flags.hide_language_button = 0;
599 #endif
601 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
603 if (!fwin->flags.lbutton_dont_fit)
604 XMapWindow(dpy, fwin->left_button->window);
606 fwin->flags.hide_left_button = 0;
609 if (fwin->titlebar) {
610 if (wPreferences.new_style == TS_NEW) {
611 updateTitlebar(fwin);
612 } else {
613 XClearWindow(dpy, fwin->titlebar->window);
614 wFrameWindowPaint(fwin);
616 checkTitleSize(fwin);
620 static void
621 #ifdef XKB_BUTTON_HINT
622 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
623 int bwidth, int bheight, int left, int language, int right,
624 Pixmap * title, Pixmap * lbutton, Pixmap * languagebutton, Pixmap * rbutton)
625 #else
626 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
627 int bwidth, int bheight, int left, int right, Pixmap * title, Pixmap * lbutton, Pixmap * rbutton)
628 #endif
630 RImage *img;
631 RImage *limg, *rimg, *mimg;
632 #ifdef XKB_BUTTON_HINT
633 RImage *timg;
634 #endif
635 int x, w;
637 *title = None;
638 *lbutton = None;
639 *rbutton = None;
640 #ifdef XKB_BUTTON_HINT
641 *languagebutton = None;
642 #endif
644 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
645 if (!img) {
646 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
647 return;
650 if (wPreferences.new_style == TS_NEW) {
651 if (left)
652 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
653 else
654 limg = NULL;
656 x = 0;
657 w = img->width;
659 #ifdef XKB_BUTTON_HINT
660 if (language)
661 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
662 else
663 timg = NULL;
664 #endif
666 if (limg) {
667 RBevelImage(limg, RBEV_RAISED2);
668 if (!RConvertImage(scr->rcontext, limg, lbutton))
669 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
671 x += limg->width;
672 w -= limg->width;
673 RReleaseImage(limg);
675 #ifdef XKB_BUTTON_HINT
676 if (timg) {
677 RBevelImage(timg, RBEV_RAISED2);
678 if (!RConvertImage(scr->rcontext, timg, languagebutton))
679 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
681 x += timg->width;
682 w -= timg->width;
683 RReleaseImage(timg);
685 #endif
687 if (right)
688 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
689 else
690 rimg = NULL;
692 if (rimg) {
693 RBevelImage(rimg, RBEV_RAISED2);
694 if (!RConvertImage(scr->rcontext, rimg, rbutton))
695 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
697 w -= rimg->width;
698 RReleaseImage(rimg);
701 if (w != width) {
702 mimg = RGetSubImage(img, x, 0, w, img->height);
703 RBevelImage(mimg, RBEV_RAISED2);
705 if (!RConvertImage(scr->rcontext, mimg, title))
706 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
708 RReleaseImage(mimg);
709 } else {
710 RBevelImage(img, RBEV_RAISED2);
712 if (!RConvertImage(scr->rcontext, img, title))
713 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
715 } else {
716 RBevelImage(img, RBEV_RAISED2);
718 if (!RConvertImage(scr->rcontext, img, title))
719 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
722 RReleaseImage(img);
725 static void
726 renderResizebarTexture(WScreen * scr, WTexture * texture, int width, int height, int cwidth, Pixmap * pmap)
728 RImage *img;
729 RColor light;
730 RColor dark;
732 *pmap = None;
734 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
735 if (!img) {
736 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
737 return;
740 light.alpha = 0;
741 light.red = light.green = light.blue = 80;
743 dark.alpha = 0;
744 dark.red = dark.green = dark.blue = 40;
746 ROperateLine(img, RSubtractOperation, 0, 0, width - 1, 0, &dark);
747 ROperateLine(img, RAddOperation, 0, 1, width - 1, 1, &light);
749 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height - 1, &dark);
750 ROperateLine(img, RAddOperation, cwidth + 1, 2, cwidth + 1, height - 1, &light);
752 if (width > 1)
753 ROperateLine(img, RSubtractOperation, width - cwidth - 2, 2,
754 width - cwidth - 2, height - 1, &dark);
755 ROperateLine(img, RAddOperation, width - cwidth - 1, 2, width - cwidth - 1, height - 1, &light);
757 #ifdef SHADOW_RESIZEBAR
758 ROperateLine(img, RAddOperation, 0, 1, 0, height - 1, &light);
759 ROperateLine(img, RSubtractOperation, width - 1, 1, width - 1, height - 1, &dark);
760 ROperateLine(img, RSubtractOperation, 0, height - 1, width - 1, height - 1, &dark);
761 #endif /* SHADOW_RESIZEBAR */
763 if (!RConvertImage(scr->rcontext, img, pmap))
764 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
766 RReleaseImage(img);
769 static void updateTexture(WFrameWindow * fwin)
771 int i;
772 unsigned long pixel;
774 i = fwin->flags.state;
775 if (fwin->titlebar) {
776 if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
777 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window, fwin->title_back[i]);
778 if (wPreferences.new_style == TS_NEW) {
779 if (fwin->left_button && fwin->lbutton_back[i])
780 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
781 fwin->lbutton_back[i]);
783 #ifdef XKB_BUTTON_HINT
784 if (fwin->language_button && fwin->languagebutton_back[i])
785 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
786 fwin->languagebutton_back[i]);
787 #endif
789 if (fwin->right_button && fwin->rbutton_back[i])
790 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
791 fwin->rbutton_back[i]);
793 } else {
794 pixel = fwin->title_texture[i]->solid.normal.pixel;
795 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
796 if (wPreferences.new_style == TS_NEW) {
797 if (fwin->left_button)
798 XSetWindowBackground(dpy, fwin->left_button->window, pixel);
799 #ifdef XKB_BUTTON_HINT
800 if (fwin->language_button)
801 XSetWindowBackground(dpy, fwin->language_button->window, pixel);
802 #endif
803 if (fwin->right_button)
804 XSetWindowBackground(dpy, fwin->right_button->window, pixel);
807 XClearWindow(dpy, fwin->titlebar->window);
809 if (fwin->left_button) {
810 XClearWindow(dpy, fwin->left_button->window);
811 handleButtonExpose(&fwin->left_button->descriptor, NULL);
813 #ifdef XKB_BUTTON_HINT
814 if (fwin->language_button) {
815 XClearWindow(dpy, fwin->language_button->window);
816 handleButtonExpose(&fwin->language_button->descriptor, NULL);
818 #endif
819 if (fwin->right_button) {
820 XClearWindow(dpy, fwin->right_button->window);
821 handleButtonExpose(&fwin->right_button->descriptor, NULL);
826 static void remakeTexture(WFrameWindow * fwin, int state)
828 Pixmap pmap, lpmap, rpmap;
829 #ifdef XKB_BUTTON_HINT
830 Pixmap tpmap;
831 #endif
833 if (fwin->title_texture[state] && fwin->titlebar) {
834 FREE_PIXMAP(fwin->title_back[state]);
835 if (wPreferences.new_style == TS_NEW) {
836 FREE_PIXMAP(fwin->lbutton_back[state]);
837 FREE_PIXMAP(fwin->rbutton_back[state]);
838 #ifdef XKB_BUTTON_HINT
839 FREE_PIXMAP(fwin->languagebutton_back[state]);
840 #endif
843 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
844 int left, right;
845 int width;
846 #ifdef XKB_BUTTON_HINT
847 int language;
848 #endif
850 /* eventually surrounded by if new_style */
851 left = fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit;
852 #ifdef XKB_BUTTON_HINT
853 language = fwin->language_button && !fwin->flags.hide_language_button
854 && !fwin->flags.languagebutton_dont_fit;
855 #endif
856 right = fwin->right_button && !fwin->flags.hide_right_button
857 && !fwin->flags.rbutton_dont_fit;
859 width = fwin->core->width + 1;
861 #ifdef XKB_BUTTON_HINT
862 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
863 width, fwin->titlebar->height,
864 fwin->titlebar->height, fwin->titlebar->height,
865 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
866 #else
867 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
868 width, fwin->titlebar->height,
869 fwin->titlebar->height, fwin->titlebar->height,
870 left, right, &pmap, &lpmap, &rpmap);
871 #endif
873 fwin->title_back[state] = pmap;
874 if (wPreferences.new_style == TS_NEW) {
875 fwin->lbutton_back[state] = lpmap;
876 fwin->rbutton_back[state] = rpmap;
877 #ifdef XKB_BUTTON_HINT
878 fwin->languagebutton_back[state] = tpmap;
879 #endif
883 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
884 && fwin->resizebar && state == 0) {
886 FREE_PIXMAP(fwin->resizebar_back[0]);
888 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
890 renderResizebarTexture(fwin->screen_ptr,
891 fwin->resizebar_texture[0],
892 fwin->resizebar->width,
893 fwin->resizebar->height, fwin->resizebar_corner_width, &pmap);
895 fwin->resizebar_back[0] = pmap;
898 /* this part should be in updateTexture() */
899 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID)
900 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
901 else
902 XSetWindowBackground(dpy, fwin->resizebar->window,
903 fwin->resizebar_texture[0]->solid.normal.pixel);
905 XClearWindow(dpy, fwin->resizebar->window);
909 void wFrameWindowPaint(WFrameWindow * fwin)
911 WScreen *scr = fwin->screen_ptr;
912 int state;
914 state = fwin->flags.state;
916 if (fwin->flags.is_client_window_frame)
917 fwin->flags.justification = wPreferences.title_justification;
919 if (fwin->flags.need_texture_remake) {
920 int i;
922 fwin->flags.need_texture_remake = 0;
923 fwin->flags.need_texture_change = 0;
925 if (fwin->flags.single_texture) {
926 remakeTexture(fwin, 0);
927 updateTexture(fwin);
928 } else {
929 /* first render the texture for the current state... */
930 remakeTexture(fwin, state);
931 /* ... and paint it */
932 updateTexture(fwin);
934 for (i = 0; i < 3; i++) {
935 if (i != state)
936 remakeTexture(fwin, i);
941 if (fwin->flags.need_texture_change) {
942 fwin->flags.need_texture_change = 0;
944 updateTexture(fwin);
947 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
948 && fwin->title_texture[state]->any.type == WTEX_SOLID) {
949 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
950 fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
953 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
954 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
955 Window win;
956 int w, h;
957 int cw;
958 GC light_gc, dim_gc;
959 WTexSolid *texture = (WTexSolid *) fwin->resizebar_texture[0];
961 w = fwin->resizebar->width;
962 h = fwin->resizebar->height;
963 cw = fwin->resizebar_corner_width;
964 light_gc = texture->light_gc;
965 dim_gc = texture->dim_gc;
966 win = fwin->resizebar->window;
968 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
969 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
971 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
972 XDrawLine(dpy, win, light_gc, cw + 1, 2, cw + 1, h);
974 XDrawLine(dpy, win, dim_gc, w - cw - 2, 2, w - cw - 2, h);
975 XDrawLine(dpy, win, light_gc, w - cw - 1, 2, w - cw - 1, h);
977 #ifdef SHADOW_RESIZEBAR
978 XDrawLine(dpy, win, light_gc, 0, 1, 0, h - 1);
979 XDrawLine(dpy, win, dim_gc, w - 1, 2, w - 1, h - 1);
980 XDrawLine(dpy, win, dim_gc, 1, h - 1, cw, h - 1);
981 XDrawLine(dpy, win, dim_gc, cw + 2, h - 1, w - cw - 2, h - 1);
982 XDrawLine(dpy, win, dim_gc, w - cw, h - 1, w - 1, h - 1);
983 #endif /* SHADOW_RESIZEBAR */
986 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
987 int x, y, w, h;
988 int lofs = 6, rofs = 6;
989 int titlelen;
990 int allButtons = 1;
992 if (!wPreferences.new_style == TS_NEW) {
993 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
994 lofs += fwin->left_button->width + 3;
995 else
996 allButtons = 0;
998 #ifdef XKB_BUTTON_HINT
999 if (fwin->language_button && !fwin->flags.hide_language_button
1000 && !fwin->flags.languagebutton_dont_fit)
1001 lofs += fwin->language_button->width;
1002 else
1003 allButtons = 0;
1004 #endif
1006 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1007 rofs += fwin->right_button->width + 3;
1008 else
1009 allButtons = 0;
1011 #ifdef XKB_BUTTON_HINT
1012 fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1013 #endif
1015 if (fwin->title) {
1016 Drawable buf;
1017 char *title;
1019 title = ShrinkString(*fwin->font, fwin->title, fwin->titlebar->width - lofs - rofs);
1020 titlelen = strlen(title);
1021 w = WMWidthOfString(*fwin->font, title, titlelen);
1023 switch (fwin->flags.justification) {
1024 case WTJ_LEFT:
1025 x = lofs;
1026 break;
1028 case WTJ_RIGHT:
1029 x = fwin->titlebar->width - w - rofs;
1030 break;
1032 default:
1033 if (!allButtons)
1034 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1035 else
1036 x = (fwin->titlebar->width - w) / 2;
1037 break;
1040 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1041 h = WMFontHeight(*fwin->font);
1043 if (y*2 + h > *fwin->title_max_height)
1044 y = (*fwin->title_max_height - h) / 2;
1046 if (y*2 + h < *fwin->title_min_height)
1047 y = (*fwin->title_min_height - h) / 2;
1049 /* We use a w+2 buffer to have an extra pixel on the left and
1050 * another one on the right. This is because for some odd reason,
1051 * sometimes when using AA fonts (when libfreetype2 is compiled
1052 * with bytecode interpreter turned off), some fonts are drawn
1053 * starting from x = -1 not from 0 as requested. Observed with
1054 * capital A letter on the bold 'trebuchet ms' font. -Dan
1056 buf = XCreatePixmap(dpy, fwin->titlebar->window, w + 2, h, scr->w_depth);
1058 XSetClipMask(dpy, scr->copy_gc, None);
1060 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
1061 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1062 x - 1, y, w + 2, h, 0, 0);
1063 } else {
1064 XSetForeground(dpy, scr->copy_gc, fwin->title_texture[state]->solid.normal.pixel);
1065 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w + 2, h);
1068 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1); */
1069 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1070 *fwin->font, 1, 0, title, titlelen);
1072 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc, 0, 0, w + 2, h, x - 1, y);
1074 XFreePixmap(dpy, buf);
1076 wfree(title);
1079 if (fwin->left_button)
1080 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1081 if (fwin->right_button)
1082 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1083 #ifdef XKB_BUTTON_HINT
1084 if (fwin->language_button)
1085 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1086 #endif
1090 static void reconfigure(WFrameWindow * fwin, int x, int y, int width, int height, Bool dontMove)
1092 int k = (wPreferences.new_style == TS_NEW ? 4 : 3);
1093 int resizedHorizontally = 0;
1095 if (dontMove)
1096 XResizeWindow(dpy, fwin->core->window, width, height);
1097 else
1098 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1100 if (fwin->core->width != width) {
1101 fwin->flags.need_texture_remake = 1;
1102 resizedHorizontally = 1;
1105 fwin->core->width = width;
1106 fwin->core->height = height;
1108 if (fwin->titlebar && resizedHorizontally) {
1109 /* Check if the titlebar is wide enough to hold the buttons.
1110 * Temporarily remove them if can't
1112 if (fwin->left_button) {
1113 if (width < fwin->top_width * k && !fwin->flags.lbutton_dont_fit) {
1114 if (!fwin->flags.hide_left_button)
1115 XUnmapWindow(dpy, fwin->left_button->window);
1117 fwin->flags.lbutton_dont_fit = 1;
1118 } else if (width >= fwin->top_width * k && fwin->flags.lbutton_dont_fit) {
1119 if (!fwin->flags.hide_left_button)
1120 XMapWindow(dpy, fwin->left_button->window);
1122 fwin->flags.lbutton_dont_fit = 0;
1125 #ifdef XKB_BUTTON_HINT
1126 if (fwin->language_button) {
1127 if (width < fwin->top_width * k && !fwin->flags.languagebutton_dont_fit) {
1128 if (!fwin->flags.hide_language_button)
1129 XUnmapWindow(dpy, fwin->language_button->window);
1131 fwin->flags.languagebutton_dont_fit = 1;
1132 } else if (width >= fwin->top_width * k && fwin->flags.languagebutton_dont_fit) {
1133 if (!fwin->flags.hide_language_button)
1134 XMapWindow(dpy, fwin->language_button->window);
1136 fwin->flags.languagebutton_dont_fit = 0;
1139 #endif
1141 if (fwin->right_button) {
1142 if (width < fwin->top_width * 2 && !fwin->flags.rbutton_dont_fit) {
1143 if (!fwin->flags.hide_right_button)
1144 XUnmapWindow(dpy, fwin->right_button->window);
1146 fwin->flags.rbutton_dont_fit = 1;
1147 } else if (width >= fwin->top_width * 2 && fwin->flags.rbutton_dont_fit) {
1148 if (!fwin->flags.hide_right_button)
1149 XMapWindow(dpy, fwin->right_button->window);
1151 fwin->flags.rbutton_dont_fit = 0;
1155 if (wPreferences.new_style == TS_NEW) {
1156 if (fwin->right_button)
1157 XMoveWindow(dpy, fwin->right_button->window,
1158 width - fwin->right_button->width + 1, 0);
1159 } else {
1160 if (fwin->right_button)
1161 XMoveWindow(dpy, fwin->right_button->window,
1162 width - fwin->right_button->width - 3,
1163 (fwin->titlebar->height - fwin->right_button->height) / 2);
1165 updateTitlebar(fwin);
1166 checkTitleSize(fwin);
1169 if (fwin->resizebar) {
1170 wCoreConfigure(fwin->resizebar, 0,
1171 fwin->core->height - fwin->resizebar->height,
1172 fwin->core->width, fwin->resizebar->height);
1174 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1175 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH)
1176 fwin->resizebar_corner_width = fwin->core->width / 2;
1180 void wFrameWindowConfigure(WFrameWindow * fwin, int x, int y, int width, int height)
1182 reconfigure(fwin, x, y, width, height, False);
1185 void wFrameWindowResize(WFrameWindow * fwin, int width, int height)
1187 reconfigure(fwin, 0, 0, width, height, True);
1190 int wFrameWindowChangeTitle(WFrameWindow * fwin, char *new_title)
1192 /* check if the title is the same as before */
1193 if (fwin->title) {
1194 if (new_title && (strcmp(fwin->title, new_title) == 0))
1195 return 0;
1196 } else {
1197 if (!new_title)
1198 return 0;
1201 if (fwin->title)
1202 wfree(fwin->title);
1204 fwin->title = wstrdup(new_title);
1206 if (fwin->titlebar) {
1207 XClearWindow(dpy, fwin->titlebar->window);
1209 wFrameWindowPaint(fwin);
1211 checkTitleSize(fwin);
1213 return 1;
1216 #ifdef XKB_BUTTON_HINT
1217 void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
1219 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1220 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
1222 #endif /* XKB_BUTTON_HINT */
1224 /*********************************************************************/
1226 static void handleExpose(WObjDescriptor * desc, XEvent * event)
1228 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1230 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1231 fwin->flags.repaint_only_titlebar = 1;
1232 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1233 fwin->flags.repaint_only_resizebar = 1;
1234 wFrameWindowPaint(fwin);
1235 fwin->flags.repaint_only_titlebar = 0;
1236 fwin->flags.repaint_only_resizebar = 0;
1239 static void checkTitleSize(WFrameWindow * fwin)
1241 int width;
1243 if (!fwin->title) {
1244 fwin->flags.incomplete_title = 0;
1245 return;
1248 if (!fwin->titlebar) {
1249 fwin->flags.incomplete_title = 1;
1250 return;
1251 } else {
1252 width = fwin->titlebar->width - 6 - 6;
1255 if (!wPreferences.new_style == TS_NEW) {
1256 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1257 width -= fwin->left_button->width + 3;
1259 #ifdef XKB_BUTTON_HINT
1260 if (fwin->language_button && !fwin->flags.hide_language_button
1261 && !fwin->flags.languagebutton_dont_fit)
1262 width -= fwin->language_button->width + 3;
1263 #endif
1265 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1266 width -= fwin->right_button->width + 3;
1269 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width)
1270 fwin->flags.incomplete_title = 1;
1271 else
1272 fwin->flags.incomplete_title = 0;
1275 static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
1277 WScreen *scr = button->screen_ptr;
1278 GC copy_gc = scr->copy_gc;
1279 int x = 0, y = 0, d = 0;
1280 int left = 0, width = 0;
1282 /* setup stuff according to the state */
1283 if (pushed) {
1284 if (image) {
1285 if (image->width >= image->height * 2) {
1286 /* the image contains 2 pictures: the second is for the
1287 * pushed state */
1288 width = image->width / 2;
1289 left = image->width / 2;
1290 } else {
1291 width = image->width;
1294 XSetClipMask(dpy, copy_gc, None);
1295 if (wPreferences.new_style == TS_NEXT)
1296 XSetForeground(dpy, copy_gc, scr->black_pixel);
1297 else
1298 XSetForeground(dpy, copy_gc, scr->white_pixel);
1300 d = 1;
1301 if (wPreferences.new_style == TS_NEW) {
1302 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1303 XSetForeground(dpy, copy_gc, scr->black_pixel);
1304 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1305 } else if (wPreferences.new_style == TS_OLD) {
1306 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1307 XSetForeground(dpy, copy_gc, scr->black_pixel);
1308 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1309 } else {
1310 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1311 XSetForeground(dpy, copy_gc, scr->black_pixel);
1312 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1314 } else {
1315 XClearWindow(dpy, button->window);
1317 if (image) {
1318 if (image->width >= image->height * 2)
1319 width = image->width / 2;
1320 else
1321 width = image->width;
1323 d = 0;
1325 if (wPreferences.new_style == TS_NEW) {
1326 if (texture->any.type == WTEX_SOLID || pushed)
1327 wDrawBevel(button->window, button->width, button->height,
1328 (WTexSolid *) texture, WREL_RAISED);
1329 } else {
1330 wDrawBevel(button->window, button->width, button->height,
1331 scr->widget_texture, WREL_RAISED);
1335 if (image) {
1336 /* display image */
1337 XSetClipMask(dpy, copy_gc, image->mask);
1338 x = (button->width - width) / 2 + d;
1339 y = (button->height - image->height) / 2 + d;
1340 XSetClipOrigin(dpy, copy_gc, x - left, y);
1341 if (!wPreferences.new_style == TS_NEW) {
1342 XSetForeground(dpy, copy_gc, scr->black_pixel);
1343 if (!pushed) {
1344 if (image->depth == 1)
1345 XCopyPlane(dpy, image->image, button->window, copy_gc,
1346 left, 0, width, image->height, x, y, 1);
1347 else
1348 XCopyArea(dpy, image->image, button->window, copy_gc,
1349 left, 0, width, image->height, x, y);
1350 } else {
1351 if (wPreferences.new_style == TS_OLD) {
1352 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1353 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1354 button->width, button->height);
1355 } else {
1356 XSetForeground(dpy, copy_gc, scr->black_pixel);
1357 XCopyArea(dpy, image->image, button->window, copy_gc,
1358 left, 0, width, image->height, x, y);
1361 } else {
1362 if (pushed) {
1363 XSetForeground(dpy, copy_gc, scr->black_pixel);
1364 } else {
1365 XSetForeground(dpy, copy_gc, color);
1366 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1368 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1373 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
1375 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1376 WCoreWindow *button = (WCoreWindow *) desc->self;
1378 #ifdef XKB_BUTTON_HINT
1379 if (button == fwin->language_button) {
1380 if (wPreferences.modelock)
1381 paintButton(button, fwin->title_texture[fwin->flags.state],
1382 WMColorPixel(fwin->title_color[fwin->flags.state]),
1383 fwin->languagebutton_image, False);
1384 } else
1385 #endif
1386 if (button == fwin->left_button)
1387 paintButton(button, fwin->title_texture[fwin->flags.state],
1388 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
1389 else
1390 paintButton(button, fwin->title_texture[fwin->flags.state],
1391 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
1394 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
1396 WFrameWindow *fwin = desc->parent;
1397 WCoreWindow *titlebar = desc->self;
1399 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1400 if (fwin->on_dblclick_titlebar)
1401 (*fwin->on_dblclick_titlebar) (titlebar, fwin->child, event);
1402 } else {
1403 if (fwin->on_mousedown_titlebar)
1404 (*fwin->on_mousedown_titlebar) (titlebar, fwin->child, event);
1408 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event)
1410 WFrameWindow *fwin = desc->parent;
1411 WCoreWindow *resizebar = desc->self;
1413 if (fwin->on_mousedown_resizebar)
1414 (*fwin->on_mousedown_resizebar) (resizebar, fwin->child, event);
1417 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
1419 WFrameWindow *fwin = desc->parent;
1420 WCoreWindow *button = desc->self;
1421 WPixmap *image;
1422 XEvent ev;
1423 int done = 0, execute = 1;
1424 WTexture *texture;
1425 unsigned long pixel;
1426 int clickButton = event->xbutton.button;
1428 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1429 if (button == fwin->right_button && fwin->on_dblclick_right)
1430 (*fwin->on_dblclick_right) (button, fwin->child, event);
1432 return;
1435 if (button == fwin->left_button)
1436 image = fwin->lbutton_image;
1437 else
1438 image = fwin->rbutton_image;
1440 #ifdef XKB_BUTTON_HINT
1441 if (button == fwin->language_button) {
1442 if (!wPreferences.modelock)
1443 return;
1444 image = fwin->languagebutton_image;
1446 #endif
1448 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1449 texture = fwin->title_texture[fwin->flags.state];
1450 paintButton(button, texture, pixel, image, True);
1452 while (!done) {
1453 WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
1454 | ButtonPressMask | ExposureMask, &ev);
1455 switch (ev.type) {
1456 case LeaveNotify:
1457 execute = 0;
1458 paintButton(button, texture, pixel, image, False);
1459 break;
1461 case EnterNotify:
1462 execute = 1;
1463 paintButton(button, texture, pixel, image, True);
1464 break;
1466 case ButtonPress:
1467 break;
1469 case ButtonRelease:
1470 if (ev.xbutton.button == clickButton)
1471 done = 1;
1472 break;
1474 default:
1475 WMHandleEvent(&ev);
1478 paintButton(button, texture, pixel, image, False);
1480 if (execute) {
1481 if (button == fwin->left_button) {
1482 if (fwin->on_click_left)
1483 (*fwin->on_click_left) (button, fwin->child, &ev);
1484 } else if (button == fwin->right_button) {
1485 if (fwin->on_click_right)
1486 (*fwin->on_click_right) (button, fwin->child, &ev);
1488 #ifdef XKB_BUTTON_HINT
1489 else if (button == fwin->language_button) {
1490 if (fwin->on_click_language)
1491 (*fwin->on_click_language) (button, fwin->child, &ev);
1493 #endif