Fix technical drawing+opaque resize
[wmaker-crm.git] / src / framewin.c
blob73f68b23b22066e246a87e2845a09565151b3ad3
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)
67 WFrameWindow *fwin;
69 fwin = wmalloc(sizeof(WFrameWindow));
70 memset(fwin, 0, 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->core = wCoreCreateTopLevel(scr, x, y, width, height, (flags & WFF_BORDER)
89 ? FRAME_BORDER_WIDTH : 0);
90 if (wPreferences.use_saveunders) {
91 unsigned long vmask;
92 XSetWindowAttributes attribs;
94 vmask = CWSaveUnder;
95 attribs.save_under = True;
96 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
99 /* setup stacking information */
100 fwin->core->stacking = wmalloc(sizeof(WStacking));
101 fwin->core->stacking->above = NULL;
102 fwin->core->stacking->under = NULL;
103 fwin->core->stacking->child_of = NULL;
104 fwin->core->stacking->window_level = wlevel;
106 AddToStackList(fwin->core);
108 wFrameWindowUpdateBorders(fwin, flags);
110 return fwin;
113 void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
115 int theight;
116 int bsize;
117 int width, height;
118 int i;
119 WScreen *scr = fwin->screen_ptr;
121 width = fwin->core->width;
122 if (flags & WFF_IS_SHADED)
123 height = -1;
124 else
125 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
127 if (flags & WFF_TITLEBAR) {
128 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
130 if (theight > *fwin->title_max_height)
131 theight = *fwin->title_max_height;
133 if (theight < *fwin->title_min_height)
134 theight = *fwin->title_min_height;
135 } else
136 theight = 0;
138 if (wPreferences.new_style == TS_NEW) {
139 bsize = theight;
140 } else if (wPreferences.new_style == TS_OLD) {
141 bsize = theight - 7;
142 } else {
143 bsize = theight - 8;
146 if (fwin->titlebar) {
147 /* if we had a titlebar and is requesting for one,
148 * check if the size has changed and resize it */
149 if (flags & WFF_TITLEBAR) {
150 fwin->top_width = theight;
152 fwin->flags.need_texture_remake = 1;
154 if (wPreferences.new_style == TS_NEW) {
155 if (fwin->left_button) {
156 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
158 #ifdef XKB_BUTTON_HINT
159 if (fwin->language_button) {
160 if (fwin->flags.hide_left_button || !fwin->left_button
161 || fwin->flags.lbutton_dont_fit) {
162 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
163 } else {
164 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
167 #endif
169 if (fwin->right_button) {
170 wCoreConfigure(fwin->right_button, width - bsize + 1, 0, bsize, bsize);
172 } else { /* !new_style */
173 if (fwin->left_button) {
174 wCoreConfigure(fwin->left_button, 3, (theight - bsize) / 2, bsize, bsize);
176 #ifdef XKB_BUTTON_HINT
177 if (fwin->language_button) {
178 wCoreConfigure(fwin->language_button, 6 + bsize, (theight - bsize) / 2,
179 bsize, bsize);
181 #endif
183 if (fwin->right_button) {
184 wCoreConfigure(fwin->right_button, width - bsize - 3,
185 (theight - bsize) / 2, bsize, bsize);
188 updateTitlebar(fwin);
189 } else {
190 /* we had a titlebar, but now we don't need it anymore */
191 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
192 FREE_PIXMAP(fwin->title_back[i]);
193 if (wPreferences.new_style == TS_NEW) {
194 FREE_PIXMAP(fwin->lbutton_back[i]);
195 FREE_PIXMAP(fwin->rbutton_back[i]);
196 #ifdef XKB_BUTTON_HINT
197 FREE_PIXMAP(fwin->languagebutton_back[i]);
198 #endif
201 if (fwin->left_button)
202 wCoreDestroy(fwin->left_button);
203 fwin->left_button = NULL;
205 #ifdef XKB_BUTTON_HINT
206 if (fwin->language_button)
207 wCoreDestroy(fwin->language_button);
208 fwin->language_button = NULL;
209 #endif
211 if (fwin->right_button)
212 wCoreDestroy(fwin->right_button);
213 fwin->right_button = NULL;
215 wCoreDestroy(fwin->titlebar);
216 fwin->titlebar = NULL;
218 fwin->top_width = 0;
220 } else {
221 /* if we didn't have a titlebar and are being requested for
222 * one, create it */
223 if (flags & WFF_TITLEBAR) {
224 fwin->top_width = theight;
226 fwin->flags.titlebar = 1;
227 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width + 1, theight);
229 if (flags & WFF_LEFT_BUTTON) {
230 fwin->flags.left_button = 1;
231 if (wPreferences.new_style == TS_NEW) {
232 fwin->left_button = wCoreCreate(fwin->core, 0, 0, bsize, bsize);
233 if (width < theight * 4) {
234 fwin->flags.lbutton_dont_fit = 1;
235 } else {
236 XMapRaised(dpy, fwin->left_button->window);
238 } else if (wPreferences.new_style == TS_OLD) {
239 fwin->left_button =
240 wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
242 XSetWindowBackground(dpy, fwin->left_button->window,
243 scr->widget_texture->normal.pixel);
245 if (width < theight * 3) {
246 fwin->flags.lbutton_dont_fit = 1;
247 } else {
248 XMapRaised(dpy, fwin->left_button->window);
250 } else {
251 fwin->left_button =
252 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
253 bsize, bsize);
255 XSetWindowBackground(dpy, fwin->left_button->window,
256 scr->widget_texture->dark.pixel);
258 if (width < theight*3) {
259 fwin->flags.lbutton_dont_fit = 1;
260 } else {
261 XMapRaised(dpy, fwin->left_button->window);
265 #ifdef XKB_BUTTON_HINT
266 if (flags & WFF_LANGUAGE_BUTTON) {
267 fwin->flags.language_button = 1;
268 if (wPreferences.new_style == TS_NEW) {
269 fwin->language_button = wCoreCreate(fwin->core, bsize, 0, bsize, bsize);
271 if (width < theight * 4) {
272 fwin->flags.languagebutton_dont_fit = 1;
273 } else {
274 XMapRaised(dpy, fwin->language_button->window);
276 } else {
277 fwin->language_button =
278 wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
279 bsize, bsize);
281 XSetWindowBackground(dpy, fwin->language_button->window,
282 scr->widget_texture->normal.pixel);
284 if (width < theight * 3) {
285 fwin->flags.languagebutton_dont_fit = 1;
286 } else {
287 XMapRaised(dpy, fwin->language_button->window);
291 #endif
293 if (flags & WFF_RIGHT_BUTTON) {
294 fwin->flags.right_button = 1;
295 if (wPreferences.new_style == TS_NEW) {
296 fwin->right_button =
297 wCoreCreate(fwin->core, width - bsize + 1, 0, bsize, bsize);
298 } else if (wPreferences.new_style == TS_OLD) {
299 fwin->right_button =
300 wCoreCreate(fwin->titlebar, width - bsize - 3,
301 (theight - bsize) / 2, bsize, bsize);
302 XSetWindowBackground(dpy, fwin->right_button->window,
303 scr->widget_texture->normal.pixel);
304 } else {
305 fwin->right_button =
306 wCoreCreate(fwin->titlebar, width-bsize-3,
307 (theight-bsize)/2, bsize, bsize);
308 XSetWindowBackground(dpy, fwin->right_button->window,
309 scr->widget_texture->dark.pixel);
312 if (width < theight * 2) {
313 fwin->flags.rbutton_dont_fit = 1;
314 } else {
315 XMapRaised(dpy, fwin->right_button->window);
319 if (wPreferences.new_style == TS_NEW)
320 updateTitlebar(fwin);
322 XMapRaised(dpy, fwin->titlebar->window);
324 fwin->flags.need_texture_remake = 1;
327 checkTitleSize(fwin);
329 if (flags & WFF_RESIZEBAR) {
330 fwin->bottom_width = RESIZEBAR_HEIGHT;
332 if (!fwin->resizebar) {
333 fwin->flags.resizebar = 1;
334 fwin->resizebar = wCoreCreate(fwin->core, 0,
335 height + fwin->top_width, width, RESIZEBAR_HEIGHT);
336 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
337 if (width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
338 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH) / 2;
339 if (fwin->resizebar_corner_width < 0)
340 fwin->resizebar_corner_width = 0;
343 XMapWindow(dpy, fwin->resizebar->window);
344 XLowerWindow(dpy, fwin->resizebar->window);
346 fwin->flags.need_texture_remake = 1;
347 } else {
348 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height) {
349 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
350 width, RESIZEBAR_HEIGHT);
353 } else {
354 fwin->bottom_width = 0;
356 if (fwin->resizebar) {
357 fwin->bottom_width = 0;
358 wCoreDestroy(fwin->resizebar);
359 fwin->resizebar = NULL;
363 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED)) {
364 wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
367 if (flags & WFF_BORDER) {
368 XSetWindowBorderWidth(dpy, fwin->core->window, FRAME_BORDER_WIDTH);
369 } else {
370 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
373 /* setup object descriptors */
375 if (fwin->titlebar) {
376 fwin->titlebar->descriptor.handle_expose = handleExpose;
377 fwin->titlebar->descriptor.parent = fwin;
378 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
379 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
382 if (fwin->resizebar) {
383 fwin->resizebar->descriptor.handle_expose = handleExpose;
384 fwin->resizebar->descriptor.parent = fwin;
385 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
386 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
389 if (fwin->left_button) {
390 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
391 fwin->left_button->descriptor.parent = fwin;
392 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
393 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
395 #ifdef XKB_BUTTON_HINT
396 if (fwin->language_button) {
397 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
398 fwin->language_button->descriptor.parent = fwin;
399 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
400 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
402 #endif
404 if (fwin->right_button) {
405 fwin->right_button->descriptor.parent = fwin;
406 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
407 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
408 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
411 checkTitleSize(fwin);
414 void wFrameWindowDestroy(WFrameWindow * fwin)
416 int i;
418 if (fwin->left_button)
419 wCoreDestroy(fwin->left_button);
421 #ifdef XKB_BUTTON_HINT
422 if (fwin->language_button)
423 wCoreDestroy(fwin->language_button);
424 #endif
426 if (fwin->right_button)
427 wCoreDestroy(fwin->right_button);
429 if (fwin->resizebar)
430 wCoreDestroy(fwin->resizebar);
432 if (fwin->titlebar)
433 wCoreDestroy(fwin->titlebar);
435 RemoveFromStackList(fwin->core);
437 wCoreDestroy(fwin->core);
439 if (fwin->title)
440 wfree(fwin->title);
442 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
443 FREE_PIXMAP(fwin->title_back[i]);
444 if (wPreferences.new_style == TS_NEW) {
445 FREE_PIXMAP(fwin->lbutton_back[i]);
446 #ifdef XKB_BUTTON_HINT
447 FREE_PIXMAP(fwin->languagebutton_back[i]);
448 #endif
449 FREE_PIXMAP(fwin->rbutton_back[i]);
453 wfree(fwin);
456 void wFrameWindowChangeState(WFrameWindow * fwin, int state)
458 if (fwin->flags.state == state)
459 return;
461 fwin->flags.state = state;
462 fwin->flags.need_texture_change = 1;
464 wFrameWindowPaint(fwin);
467 static void updateTitlebar(WFrameWindow * fwin)
469 int x, w;
470 int theight;
472 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
474 if (theight > *fwin->title_max_height)
475 theight = *fwin->title_max_height;
477 if (theight < *fwin->title_min_height)
478 theight = *fwin->title_min_height;
480 x = 0;
481 w = fwin->core->width + 1;
483 if (wPreferences.new_style == TS_NEW) {
484 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
485 x = 0;
486 #ifdef XKB_BUTTON_HINT
487 if (fwin->language_button)
488 wCoreConfigure(fwin->language_button, 0, 0,
489 fwin->language_button->width, fwin->language_button->width);
490 #endif
491 } else {
492 #ifdef XKB_BUTTON_HINT
493 if (fwin->language_button)
494 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
495 fwin->language_button->width, fwin->language_button->width);
496 #endif
497 x = fwin->left_button->width;
498 w -= fwin->left_button->width;
500 #ifdef XKB_BUTTON_HINT
501 if (fwin->flags.hide_language_button || !fwin->language_button
502 || fwin->flags.languagebutton_dont_fit) {
503 } else {
504 x += fwin->language_button->width;
505 w -= fwin->language_button->width;
507 #endif
509 #ifdef XKB_BUTTON_HINT
510 else {
511 int bsize = theight - 7;
512 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
513 if (fwin->language_button)
514 wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
515 fwin->language_button->width, fwin->language_button->width);
516 } else {
517 if (fwin->language_button)
518 wCoreConfigure(fwin->language_button,
519 6 + fwin->left_button->width, (theight - bsize) / 2,
520 fwin->language_button->width, fwin->language_button->width);
523 #endif
525 if (wPreferences.new_style == TS_NEW) {
526 if (!fwin->flags.hide_right_button && fwin->right_button && !fwin->flags.rbutton_dont_fit) {
527 w -= fwin->right_button->width;
531 if (wPreferences.new_style == TS_NEW || fwin->titlebar->width != w)
532 fwin->flags.need_texture_remake = 1;
534 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
537 void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
539 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
540 XUnmapWindow(dpy, fwin->right_button->window);
541 fwin->flags.hide_right_button = 1;
544 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
545 XUnmapWindow(dpy, fwin->left_button->window);
546 fwin->flags.hide_left_button = 1;
548 #ifdef XKB_BUTTON_HINT
549 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
550 XUnmapWindow(dpy, fwin->language_button->window);
551 fwin->flags.hide_language_button = 1;
553 #endif
555 if (fwin->titlebar) {
556 if (wPreferences.new_style == TS_NEW) {
557 updateTitlebar(fwin);
558 } else {
559 #ifdef XKB_BUTTON_HINT
560 updateTitlebar(fwin);
561 #else
562 XClearWindow(dpy, fwin->titlebar->window);
563 wFrameWindowPaint(fwin);
564 #endif
566 checkTitleSize(fwin);
570 void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
572 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
574 if (!fwin->flags.rbutton_dont_fit)
575 XMapWindow(dpy, fwin->right_button->window);
577 fwin->flags.hide_right_button = 0;
579 #ifdef XKB_BUTTON_HINT
580 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
582 if (!fwin->flags.languagebutton_dont_fit)
583 XMapWindow(dpy, fwin->language_button->window);
585 fwin->flags.hide_language_button = 0;
587 #endif
589 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
591 if (!fwin->flags.lbutton_dont_fit)
592 XMapWindow(dpy, fwin->left_button->window);
594 fwin->flags.hide_left_button = 0;
597 if (fwin->titlebar) {
598 if (wPreferences.new_style == TS_NEW) {
599 updateTitlebar(fwin);
600 } else {
601 XClearWindow(dpy, fwin->titlebar->window);
602 wFrameWindowPaint(fwin);
604 checkTitleSize(fwin);
608 static void
609 #ifdef XKB_BUTTON_HINT
610 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
611 int bwidth, int bheight, int left, int language, int right,
612 Pixmap * title, Pixmap * lbutton, Pixmap * languagebutton, Pixmap * rbutton)
613 #else
614 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
615 int bwidth, int bheight, int left, int right, Pixmap * title, Pixmap * lbutton, Pixmap * rbutton)
616 #endif
618 RImage *img;
619 RImage *limg, *rimg, *mimg;
620 #ifdef XKB_BUTTON_HINT
621 RImage *timg;
622 #endif
623 int x, w;
625 *title = None;
626 *lbutton = None;
627 *rbutton = None;
628 #ifdef XKB_BUTTON_HINT
629 *languagebutton = None;
630 #endif
632 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
633 if (!img) {
634 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
635 return;
638 if (wPreferences.new_style == TS_NEW) {
639 if (left) {
640 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
641 } else
642 limg = NULL;
644 x = 0;
645 w = img->width;
647 #ifdef XKB_BUTTON_HINT
648 if (language) {
649 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
650 } else
651 timg = NULL;
652 #endif
654 if (limg) {
655 RBevelImage(limg, RBEV_RAISED2);
656 if (!RConvertImage(scr->rcontext, limg, lbutton)) {
657 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
659 x += limg->width;
660 w -= limg->width;
661 RReleaseImage(limg);
663 #ifdef XKB_BUTTON_HINT
664 if (timg) {
665 RBevelImage(timg, RBEV_RAISED2);
666 if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
667 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
669 x += timg->width;
670 w -= timg->width;
671 RReleaseImage(timg);
673 #endif
675 if (right) {
676 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
677 } else
678 rimg = NULL;
680 if (rimg) {
681 RBevelImage(rimg, RBEV_RAISED2);
682 if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
683 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
685 w -= rimg->width;
686 RReleaseImage(rimg);
689 if (w != width) {
690 mimg = RGetSubImage(img, x, 0, w, img->height);
691 RBevelImage(mimg, RBEV_RAISED2);
693 if (!RConvertImage(scr->rcontext, mimg, title)) {
694 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
696 RReleaseImage(mimg);
697 } else {
698 RBevelImage(img, RBEV_RAISED2);
700 if (!RConvertImage(scr->rcontext, img, title)) {
701 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
704 } else {
705 RBevelImage(img, RBEV_RAISED2);
707 if (!RConvertImage(scr->rcontext, img, title)) {
708 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
712 RReleaseImage(img);
715 static void
716 renderResizebarTexture(WScreen * scr, WTexture * texture, int width, int height, int cwidth, Pixmap * pmap)
718 RImage *img;
719 RColor light;
720 RColor dark;
722 *pmap = None;
724 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
725 if (!img) {
726 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
727 return;
730 light.alpha = 0;
731 light.red = light.green = light.blue = 80;
733 dark.alpha = 0;
734 dark.red = dark.green = dark.blue = 40;
736 ROperateLine(img, RSubtractOperation, 0, 0, width - 1, 0, &dark);
737 ROperateLine(img, RAddOperation, 0, 1, width - 1, 1, &light);
739 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height - 1, &dark);
740 ROperateLine(img, RAddOperation, cwidth + 1, 2, cwidth + 1, height - 1, &light);
742 if (width > 1)
743 ROperateLine(img, RSubtractOperation, width - cwidth - 2, 2,
744 width - cwidth - 2, height - 1, &dark);
745 ROperateLine(img, RAddOperation, width - cwidth - 1, 2, width - cwidth - 1, height - 1, &light);
747 #ifdef SHADOW_RESIZEBAR
748 ROperateLine(img, RAddOperation, 0, 1, 0, height - 1, &light);
749 ROperateLine(img, RSubtractOperation, width - 1, 1, width - 1, height - 1, &dark);
750 ROperateLine(img, RSubtractOperation, 0, height - 1, width - 1, height - 1, &dark);
751 #endif /* SHADOW_RESIZEBAR */
753 if (!RConvertImage(scr->rcontext, img, pmap)) {
754 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
757 RReleaseImage(img);
760 static void updateTexture(WFrameWindow * fwin)
762 int i;
763 unsigned long pixel;
765 i = fwin->flags.state;
766 if (fwin->titlebar) {
767 if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
768 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window, fwin->title_back[i]);
769 if (wPreferences.new_style == TS_NEW) {
770 if (fwin->left_button && fwin->lbutton_back[i])
771 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
772 fwin->lbutton_back[i]);
774 #ifdef XKB_BUTTON_HINT
775 if (fwin->language_button && fwin->languagebutton_back[i]) {
776 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
777 fwin->languagebutton_back[i]);
779 #endif
781 if (fwin->right_button && fwin->rbutton_back[i])
782 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
783 fwin->rbutton_back[i]);
785 } else {
786 pixel = fwin->title_texture[i]->solid.normal.pixel;
787 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
788 if (wPreferences.new_style == TS_NEW) {
789 if (fwin->left_button)
790 XSetWindowBackground(dpy, fwin->left_button->window, pixel);
791 #ifdef XKB_BUTTON_HINT
792 if (fwin->language_button)
793 XSetWindowBackground(dpy, fwin->language_button->window, pixel);
794 #endif
795 if (fwin->right_button)
796 XSetWindowBackground(dpy, fwin->right_button->window, pixel);
799 XClearWindow(dpy, fwin->titlebar->window);
801 if (fwin->left_button) {
802 XClearWindow(dpy, fwin->left_button->window);
803 handleButtonExpose(&fwin->left_button->descriptor, NULL);
805 #ifdef XKB_BUTTON_HINT
806 if (fwin->language_button) {
807 XClearWindow(dpy, fwin->language_button->window);
808 handleButtonExpose(&fwin->language_button->descriptor, NULL);
810 #endif
811 if (fwin->right_button) {
812 XClearWindow(dpy, fwin->right_button->window);
813 handleButtonExpose(&fwin->right_button->descriptor, NULL);
818 static void remakeTexture(WFrameWindow * fwin, int state)
820 Pixmap pmap, lpmap, rpmap;
821 #ifdef XKB_BUTTON_HINT
822 Pixmap tpmap;
823 #endif
825 if (fwin->title_texture[state] && fwin->titlebar) {
826 FREE_PIXMAP(fwin->title_back[state]);
827 if (wPreferences.new_style == TS_NEW) {
828 FREE_PIXMAP(fwin->lbutton_back[state]);
829 FREE_PIXMAP(fwin->rbutton_back[state]);
830 #ifdef XKB_BUTTON_HINT
831 FREE_PIXMAP(fwin->languagebutton_back[state]);
832 #endif
835 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
836 int left, right;
837 int width;
838 #ifdef XKB_BUTTON_HINT
839 int language;
840 #endif
842 /* eventually surrounded by if new_style */
843 left = fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit;
844 #ifdef XKB_BUTTON_HINT
845 language = fwin->language_button && !fwin->flags.hide_language_button
846 && !fwin->flags.languagebutton_dont_fit;
847 #endif
848 right = fwin->right_button && !fwin->flags.hide_right_button
849 && !fwin->flags.rbutton_dont_fit;
851 width = fwin->core->width + 1;
853 #ifdef XKB_BUTTON_HINT
854 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
855 width, fwin->titlebar->height,
856 fwin->titlebar->height, fwin->titlebar->height,
857 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
858 #else
859 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
860 width, fwin->titlebar->height,
861 fwin->titlebar->height, fwin->titlebar->height,
862 left, right, &pmap, &lpmap, &rpmap);
863 #endif
865 fwin->title_back[state] = pmap;
866 if (wPreferences.new_style == TS_NEW) {
867 fwin->lbutton_back[state] = lpmap;
868 fwin->rbutton_back[state] = rpmap;
869 #ifdef XKB_BUTTON_HINT
870 fwin->languagebutton_back[state] = tpmap;
871 #endif
875 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
876 && fwin->resizebar && state == 0) {
878 FREE_PIXMAP(fwin->resizebar_back[0]);
880 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
882 renderResizebarTexture(fwin->screen_ptr,
883 fwin->resizebar_texture[0],
884 fwin->resizebar->width,
885 fwin->resizebar->height, fwin->resizebar_corner_width, &pmap);
887 fwin->resizebar_back[0] = pmap;
890 /* this part should be in updateTexture() */
891 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
892 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
893 } else {
894 XSetWindowBackground(dpy, fwin->resizebar->window,
895 fwin->resizebar_texture[0]->solid.normal.pixel);
897 XClearWindow(dpy, fwin->resizebar->window);
901 void wFrameWindowPaint(WFrameWindow * fwin)
903 WScreen *scr = fwin->screen_ptr;
904 int state;
906 state = fwin->flags.state;
908 if (fwin->flags.is_client_window_frame)
909 fwin->flags.justification = wPreferences.title_justification;
911 if (fwin->flags.need_texture_remake) {
912 int i;
914 fwin->flags.need_texture_remake = 0;
915 fwin->flags.need_texture_change = 0;
917 if (fwin->flags.single_texture) {
918 remakeTexture(fwin, 0);
919 updateTexture(fwin);
920 } else {
921 /* first render the texture for the current state... */
922 remakeTexture(fwin, state);
923 /* ... and paint it */
924 updateTexture(fwin);
926 for (i = 0; i < 3; i++) {
927 if (i != state) {
928 remakeTexture(fwin, i);
934 if (fwin->flags.need_texture_change) {
935 fwin->flags.need_texture_change = 0;
937 updateTexture(fwin);
940 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
941 && fwin->title_texture[state]->any.type == WTEX_SOLID) {
942 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
943 fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
946 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
947 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
948 Window win;
949 int w, h;
950 int cw;
951 GC light_gc, dim_gc;
952 WTexSolid *texture = (WTexSolid *) fwin->resizebar_texture[0];
954 w = fwin->resizebar->width;
955 h = fwin->resizebar->height;
956 cw = fwin->resizebar_corner_width;
957 light_gc = texture->light_gc;
958 dim_gc = texture->dim_gc;
959 win = fwin->resizebar->window;
961 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
962 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
964 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
965 XDrawLine(dpy, win, light_gc, cw + 1, 2, cw + 1, h);
967 XDrawLine(dpy, win, dim_gc, w - cw - 2, 2, w - cw - 2, h);
968 XDrawLine(dpy, win, light_gc, w - cw - 1, 2, w - cw - 1, h);
970 #ifdef SHADOW_RESIZEBAR
971 XDrawLine(dpy, win, light_gc, 0, 1, 0, h - 1);
972 XDrawLine(dpy, win, dim_gc, w - 1, 2, w - 1, h - 1);
973 XDrawLine(dpy, win, dim_gc, 1, h - 1, cw, h - 1);
974 XDrawLine(dpy, win, dim_gc, cw + 2, h - 1, w - cw - 2, h - 1);
975 XDrawLine(dpy, win, dim_gc, w - cw, h - 1, w - 1, h - 1);
976 #endif /* SHADOW_RESIZEBAR */
979 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
980 int x, y, w, h;
981 int lofs = 6, rofs = 6;
982 int titlelen;
983 int allButtons = 1;
985 if (!wPreferences.new_style == TS_NEW) {
986 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
987 lofs += fwin->left_button->width + 3;
988 else
989 allButtons = 0;
991 #ifdef XKB_BUTTON_HINT
992 if (fwin->language_button && !fwin->flags.hide_language_button
993 && !fwin->flags.languagebutton_dont_fit)
994 lofs += fwin->language_button->width;
995 else
996 allButtons = 0;
997 #endif
999 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1000 rofs += fwin->right_button->width + 3;
1001 else
1002 allButtons = 0;
1004 #ifdef XKB_BUTTON_HINT
1005 fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1006 #endif
1008 if (fwin->title) {
1009 Drawable buf;
1010 char *title;
1012 title = ShrinkString(*fwin->font, fwin->title, fwin->titlebar->width - lofs - rofs);
1013 titlelen = strlen(title);
1014 w = WMWidthOfString(*fwin->font, title, titlelen);
1016 switch (fwin->flags.justification) {
1017 case WTJ_LEFT:
1018 x = lofs;
1019 break;
1021 case WTJ_RIGHT:
1022 x = fwin->titlebar->width - w - rofs;
1023 break;
1025 default:
1026 if (!allButtons)
1027 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1028 else
1029 x = (fwin->titlebar->width - w) / 2;
1030 break;
1033 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1034 h = WMFontHeight(*fwin->font);
1036 if (y*2 + h > *fwin->title_max_height)
1037 y = (*fwin->title_max_height - h) / 2;
1039 if (y*2 + h < *fwin->title_min_height)
1040 y = (*fwin->title_min_height - h) / 2;
1042 /* We use a w+2 buffer to have an extra pixel on the left and
1043 * another one on the right. This is because for some odd reason,
1044 * sometimes when using AA fonts (when libfreetype2 is compiled
1045 * with bytecode interpreter turned off), some fonts are drawn
1046 * starting from x = -1 not from 0 as requested. Observed with
1047 * capital A letter on the bold 'trebuchet ms' font. -Dan
1049 buf = XCreatePixmap(dpy, fwin->titlebar->window, w + 2, h, scr->w_depth);
1051 XSetClipMask(dpy, scr->copy_gc, None);
1053 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
1054 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1055 x - 1, y, w + 2, h, 0, 0);
1056 } else {
1057 XSetForeground(dpy, scr->copy_gc, fwin->title_texture[state]->solid.normal.pixel);
1058 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w + 2, h);
1061 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1); */
1062 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1063 *fwin->font, 1, 0, title, titlelen);
1065 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc, 0, 0, w + 2, h, x - 1, y);
1067 XFreePixmap(dpy, buf);
1069 wfree(title);
1072 if (fwin->left_button)
1073 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1074 if (fwin->right_button)
1075 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1076 #ifdef XKB_BUTTON_HINT
1077 if (fwin->language_button)
1078 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1079 #endif
1083 static void reconfigure(WFrameWindow * fwin, int x, int y, int width, int height, Bool dontMove)
1085 int k = (wPreferences.new_style == TS_NEW ? 4 : 3);
1086 int resizedHorizontally = 0;
1088 if (dontMove)
1089 XResizeWindow(dpy, fwin->core->window, width, height);
1090 else
1091 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1094 if (fwin->core->height != height && fwin->resizebar)
1095 XMoveWindow(dpy, fwin->resizebar->window, 0,
1096 height - fwin->resizebar->height);
1098 if (fwin->core->width != width) {
1099 fwin->flags.need_texture_remake = 1;
1100 resizedHorizontally = 1;
1103 fwin->core->width = width;
1104 fwin->core->height = height;
1106 if (fwin->titlebar && resizedHorizontally) {
1107 /* Check if the titlebar is wide enough to hold the buttons.
1108 * Temporarily remove them if can't
1110 if (fwin->left_button) {
1111 if (width < fwin->top_width * k && !fwin->flags.lbutton_dont_fit) {
1113 if (!fwin->flags.hide_left_button) {
1114 XUnmapWindow(dpy, fwin->left_button->window);
1116 fwin->flags.lbutton_dont_fit = 1;
1117 } 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) {
1129 if (!fwin->flags.hide_language_button) {
1130 XUnmapWindow(dpy, fwin->language_button->window);
1132 fwin->flags.languagebutton_dont_fit = 1;
1133 } 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) {
1146 if (!fwin->flags.hide_right_button) {
1147 XUnmapWindow(dpy, fwin->right_button->window);
1149 fwin->flags.rbutton_dont_fit = 1;
1150 } else if (width >= fwin->top_width * 2 && fwin->flags.rbutton_dont_fit) {
1152 if (!fwin->flags.hide_right_button) {
1153 XMapWindow(dpy, fwin->right_button->window);
1155 fwin->flags.rbutton_dont_fit = 0;
1159 if (wPreferences.new_style == TS_NEW) {
1160 if (fwin->right_button)
1161 XMoveWindow(dpy, fwin->right_button->window,
1162 width - fwin->right_button->width + 1, 0);
1163 } else {
1164 if (fwin->right_button)
1165 XMoveWindow(dpy, fwin->right_button->window,
1166 width - fwin->right_button->width - 3,
1167 (fwin->titlebar->height - fwin->right_button->height) / 2);
1169 updateTitlebar(fwin);
1170 checkTitleSize(fwin);
1173 if (fwin->resizebar) {
1174 wCoreConfigure(fwin->resizebar, 0,
1175 fwin->core->height - fwin->resizebar->height,
1176 fwin->core->width, fwin->resizebar->height);
1178 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1179 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
1180 fwin->resizebar_corner_width = fwin->core->width / 2;
1185 void wFrameWindowConfigure(WFrameWindow * fwin, int x, int y, int width, int height)
1187 reconfigure(fwin, x, y, width, height, False);
1190 void wFrameWindowResize(WFrameWindow * fwin, int width, int height)
1192 reconfigure(fwin, 0, 0, width, height, True);
1195 int wFrameWindowChangeTitle(WFrameWindow * fwin, char *new_title)
1197 /* check if the title is the same as before */
1198 if (fwin->title) {
1199 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1200 return 0;
1202 } else {
1203 if (!new_title)
1204 return 0;
1207 if (fwin->title)
1208 wfree(fwin->title);
1210 fwin->title = wstrdup(new_title);
1212 if (fwin->titlebar) {
1213 XClearWindow(dpy, fwin->titlebar->window);
1215 wFrameWindowPaint(fwin);
1217 checkTitleSize(fwin);
1219 return 1;
1222 #ifdef XKB_BUTTON_HINT
1223 void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
1225 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1226 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
1228 #endif /* XKB_BUTTON_HINT */
1230 /*********************************************************************/
1232 static void handleExpose(WObjDescriptor * desc, XEvent * event)
1234 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1236 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1237 fwin->flags.repaint_only_titlebar = 1;
1238 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1239 fwin->flags.repaint_only_resizebar = 1;
1240 wFrameWindowPaint(fwin);
1241 fwin->flags.repaint_only_titlebar = 0;
1242 fwin->flags.repaint_only_resizebar = 0;
1245 static void checkTitleSize(WFrameWindow * fwin)
1247 int width;
1249 if (!fwin->title) {
1250 fwin->flags.incomplete_title = 0;
1251 return;
1254 if (!fwin->titlebar) {
1255 fwin->flags.incomplete_title = 1;
1256 return;
1257 } else {
1258 width = fwin->titlebar->width - 6 - 6;
1261 if (!wPreferences.new_style == TS_NEW) {
1262 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1263 width -= fwin->left_button->width + 3;
1265 #ifdef XKB_BUTTON_HINT
1266 if (fwin->language_button && !fwin->flags.hide_language_button
1267 && !fwin->flags.languagebutton_dont_fit)
1268 width -= fwin->language_button->width + 3;
1269 #endif
1271 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1272 width -= fwin->right_button->width + 3;
1274 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1275 fwin->flags.incomplete_title = 1;
1276 } else {
1277 fwin->flags.incomplete_title = 0;
1281 static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
1283 WScreen *scr = button->screen_ptr;
1284 GC copy_gc = scr->copy_gc;
1285 int x = 0, y = 0, d = 0;
1286 int left = 0, width = 0;
1288 /* setup stuff according to the state */
1289 if (pushed) {
1290 if (image) {
1291 if (image->width >= image->height * 2) {
1292 /* the image contains 2 pictures: the second is for the
1293 * pushed state */
1294 width = image->width / 2;
1295 left = image->width / 2;
1296 } else {
1297 width = image->width;
1300 XSetClipMask(dpy, copy_gc, None);
1301 if (wPreferences.new_style == TS_NEXT) {
1302 XSetForeground(dpy, copy_gc, scr->black_pixel);
1303 } else {
1304 XSetForeground(dpy, copy_gc, scr->white_pixel);
1306 d = 1;
1307 if (wPreferences.new_style == TS_NEW) {
1308 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1309 XSetForeground(dpy, copy_gc, scr->black_pixel);
1310 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1311 } else if (wPreferences.new_style == TS_OLD) {
1312 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1313 XSetForeground(dpy, copy_gc, scr->black_pixel);
1314 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1315 } else {
1316 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1317 XSetForeground(dpy, copy_gc, scr->black_pixel);
1318 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1320 } else {
1321 XClearWindow(dpy, button->window);
1323 if (image) {
1324 if (image->width >= image->height * 2)
1325 width = image->width / 2;
1326 else
1327 width = image->width;
1329 d = 0;
1331 if (wPreferences.new_style == TS_NEW) {
1332 if (texture->any.type == WTEX_SOLID || pushed) {
1333 wDrawBevel(button->window, button->width, button->height,
1334 (WTexSolid *) texture, WREL_RAISED);
1336 } else {
1337 wDrawBevel(button->window, button->width, button->height,
1338 scr->widget_texture, WREL_RAISED);
1342 if (image) {
1343 /* display image */
1344 XSetClipMask(dpy, copy_gc, image->mask);
1345 x = (button->width - width) / 2 + d;
1346 y = (button->height - image->height) / 2 + d;
1347 XSetClipOrigin(dpy, copy_gc, x - left, y);
1348 if (!wPreferences.new_style == TS_NEW) {
1349 XSetForeground(dpy, copy_gc, scr->black_pixel);
1350 if (!pushed) {
1351 if (image->depth == 1)
1352 XCopyPlane(dpy, image->image, button->window, copy_gc,
1353 left, 0, width, image->height, x, y, 1);
1354 else
1355 XCopyArea(dpy, image->image, button->window, copy_gc,
1356 left, 0, width, image->height, x, y);
1357 } else {
1358 if (wPreferences.new_style == TS_OLD) {
1359 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1360 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1361 button->width, button->height);
1362 } else {
1363 XSetForeground(dpy, copy_gc, scr->black_pixel);
1364 XCopyArea(dpy, image->image, button->window, copy_gc,
1365 left, 0, width, image->height, x, y);
1368 } else {
1369 if (pushed) {
1370 XSetForeground(dpy, copy_gc, scr->black_pixel);
1371 } else {
1372 XSetForeground(dpy, copy_gc, color);
1373 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1375 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1380 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
1382 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1383 WCoreWindow *button = (WCoreWindow *) desc->self;
1385 #ifdef XKB_BUTTON_HINT
1386 if (button == fwin->language_button) {
1387 if (wPreferences.modelock) {
1388 paintButton(button, fwin->title_texture[fwin->flags.state],
1389 WMColorPixel(fwin->title_color[fwin->flags.state]),
1390 fwin->languagebutton_image, False);
1392 } else
1393 #endif
1394 if (button == fwin->left_button) {
1395 paintButton(button, fwin->title_texture[fwin->flags.state],
1396 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
1397 } else {
1398 paintButton(button, fwin->title_texture[fwin->flags.state],
1399 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
1403 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
1405 WFrameWindow *fwin = desc->parent;
1406 WCoreWindow *titlebar = desc->self;
1408 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1409 if (fwin->on_dblclick_titlebar) {
1410 (*fwin->on_dblclick_titlebar) (titlebar, fwin->child, event);
1412 } else {
1413 if (fwin->on_mousedown_titlebar) {
1414 (*fwin->on_mousedown_titlebar) (titlebar, fwin->child, event);
1419 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event)
1421 WFrameWindow *fwin = desc->parent;
1422 WCoreWindow *resizebar = desc->self;
1424 if (fwin->on_mousedown_resizebar)
1425 (*fwin->on_mousedown_resizebar) (resizebar, fwin->child, event);
1428 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
1430 WFrameWindow *fwin = desc->parent;
1431 WCoreWindow *button = desc->self;
1432 WPixmap *image;
1433 XEvent ev;
1434 int done = 0, execute = 1;
1435 WTexture *texture;
1436 unsigned long pixel;
1437 int clickButton = event->xbutton.button;
1439 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1440 if (button == fwin->right_button && fwin->on_dblclick_right) {
1441 (*fwin->on_dblclick_right) (button, fwin->child, event);
1443 return;
1446 if (button == fwin->left_button) {
1447 image = fwin->lbutton_image;
1448 } else {
1449 image = fwin->rbutton_image;
1451 #ifdef XKB_BUTTON_HINT
1452 if (button == fwin->language_button) {
1453 if (!wPreferences.modelock)
1454 return;
1455 image = fwin->languagebutton_image;
1457 #endif
1459 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1460 texture = fwin->title_texture[fwin->flags.state];
1461 paintButton(button, texture, pixel, image, True);
1463 while (!done) {
1464 WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
1465 | ButtonPressMask | ExposureMask, &ev);
1466 switch (ev.type) {
1467 case LeaveNotify:
1468 execute = 0;
1469 paintButton(button, texture, pixel, image, False);
1470 break;
1472 case EnterNotify:
1473 execute = 1;
1474 paintButton(button, texture, pixel, image, True);
1475 break;
1477 case ButtonPress:
1478 break;
1480 case ButtonRelease:
1481 if (ev.xbutton.button == clickButton)
1482 done = 1;
1483 break;
1485 default:
1486 WMHandleEvent(&ev);
1489 paintButton(button, texture, pixel, image, False);
1491 if (execute) {
1492 if (button == fwin->left_button) {
1493 if (fwin->on_click_left)
1494 (*fwin->on_click_left) (button, fwin->child, &ev);
1495 } else if (button == fwin->right_button) {
1496 if (fwin->on_click_right)
1497 (*fwin->on_click_right) (button, fwin->child, &ev);
1499 #ifdef XKB_BUTTON_HINT
1500 else if (button == fwin->language_button) {
1501 if (fwin->on_click_language)
1502 (*fwin->on_click_language) (button, fwin->child, &ev);
1504 #endif