Allow windows to specify their own depth.
[wmaker-crm.git] / src / framewin.c
blob448d204fe6eabb1e27dd66d521fbe6f4690439eb
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 WFrameWindow *wFrameWindowCreate(WScreen * scr, int wlevel, int x, int y,
62 int width, int height, int *clearance,
63 int *title_min, int *title_max, int flags,
64 WTexture ** title_texture, WTexture ** resize_texture,
65 WMColor ** color, WMFont ** font,
66 int depth, Visual *visual, Colormap colormap)
68 WFrameWindow *fwin;
70 fwin = wmalloc(sizeof(WFrameWindow));
72 fwin->screen_ptr = scr;
74 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
76 fwin->title_texture = title_texture;
77 fwin->resizebar_texture = resize_texture;
78 fwin->title_color = color;
79 fwin->title_clearance = clearance;
80 fwin->title_min_height = title_min;
81 fwin->title_max_height = title_max;
82 fwin->font = font;
83 #ifdef KEEP_XKB_LOCK_STATUS
84 fwin->languagemode = XkbGroup1Index;
85 fwin->last_languagemode = XkbGroup2Index;
86 #endif
88 fwin->depth = depth;
89 fwin->visual = visual;
90 fwin->colormap = colormap;
92 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height, (flags & WFF_BORDER)
93 ? FRAME_BORDER_WIDTH : 0, fwin->depth, fwin->visual, fwin->colormap);
94 if (wPreferences.use_saveunders) {
95 unsigned long vmask;
96 XSetWindowAttributes attribs;
98 vmask = CWSaveUnder;
99 attribs.save_under = True;
100 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
103 /* setup stacking information */
104 fwin->core->stacking = wmalloc(sizeof(WStacking));
105 fwin->core->stacking->above = NULL;
106 fwin->core->stacking->under = NULL;
107 fwin->core->stacking->child_of = NULL;
108 fwin->core->stacking->window_level = wlevel;
110 AddToStackList(fwin->core);
112 wFrameWindowUpdateBorders(fwin, flags);
114 return fwin;
117 void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
119 int theight;
120 int bsize;
121 int width, height;
122 int i;
123 WScreen *scr = fwin->screen_ptr;
125 width = fwin->core->width;
126 if (flags & WFF_IS_SHADED)
127 height = -1;
128 else
129 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
131 if (flags & WFF_TITLEBAR) {
132 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
134 if (theight > *fwin->title_max_height)
135 theight = *fwin->title_max_height;
137 if (theight < *fwin->title_min_height)
138 theight = *fwin->title_min_height;
139 } else
140 theight = 0;
142 if (wPreferences.new_style == TS_NEW) {
143 bsize = theight;
144 } else if (wPreferences.new_style == TS_OLD) {
145 bsize = theight - 7;
146 } else {
147 bsize = theight - 8;
150 if (fwin->titlebar) {
151 /* if we had a titlebar and is requesting for one,
152 * check if the size has changed and resize it */
153 if (flags & WFF_TITLEBAR) {
154 fwin->top_width = theight;
156 fwin->flags.need_texture_remake = 1;
158 if (wPreferences.new_style == TS_NEW) {
159 if (fwin->left_button) {
160 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
162 #ifdef XKB_BUTTON_HINT
163 if (fwin->language_button) {
164 if (fwin->flags.hide_left_button || !fwin->left_button
165 || fwin->flags.lbutton_dont_fit) {
166 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
167 } else {
168 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
171 #endif
173 if (fwin->right_button) {
174 wCoreConfigure(fwin->right_button, width - bsize + 1, 0, bsize, bsize);
176 } else { /* !new_style */
177 if (fwin->left_button) {
178 wCoreConfigure(fwin->left_button, 3, (theight - bsize) / 2, bsize, bsize);
180 #ifdef XKB_BUTTON_HINT
181 if (fwin->language_button) {
182 wCoreConfigure(fwin->language_button, 6 + bsize, (theight - bsize) / 2,
183 bsize, bsize);
185 #endif
187 if (fwin->right_button) {
188 wCoreConfigure(fwin->right_button, width - bsize - 3,
189 (theight - bsize) / 2, bsize, bsize);
192 updateTitlebar(fwin);
193 } else {
194 /* we had a titlebar, but now we don't need it anymore */
195 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
196 FREE_PIXMAP(fwin->title_back[i]);
197 if (wPreferences.new_style == TS_NEW) {
198 FREE_PIXMAP(fwin->lbutton_back[i]);
199 FREE_PIXMAP(fwin->rbutton_back[i]);
200 #ifdef XKB_BUTTON_HINT
201 FREE_PIXMAP(fwin->languagebutton_back[i]);
202 #endif
205 if (fwin->left_button)
206 wCoreDestroy(fwin->left_button);
207 fwin->left_button = NULL;
209 #ifdef XKB_BUTTON_HINT
210 if (fwin->language_button)
211 wCoreDestroy(fwin->language_button);
212 fwin->language_button = NULL;
213 #endif
215 if (fwin->right_button)
216 wCoreDestroy(fwin->right_button);
217 fwin->right_button = NULL;
219 wCoreDestroy(fwin->titlebar);
220 fwin->titlebar = NULL;
222 fwin->top_width = 0;
224 } else {
225 /* if we didn't have a titlebar and are being requested for
226 * one, create it */
227 if (flags & WFF_TITLEBAR) {
228 fwin->top_width = theight;
230 fwin->flags.titlebar = 1;
231 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width + 1, theight);
233 if (flags & WFF_LEFT_BUTTON) {
234 fwin->flags.left_button = 1;
235 if (wPreferences.new_style == TS_NEW) {
236 fwin->left_button = wCoreCreate(fwin->core, 0, 0, bsize, bsize);
237 if (width < theight * 4) {
238 fwin->flags.lbutton_dont_fit = 1;
239 } else {
240 XMapRaised(dpy, fwin->left_button->window);
242 } else if (wPreferences.new_style == TS_OLD) {
243 fwin->left_button =
244 wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
246 XSetWindowBackground(dpy, fwin->left_button->window,
247 scr->widget_texture->normal.pixel);
249 if (width < theight * 3) {
250 fwin->flags.lbutton_dont_fit = 1;
251 } else {
252 XMapRaised(dpy, fwin->left_button->window);
254 } else {
255 fwin->left_button =
256 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
257 bsize, bsize);
259 XSetWindowBackground(dpy, fwin->left_button->window,
260 scr->widget_texture->dark.pixel);
262 if (width < theight*3) {
263 fwin->flags.lbutton_dont_fit = 1;
264 } else {
265 XMapRaised(dpy, fwin->left_button->window);
269 #ifdef XKB_BUTTON_HINT
270 if (flags & WFF_LANGUAGE_BUTTON) {
271 fwin->flags.language_button = 1;
272 if (wPreferences.new_style == TS_NEW) {
273 fwin->language_button = wCoreCreate(fwin->core, bsize, 0, bsize, bsize);
275 if (width < theight * 4) {
276 fwin->flags.languagebutton_dont_fit = 1;
277 } else {
278 XMapRaised(dpy, fwin->language_button->window);
280 } else {
281 fwin->language_button =
282 wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
283 bsize, bsize);
285 XSetWindowBackground(dpy, fwin->language_button->window,
286 scr->widget_texture->normal.pixel);
288 if (width < theight * 3) {
289 fwin->flags.languagebutton_dont_fit = 1;
290 } else {
291 XMapRaised(dpy, fwin->language_button->window);
295 #endif
297 if (flags & WFF_RIGHT_BUTTON) {
298 fwin->flags.right_button = 1;
299 if (wPreferences.new_style == TS_NEW) {
300 fwin->right_button =
301 wCoreCreate(fwin->core, width - bsize + 1, 0, bsize, bsize);
302 } else if (wPreferences.new_style == TS_OLD) {
303 fwin->right_button =
304 wCoreCreate(fwin->titlebar, width - bsize - 3,
305 (theight - bsize) / 2, bsize, bsize);
306 XSetWindowBackground(dpy, fwin->right_button->window,
307 scr->widget_texture->normal.pixel);
308 } else {
309 fwin->right_button =
310 wCoreCreate(fwin->titlebar, width-bsize-3,
311 (theight-bsize)/2, bsize, bsize);
312 XSetWindowBackground(dpy, fwin->right_button->window,
313 scr->widget_texture->dark.pixel);
316 if (width < theight * 2) {
317 fwin->flags.rbutton_dont_fit = 1;
318 } else {
319 XMapRaised(dpy, fwin->right_button->window);
323 if (wPreferences.new_style == TS_NEW)
324 updateTitlebar(fwin);
326 XMapRaised(dpy, fwin->titlebar->window);
328 fwin->flags.need_texture_remake = 1;
331 checkTitleSize(fwin);
333 if (flags & WFF_RESIZEBAR) {
334 fwin->bottom_width = RESIZEBAR_HEIGHT;
336 if (!fwin->resizebar) {
337 fwin->flags.resizebar = 1;
338 fwin->resizebar = wCoreCreate(fwin->core, 0,
339 height + fwin->top_width, width, RESIZEBAR_HEIGHT);
340 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
341 if (width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
342 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH) / 2;
343 if (fwin->resizebar_corner_width < 0)
344 fwin->resizebar_corner_width = 0;
347 XMapWindow(dpy, fwin->resizebar->window);
348 XLowerWindow(dpy, fwin->resizebar->window);
350 fwin->flags.need_texture_remake = 1;
351 } else {
352 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height) {
353 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
354 width, RESIZEBAR_HEIGHT);
357 } else {
358 fwin->bottom_width = 0;
360 if (fwin->resizebar) {
361 fwin->bottom_width = 0;
362 wCoreDestroy(fwin->resizebar);
363 fwin->resizebar = NULL;
367 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED)) {
368 wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
371 if (flags & WFF_BORDER) {
372 XSetWindowBorderWidth(dpy, fwin->core->window, FRAME_BORDER_WIDTH);
373 } else {
374 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
377 /* setup object descriptors */
379 if (fwin->titlebar) {
380 fwin->titlebar->descriptor.handle_expose = handleExpose;
381 fwin->titlebar->descriptor.parent = fwin;
382 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
383 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
386 if (fwin->resizebar) {
387 fwin->resizebar->descriptor.handle_expose = handleExpose;
388 fwin->resizebar->descriptor.parent = fwin;
389 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
390 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
393 if (fwin->left_button) {
394 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
395 fwin->left_button->descriptor.parent = fwin;
396 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
397 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
399 #ifdef XKB_BUTTON_HINT
400 if (fwin->language_button) {
401 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
402 fwin->language_button->descriptor.parent = fwin;
403 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
404 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
406 #endif
408 if (fwin->right_button) {
409 fwin->right_button->descriptor.parent = fwin;
410 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
411 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
412 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
415 checkTitleSize(fwin);
418 void wFrameWindowDestroy(WFrameWindow * fwin)
420 int i;
422 if (fwin->left_button)
423 wCoreDestroy(fwin->left_button);
425 #ifdef XKB_BUTTON_HINT
426 if (fwin->language_button)
427 wCoreDestroy(fwin->language_button);
428 #endif
430 if (fwin->right_button)
431 wCoreDestroy(fwin->right_button);
433 if (fwin->resizebar)
434 wCoreDestroy(fwin->resizebar);
436 if (fwin->titlebar)
437 wCoreDestroy(fwin->titlebar);
439 RemoveFromStackList(fwin->core);
441 wCoreDestroy(fwin->core);
443 if (fwin->title)
444 wfree(fwin->title);
446 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
447 FREE_PIXMAP(fwin->title_back[i]);
448 if (wPreferences.new_style == TS_NEW) {
449 FREE_PIXMAP(fwin->lbutton_back[i]);
450 #ifdef XKB_BUTTON_HINT
451 FREE_PIXMAP(fwin->languagebutton_back[i]);
452 #endif
453 FREE_PIXMAP(fwin->rbutton_back[i]);
457 wfree(fwin);
460 void wFrameWindowChangeState(WFrameWindow * fwin, int state)
462 if (fwin->flags.state == state)
463 return;
465 fwin->flags.state = state;
466 fwin->flags.need_texture_change = 1;
468 wFrameWindowPaint(fwin);
471 static void updateTitlebar(WFrameWindow * fwin)
473 int x, w;
474 int theight;
476 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
478 if (theight > *fwin->title_max_height)
479 theight = *fwin->title_max_height;
481 if (theight < *fwin->title_min_height)
482 theight = *fwin->title_min_height;
484 x = 0;
485 w = fwin->core->width + 1;
487 if (wPreferences.new_style == TS_NEW) {
488 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
489 x = 0;
490 #ifdef XKB_BUTTON_HINT
491 if (fwin->language_button)
492 wCoreConfigure(fwin->language_button, 0, 0,
493 fwin->language_button->width, fwin->language_button->width);
494 #endif
495 } else {
496 #ifdef XKB_BUTTON_HINT
497 if (fwin->language_button)
498 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
499 fwin->language_button->width, fwin->language_button->width);
500 #endif
501 x = fwin->left_button->width;
502 w -= fwin->left_button->width;
504 #ifdef XKB_BUTTON_HINT
505 if (fwin->flags.hide_language_button || !fwin->language_button
506 || fwin->flags.languagebutton_dont_fit) {
507 } else {
508 x += fwin->language_button->width;
509 w -= fwin->language_button->width;
511 #endif
513 #ifdef XKB_BUTTON_HINT
514 else {
515 int bsize = theight - 7;
516 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
517 if (fwin->language_button)
518 wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
519 fwin->language_button->width, fwin->language_button->width);
520 } else {
521 if (fwin->language_button)
522 wCoreConfigure(fwin->language_button,
523 6 + fwin->left_button->width, (theight - bsize) / 2,
524 fwin->language_button->width, fwin->language_button->width);
527 #endif
529 if (wPreferences.new_style == TS_NEW) {
530 if (!fwin->flags.hide_right_button && fwin->right_button && !fwin->flags.rbutton_dont_fit) {
531 w -= fwin->right_button->width;
535 if (wPreferences.new_style == TS_NEW || fwin->titlebar->width != w)
536 fwin->flags.need_texture_remake = 1;
538 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
541 void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
543 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
544 XUnmapWindow(dpy, fwin->right_button->window);
545 fwin->flags.hide_right_button = 1;
548 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
549 XUnmapWindow(dpy, fwin->left_button->window);
550 fwin->flags.hide_left_button = 1;
552 #ifdef XKB_BUTTON_HINT
553 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
554 XUnmapWindow(dpy, fwin->language_button->window);
555 fwin->flags.hide_language_button = 1;
557 #endif
559 if (fwin->titlebar) {
560 if (wPreferences.new_style == TS_NEW) {
561 updateTitlebar(fwin);
562 } else {
563 #ifdef XKB_BUTTON_HINT
564 updateTitlebar(fwin);
565 #else
566 XClearWindow(dpy, fwin->titlebar->window);
567 wFrameWindowPaint(fwin);
568 #endif
570 checkTitleSize(fwin);
574 void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
576 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
578 if (!fwin->flags.rbutton_dont_fit)
579 XMapWindow(dpy, fwin->right_button->window);
581 fwin->flags.hide_right_button = 0;
583 #ifdef XKB_BUTTON_HINT
584 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
586 if (!fwin->flags.languagebutton_dont_fit)
587 XMapWindow(dpy, fwin->language_button->window);
589 fwin->flags.hide_language_button = 0;
591 #endif
593 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
595 if (!fwin->flags.lbutton_dont_fit)
596 XMapWindow(dpy, fwin->left_button->window);
598 fwin->flags.hide_left_button = 0;
601 if (fwin->titlebar) {
602 if (wPreferences.new_style == TS_NEW) {
603 updateTitlebar(fwin);
604 } else {
605 XClearWindow(dpy, fwin->titlebar->window);
606 wFrameWindowPaint(fwin);
608 checkTitleSize(fwin);
612 static void
613 #ifdef XKB_BUTTON_HINT
614 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
615 int bwidth, int bheight, int left, int language, int right,
616 Pixmap * title, Pixmap * lbutton, Pixmap * languagebutton, Pixmap * rbutton)
617 #else
618 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
619 int bwidth, int bheight, int left, int right, Pixmap * title, Pixmap * lbutton, Pixmap * rbutton)
620 #endif
622 RImage *img;
623 RImage *limg, *rimg, *mimg;
624 #ifdef XKB_BUTTON_HINT
625 RImage *timg;
626 #endif
627 int x, w;
629 *title = None;
630 *lbutton = None;
631 *rbutton = None;
632 #ifdef XKB_BUTTON_HINT
633 *languagebutton = None;
634 #endif
636 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
637 if (!img) {
638 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
639 return;
642 if (wPreferences.new_style == TS_NEW) {
643 if (left) {
644 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
645 } else
646 limg = NULL;
648 x = 0;
649 w = img->width;
651 #ifdef XKB_BUTTON_HINT
652 if (language) {
653 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
654 } else
655 timg = NULL;
656 #endif
658 if (limg) {
659 RBevelImage(limg, RBEV_RAISED2);
660 if (!RConvertImage(scr->rcontext, limg, lbutton)) {
661 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
663 x += limg->width;
664 w -= limg->width;
665 RReleaseImage(limg);
667 #ifdef XKB_BUTTON_HINT
668 if (timg) {
669 RBevelImage(timg, RBEV_RAISED2);
670 if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
671 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
673 x += timg->width;
674 w -= timg->width;
675 RReleaseImage(timg);
677 #endif
679 if (right) {
680 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
681 } else
682 rimg = NULL;
684 if (rimg) {
685 RBevelImage(rimg, RBEV_RAISED2);
686 if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
687 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
689 w -= rimg->width;
690 RReleaseImage(rimg);
693 if (w != width) {
694 mimg = RGetSubImage(img, x, 0, w, img->height);
695 RBevelImage(mimg, RBEV_RAISED2);
697 if (!RConvertImage(scr->rcontext, mimg, title)) {
698 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
700 RReleaseImage(mimg);
701 } else {
702 RBevelImage(img, RBEV_RAISED2);
704 if (!RConvertImage(scr->rcontext, img, title)) {
705 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
708 } else {
709 RBevelImage(img, RBEV_RAISED2);
711 if (!RConvertImage(scr->rcontext, img, title)) {
712 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
716 RReleaseImage(img);
719 static void
720 renderResizebarTexture(WScreen * scr, WTexture * texture, int width, int height, int cwidth, Pixmap * pmap)
722 RImage *img;
723 RColor light;
724 RColor dark;
726 *pmap = None;
728 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
729 if (!img) {
730 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
731 return;
734 light.alpha = 0;
735 light.red = light.green = light.blue = 80;
737 dark.alpha = 0;
738 dark.red = dark.green = dark.blue = 40;
740 ROperateLine(img, RSubtractOperation, 0, 0, width - 1, 0, &dark);
741 ROperateLine(img, RAddOperation, 0, 1, width - 1, 1, &light);
743 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height - 1, &dark);
744 ROperateLine(img, RAddOperation, cwidth + 1, 2, cwidth + 1, height - 1, &light);
746 if (width > 1)
747 ROperateLine(img, RSubtractOperation, width - cwidth - 2, 2,
748 width - cwidth - 2, height - 1, &dark);
749 ROperateLine(img, RAddOperation, width - cwidth - 1, 2, width - cwidth - 1, height - 1, &light);
751 #ifdef SHADOW_RESIZEBAR
752 ROperateLine(img, RAddOperation, 0, 1, 0, height - 1, &light);
753 ROperateLine(img, RSubtractOperation, width - 1, 1, width - 1, height - 1, &dark);
754 ROperateLine(img, RSubtractOperation, 0, height - 1, width - 1, height - 1, &dark);
755 #endif /* SHADOW_RESIZEBAR */
757 if (!RConvertImage(scr->rcontext, img, pmap)) {
758 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
761 RReleaseImage(img);
764 static void updateTexture(WFrameWindow * fwin)
766 int i;
767 unsigned long pixel;
769 i = fwin->flags.state;
770 if (fwin->titlebar) {
771 if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
772 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window, fwin->title_back[i]);
773 if (wPreferences.new_style == TS_NEW) {
774 if (fwin->left_button && fwin->lbutton_back[i])
775 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
776 fwin->lbutton_back[i]);
778 #ifdef XKB_BUTTON_HINT
779 if (fwin->language_button && fwin->languagebutton_back[i]) {
780 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
781 fwin->languagebutton_back[i]);
783 #endif
785 if (fwin->right_button && fwin->rbutton_back[i])
786 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
787 fwin->rbutton_back[i]);
789 } else {
790 pixel = fwin->title_texture[i]->solid.normal.pixel;
791 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
792 if (wPreferences.new_style == TS_NEW) {
793 if (fwin->left_button)
794 XSetWindowBackground(dpy, fwin->left_button->window, pixel);
795 #ifdef XKB_BUTTON_HINT
796 if (fwin->language_button)
797 XSetWindowBackground(dpy, fwin->language_button->window, pixel);
798 #endif
799 if (fwin->right_button)
800 XSetWindowBackground(dpy, fwin->right_button->window, pixel);
803 XClearWindow(dpy, fwin->titlebar->window);
805 if (fwin->left_button) {
806 XClearWindow(dpy, fwin->left_button->window);
807 handleButtonExpose(&fwin->left_button->descriptor, NULL);
809 #ifdef XKB_BUTTON_HINT
810 if (fwin->language_button) {
811 XClearWindow(dpy, fwin->language_button->window);
812 handleButtonExpose(&fwin->language_button->descriptor, NULL);
814 #endif
815 if (fwin->right_button) {
816 XClearWindow(dpy, fwin->right_button->window);
817 handleButtonExpose(&fwin->right_button->descriptor, NULL);
822 static void remakeTexture(WFrameWindow * fwin, int state)
824 Pixmap pmap, lpmap, rpmap;
825 #ifdef XKB_BUTTON_HINT
826 Pixmap tpmap;
827 #endif
829 if (fwin->title_texture[state] && fwin->titlebar) {
830 FREE_PIXMAP(fwin->title_back[state]);
831 if (wPreferences.new_style == TS_NEW) {
832 FREE_PIXMAP(fwin->lbutton_back[state]);
833 FREE_PIXMAP(fwin->rbutton_back[state]);
834 #ifdef XKB_BUTTON_HINT
835 FREE_PIXMAP(fwin->languagebutton_back[state]);
836 #endif
839 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
840 int left, right;
841 int width;
842 #ifdef XKB_BUTTON_HINT
843 int language;
844 #endif
846 /* eventually surrounded by if new_style */
847 left = fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit;
848 #ifdef XKB_BUTTON_HINT
849 language = fwin->language_button && !fwin->flags.hide_language_button
850 && !fwin->flags.languagebutton_dont_fit;
851 #endif
852 right = fwin->right_button && !fwin->flags.hide_right_button
853 && !fwin->flags.rbutton_dont_fit;
855 width = fwin->core->width + 1;
857 #ifdef XKB_BUTTON_HINT
858 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
859 width, fwin->titlebar->height,
860 fwin->titlebar->height, fwin->titlebar->height,
861 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
862 #else
863 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
864 width, fwin->titlebar->height,
865 fwin->titlebar->height, fwin->titlebar->height,
866 left, right, &pmap, &lpmap, &rpmap);
867 #endif
869 fwin->title_back[state] = pmap;
870 if (wPreferences.new_style == TS_NEW) {
871 fwin->lbutton_back[state] = lpmap;
872 fwin->rbutton_back[state] = rpmap;
873 #ifdef XKB_BUTTON_HINT
874 fwin->languagebutton_back[state] = tpmap;
875 #endif
879 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
880 && fwin->resizebar && state == 0) {
882 FREE_PIXMAP(fwin->resizebar_back[0]);
884 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
886 renderResizebarTexture(fwin->screen_ptr,
887 fwin->resizebar_texture[0],
888 fwin->resizebar->width,
889 fwin->resizebar->height, fwin->resizebar_corner_width, &pmap);
891 fwin->resizebar_back[0] = pmap;
894 /* this part should be in updateTexture() */
895 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
896 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
897 } else {
898 XSetWindowBackground(dpy, fwin->resizebar->window,
899 fwin->resizebar_texture[0]->solid.normal.pixel);
901 XClearWindow(dpy, fwin->resizebar->window);
905 void wFrameWindowPaint(WFrameWindow * fwin)
907 WScreen *scr = fwin->screen_ptr;
908 int state;
910 state = fwin->flags.state;
912 if (fwin->flags.is_client_window_frame)
913 fwin->flags.justification = wPreferences.title_justification;
915 if (fwin->flags.need_texture_remake) {
916 int i;
918 fwin->flags.need_texture_remake = 0;
919 fwin->flags.need_texture_change = 0;
921 if (fwin->flags.single_texture) {
922 remakeTexture(fwin, 0);
923 updateTexture(fwin);
924 } else {
925 /* first render the texture for the current state... */
926 remakeTexture(fwin, state);
927 /* ... and paint it */
928 updateTexture(fwin);
930 for (i = 0; i < 3; i++) {
931 if (i != state) {
932 remakeTexture(fwin, i);
938 if (fwin->flags.need_texture_change) {
939 fwin->flags.need_texture_change = 0;
941 updateTexture(fwin);
944 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
945 && fwin->title_texture[state]->any.type == WTEX_SOLID) {
946 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
947 fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
950 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
951 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
952 Window win;
953 int w, h;
954 int cw;
955 GC light_gc, dim_gc;
956 WTexSolid *texture = (WTexSolid *) fwin->resizebar_texture[0];
958 w = fwin->resizebar->width;
959 h = fwin->resizebar->height;
960 cw = fwin->resizebar_corner_width;
961 light_gc = texture->light_gc;
962 dim_gc = texture->dim_gc;
963 win = fwin->resizebar->window;
965 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
966 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
968 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
969 XDrawLine(dpy, win, light_gc, cw + 1, 2, cw + 1, h);
971 XDrawLine(dpy, win, dim_gc, w - cw - 2, 2, w - cw - 2, h);
972 XDrawLine(dpy, win, light_gc, w - cw - 1, 2, w - cw - 1, h);
974 #ifdef SHADOW_RESIZEBAR
975 XDrawLine(dpy, win, light_gc, 0, 1, 0, h - 1);
976 XDrawLine(dpy, win, dim_gc, w - 1, 2, w - 1, h - 1);
977 XDrawLine(dpy, win, dim_gc, 1, h - 1, cw, h - 1);
978 XDrawLine(dpy, win, dim_gc, cw + 2, h - 1, w - cw - 2, h - 1);
979 XDrawLine(dpy, win, dim_gc, w - cw, h - 1, w - 1, h - 1);
980 #endif /* SHADOW_RESIZEBAR */
983 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
984 int x, y, w, h;
985 int lofs = 6, rofs = 6;
986 int titlelen;
987 int allButtons = 1;
989 if (!wPreferences.new_style == TS_NEW) {
990 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
991 lofs += fwin->left_button->width + 3;
992 else
993 allButtons = 0;
995 #ifdef XKB_BUTTON_HINT
996 if (fwin->language_button && !fwin->flags.hide_language_button
997 && !fwin->flags.languagebutton_dont_fit)
998 lofs += fwin->language_button->width;
999 else
1000 allButtons = 0;
1001 #endif
1003 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1004 rofs += fwin->right_button->width + 3;
1005 else
1006 allButtons = 0;
1008 #ifdef XKB_BUTTON_HINT
1009 fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1010 #endif
1012 if (fwin->title) {
1013 Drawable buf;
1014 char *title;
1016 title = ShrinkString(*fwin->font, fwin->title, fwin->titlebar->width - lofs - rofs);
1017 titlelen = strlen(title);
1018 w = WMWidthOfString(*fwin->font, title, titlelen);
1020 switch (fwin->flags.justification) {
1021 case WTJ_LEFT:
1022 x = lofs;
1023 break;
1025 case WTJ_RIGHT:
1026 x = fwin->titlebar->width - w - rofs;
1027 break;
1029 default:
1030 if (!allButtons)
1031 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1032 else
1033 x = (fwin->titlebar->width - w) / 2;
1034 break;
1037 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1038 h = WMFontHeight(*fwin->font);
1040 if (y*2 + h > *fwin->title_max_height)
1041 y = (*fwin->title_max_height - h) / 2;
1043 if (y*2 + h < *fwin->title_min_height)
1044 y = (*fwin->title_min_height - h) / 2;
1046 /* We use a w+2 buffer to have an extra pixel on the left and
1047 * another one on the right. This is because for some odd reason,
1048 * sometimes when using AA fonts (when libfreetype2 is compiled
1049 * with bytecode interpreter turned off), some fonts are drawn
1050 * starting from x = -1 not from 0 as requested. Observed with
1051 * capital A letter on the bold 'trebuchet ms' font. -Dan
1053 buf = XCreatePixmap(dpy, fwin->titlebar->window, w + 2, h, scr->w_depth);
1055 XSetClipMask(dpy, scr->copy_gc, None);
1057 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
1058 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1059 x - 1, y, w + 2, h, 0, 0);
1060 } else {
1061 XSetForeground(dpy, scr->copy_gc, fwin->title_texture[state]->solid.normal.pixel);
1062 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w + 2, h);
1065 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1); */
1066 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1067 *fwin->font, 1, 0, title, titlelen);
1069 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc, 0, 0, w + 2, h, x - 1, y);
1071 XFreePixmap(dpy, buf);
1073 wfree(title);
1076 if (fwin->left_button)
1077 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1078 if (fwin->right_button)
1079 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1080 #ifdef XKB_BUTTON_HINT
1081 if (fwin->language_button)
1082 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1083 #endif
1087 static void reconfigure(WFrameWindow * fwin, int x, int y, int width, int height, Bool dontMove)
1089 int k = (wPreferences.new_style == TS_NEW ? 4 : 3);
1090 int resizedHorizontally = 0;
1092 if (dontMove)
1093 XResizeWindow(dpy, fwin->core->window, width, height);
1094 else
1095 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1098 if (fwin->core->height != height && fwin->resizebar)
1099 XMoveWindow(dpy, fwin->resizebar->window, 0,
1100 height - fwin->resizebar->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) {
1117 if (!fwin->flags.hide_left_button) {
1118 XUnmapWindow(dpy, fwin->left_button->window);
1120 fwin->flags.lbutton_dont_fit = 1;
1121 } else if (width >= fwin->top_width * k && fwin->flags.lbutton_dont_fit) {
1123 if (!fwin->flags.hide_left_button) {
1124 XMapWindow(dpy, fwin->left_button->window);
1126 fwin->flags.lbutton_dont_fit = 0;
1129 #ifdef XKB_BUTTON_HINT
1130 if (fwin->language_button) {
1131 if (width < fwin->top_width * k && !fwin->flags.languagebutton_dont_fit) {
1133 if (!fwin->flags.hide_language_button) {
1134 XUnmapWindow(dpy, fwin->language_button->window);
1136 fwin->flags.languagebutton_dont_fit = 1;
1137 } else if (width >= fwin->top_width * k && fwin->flags.languagebutton_dont_fit) {
1139 if (!fwin->flags.hide_language_button) {
1140 XMapWindow(dpy, fwin->language_button->window);
1142 fwin->flags.languagebutton_dont_fit = 0;
1145 #endif
1147 if (fwin->right_button) {
1148 if (width < fwin->top_width * 2 && !fwin->flags.rbutton_dont_fit) {
1150 if (!fwin->flags.hide_right_button) {
1151 XUnmapWindow(dpy, fwin->right_button->window);
1153 fwin->flags.rbutton_dont_fit = 1;
1154 } 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;
1189 void wFrameWindowConfigure(WFrameWindow * fwin, int x, int y, int width, int height)
1191 reconfigure(fwin, x, y, width, height, False);
1194 void wFrameWindowResize(WFrameWindow * fwin, int width, int height)
1196 reconfigure(fwin, 0, 0, width, height, True);
1199 int wFrameWindowChangeTitle(WFrameWindow * fwin, char *new_title)
1201 /* check if the title is the same as before */
1202 if (fwin->title) {
1203 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1204 return 0;
1206 } else {
1207 if (!new_title)
1208 return 0;
1211 if (fwin->title)
1212 wfree(fwin->title);
1214 fwin->title = wstrdup(new_title);
1216 if (fwin->titlebar) {
1217 XClearWindow(dpy, fwin->titlebar->window);
1219 wFrameWindowPaint(fwin);
1221 checkTitleSize(fwin);
1223 return 1;
1226 #ifdef XKB_BUTTON_HINT
1227 void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
1229 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1230 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
1232 #endif /* XKB_BUTTON_HINT */
1234 /*********************************************************************/
1236 static void handleExpose(WObjDescriptor * desc, XEvent * event)
1238 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1240 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1241 fwin->flags.repaint_only_titlebar = 1;
1242 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1243 fwin->flags.repaint_only_resizebar = 1;
1244 wFrameWindowPaint(fwin);
1245 fwin->flags.repaint_only_titlebar = 0;
1246 fwin->flags.repaint_only_resizebar = 0;
1249 static void checkTitleSize(WFrameWindow * fwin)
1251 int width;
1253 if (!fwin->title) {
1254 fwin->flags.incomplete_title = 0;
1255 return;
1258 if (!fwin->titlebar) {
1259 fwin->flags.incomplete_title = 1;
1260 return;
1261 } else {
1262 width = fwin->titlebar->width - 6 - 6;
1265 if (!wPreferences.new_style == TS_NEW) {
1266 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1267 width -= fwin->left_button->width + 3;
1269 #ifdef XKB_BUTTON_HINT
1270 if (fwin->language_button && !fwin->flags.hide_language_button
1271 && !fwin->flags.languagebutton_dont_fit)
1272 width -= fwin->language_button->width + 3;
1273 #endif
1275 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1276 width -= fwin->right_button->width + 3;
1278 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1279 fwin->flags.incomplete_title = 1;
1280 } else {
1281 fwin->flags.incomplete_title = 0;
1285 static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
1287 WScreen *scr = button->screen_ptr;
1288 GC copy_gc = scr->copy_gc;
1289 int x = 0, y = 0, d = 0;
1290 int left = 0, width = 0;
1292 /* setup stuff according to the state */
1293 if (pushed) {
1294 if (image) {
1295 if (image->width >= image->height * 2) {
1296 /* the image contains 2 pictures: the second is for the
1297 * pushed state */
1298 width = image->width / 2;
1299 left = image->width / 2;
1300 } else {
1301 width = image->width;
1304 XSetClipMask(dpy, copy_gc, None);
1305 if (wPreferences.new_style == TS_NEXT) {
1306 XSetForeground(dpy, copy_gc, scr->black_pixel);
1307 } else {
1308 XSetForeground(dpy, copy_gc, scr->white_pixel);
1310 d = 1;
1311 if (wPreferences.new_style == TS_NEW) {
1312 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1313 XSetForeground(dpy, copy_gc, scr->black_pixel);
1314 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1315 } else if (wPreferences.new_style == TS_OLD) {
1316 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1317 XSetForeground(dpy, copy_gc, scr->black_pixel);
1318 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1319 } else {
1320 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1321 XSetForeground(dpy, copy_gc, scr->black_pixel);
1322 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1324 } else {
1325 XClearWindow(dpy, button->window);
1327 if (image) {
1328 if (image->width >= image->height * 2)
1329 width = image->width / 2;
1330 else
1331 width = image->width;
1333 d = 0;
1335 if (wPreferences.new_style == TS_NEW) {
1336 if (texture->any.type == WTEX_SOLID || pushed) {
1337 wDrawBevel(button->window, button->width, button->height,
1338 (WTexSolid *) texture, WREL_RAISED);
1340 } else {
1341 wDrawBevel(button->window, button->width, button->height,
1342 scr->widget_texture, WREL_RAISED);
1346 if (image) {
1347 /* display image */
1348 XSetClipMask(dpy, copy_gc, image->mask);
1349 x = (button->width - width) / 2 + d;
1350 y = (button->height - image->height) / 2 + d;
1351 XSetClipOrigin(dpy, copy_gc, x - left, y);
1352 if (!wPreferences.new_style == TS_NEW) {
1353 XSetForeground(dpy, copy_gc, scr->black_pixel);
1354 if (!pushed) {
1355 if (image->depth == 1)
1356 XCopyPlane(dpy, image->image, button->window, copy_gc,
1357 left, 0, width, image->height, x, y, 1);
1358 else
1359 XCopyArea(dpy, image->image, button->window, copy_gc,
1360 left, 0, width, image->height, x, y);
1361 } else {
1362 if (wPreferences.new_style == TS_OLD) {
1363 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1364 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1365 button->width, button->height);
1366 } else {
1367 XSetForeground(dpy, copy_gc, scr->black_pixel);
1368 XCopyArea(dpy, image->image, button->window, copy_gc,
1369 left, 0, width, image->height, x, y);
1372 } else {
1373 if (pushed) {
1374 XSetForeground(dpy, copy_gc, scr->black_pixel);
1375 } else {
1376 XSetForeground(dpy, copy_gc, color);
1377 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1379 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1384 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
1386 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1387 WCoreWindow *button = (WCoreWindow *) desc->self;
1389 #ifdef XKB_BUTTON_HINT
1390 if (button == fwin->language_button) {
1391 if (wPreferences.modelock) {
1392 paintButton(button, fwin->title_texture[fwin->flags.state],
1393 WMColorPixel(fwin->title_color[fwin->flags.state]),
1394 fwin->languagebutton_image, False);
1396 } else
1397 #endif
1398 if (button == fwin->left_button) {
1399 paintButton(button, fwin->title_texture[fwin->flags.state],
1400 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
1401 } else {
1402 paintButton(button, fwin->title_texture[fwin->flags.state],
1403 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
1407 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
1409 WFrameWindow *fwin = desc->parent;
1410 WCoreWindow *titlebar = desc->self;
1412 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1413 if (fwin->on_dblclick_titlebar) {
1414 (*fwin->on_dblclick_titlebar) (titlebar, fwin->child, event);
1416 } else {
1417 if (fwin->on_mousedown_titlebar) {
1418 (*fwin->on_mousedown_titlebar) (titlebar, fwin->child, event);
1423 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event)
1425 WFrameWindow *fwin = desc->parent;
1426 WCoreWindow *resizebar = desc->self;
1428 if (fwin->on_mousedown_resizebar)
1429 (*fwin->on_mousedown_resizebar) (resizebar, fwin->child, event);
1432 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
1434 WFrameWindow *fwin = desc->parent;
1435 WCoreWindow *button = desc->self;
1436 WPixmap *image;
1437 XEvent ev;
1438 int done = 0, execute = 1;
1439 WTexture *texture;
1440 unsigned long pixel;
1441 int clickButton = event->xbutton.button;
1443 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1444 if (button == fwin->right_button && fwin->on_dblclick_right) {
1445 (*fwin->on_dblclick_right) (button, fwin->child, event);
1447 return;
1450 if (button == fwin->left_button) {
1451 image = fwin->lbutton_image;
1452 } else {
1453 image = fwin->rbutton_image;
1455 #ifdef XKB_BUTTON_HINT
1456 if (button == fwin->language_button) {
1457 if (!wPreferences.modelock)
1458 return;
1459 image = fwin->languagebutton_image;
1461 #endif
1463 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1464 texture = fwin->title_texture[fwin->flags.state];
1465 paintButton(button, texture, pixel, image, True);
1467 while (!done) {
1468 WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
1469 | ButtonPressMask | ExposureMask, &ev);
1470 switch (ev.type) {
1471 case LeaveNotify:
1472 execute = 0;
1473 paintButton(button, texture, pixel, image, False);
1474 break;
1476 case EnterNotify:
1477 execute = 1;
1478 paintButton(button, texture, pixel, image, True);
1479 break;
1481 case ButtonPress:
1482 break;
1484 case ButtonRelease:
1485 if (ev.xbutton.button == clickButton)
1486 done = 1;
1487 break;
1489 default:
1490 WMHandleEvent(&ev);
1493 paintButton(button, texture, pixel, image, False);
1495 if (execute) {
1496 if (button == fwin->left_button) {
1497 if (fwin->on_click_left)
1498 (*fwin->on_click_left) (button, fwin->child, &ev);
1499 } else if (button == fwin->right_button) {
1500 if (fwin->on_click_right)
1501 (*fwin->on_click_right) (button, fwin->child, &ev);
1503 #ifdef XKB_BUTTON_HINT
1504 else if (button == fwin->language_button) {
1505 if (fwin->on_click_language)
1506 (*fwin->on_click_language) (button, fwin->child, &ev);
1508 #endif