Don't save app settings proplist when nothing changed
[wmaker-crm.git] / src / framewin.c
blobf47d24e2f3aac4fe9733a383eafeeb7dd5125c86
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, int flags,
63 WTexture ** title_texture, WTexture ** resize_texture,
64 WMColor ** color, WMFont ** font)
66 WFrameWindow *fwin;
68 fwin = wmalloc(sizeof(WFrameWindow));
69 memset(fwin, 0, sizeof(WFrameWindow));
71 fwin->screen_ptr = scr;
73 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
75 fwin->title_texture = title_texture;
76 fwin->resizebar_texture = resize_texture;
77 fwin->title_color = color;
78 fwin->title_clearance = clearance;
79 fwin->font = font;
80 #ifdef KEEP_XKB_LOCK_STATUS
81 fwin->languagemode = XkbGroup1Index;
82 fwin->last_languagemode = XkbGroup2Index;
83 #endif
85 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height, (flags & WFF_BORDER)
86 ? FRAME_BORDER_WIDTH : 0);
87 if (wPreferences.use_saveunders) {
88 unsigned long vmask;
89 XSetWindowAttributes attribs;
91 vmask = CWSaveUnder;
92 attribs.save_under = True;
93 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
96 /* setup stacking information */
97 fwin->core->stacking = wmalloc(sizeof(WStacking));
98 fwin->core->stacking->above = NULL;
99 fwin->core->stacking->under = NULL;
100 fwin->core->stacking->child_of = NULL;
101 fwin->core->stacking->window_level = wlevel;
103 AddToStackList(fwin->core);
105 wFrameWindowUpdateBorders(fwin, flags);
107 return fwin;
110 void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
112 int theight;
113 int bsize;
114 int width, height;
115 int i;
116 WScreen *scr = fwin->screen_ptr;
118 width = fwin->core->width;
119 if (flags & WFF_IS_SHADED)
120 height = -1;
121 else
122 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
124 if (flags & WFF_TITLEBAR)
125 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
126 else
127 theight = 0;
129 if (wPreferences.new_style == TS_NEW) {
130 bsize = theight;
131 } else if (wPreferences.new_style == TS_OLD) {
132 bsize = theight - 7;
133 } else {
134 bsize = theight - 8;
137 if (fwin->titlebar) {
138 /* if we had a titlebar and is requesting for one,
139 * check if the size has changed and resize it */
140 if (flags & WFF_TITLEBAR) {
141 fwin->top_width = theight;
143 fwin->flags.need_texture_remake = 1;
145 if (wPreferences.new_style == TS_NEW) {
146 if (fwin->left_button) {
147 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
149 #ifdef XKB_BUTTON_HINT
150 if (fwin->language_button) {
151 if (fwin->flags.hide_left_button || !fwin->left_button
152 || fwin->flags.lbutton_dont_fit) {
153 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
154 } else {
155 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
158 #endif
160 if (fwin->right_button) {
161 wCoreConfigure(fwin->right_button, width - bsize + 1, 0, bsize, bsize);
163 } else { /* !new_style */
164 if (fwin->left_button) {
165 wCoreConfigure(fwin->left_button, 3, (theight - bsize) / 2, bsize, bsize);
167 #ifdef XKB_BUTTON_HINT
168 if (fwin->language_button) {
169 wCoreConfigure(fwin->language_button, 6 + bsize, (theight - bsize) / 2,
170 bsize, bsize);
172 #endif
174 if (fwin->right_button) {
175 wCoreConfigure(fwin->right_button, width - bsize - 3,
176 (theight - bsize) / 2, bsize, bsize);
179 updateTitlebar(fwin);
180 } else {
181 /* we had a titlebar, but now we don't need it anymore */
182 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
183 FREE_PIXMAP(fwin->title_back[i]);
184 if (wPreferences.new_style == TS_NEW) {
185 FREE_PIXMAP(fwin->lbutton_back[i]);
186 FREE_PIXMAP(fwin->rbutton_back[i]);
187 #ifdef XKB_BUTTON_HINT
188 FREE_PIXMAP(fwin->languagebutton_back[i]);
189 #endif
192 if (fwin->left_button)
193 wCoreDestroy(fwin->left_button);
194 fwin->left_button = NULL;
196 #ifdef XKB_BUTTON_HINT
197 if (fwin->language_button)
198 wCoreDestroy(fwin->language_button);
199 fwin->language_button = NULL;
200 #endif
202 if (fwin->right_button)
203 wCoreDestroy(fwin->right_button);
204 fwin->right_button = NULL;
206 wCoreDestroy(fwin->titlebar);
207 fwin->titlebar = NULL;
209 fwin->top_width = 0;
211 } else {
212 /* if we didn't have a titlebar and are being requested for
213 * one, create it */
214 if (flags & WFF_TITLEBAR) {
215 fwin->top_width = theight;
217 fwin->flags.titlebar = 1;
218 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width + 1, theight);
220 if (flags & WFF_LEFT_BUTTON) {
221 fwin->flags.left_button = 1;
222 if (wPreferences.new_style == TS_NEW) {
223 fwin->left_button = wCoreCreate(fwin->core, 0, 0, bsize, bsize);
224 if (width < theight * 4) {
225 fwin->flags.lbutton_dont_fit = 1;
226 } else {
227 XMapRaised(dpy, fwin->left_button->window);
229 } else if (wPreferences.new_style == TS_OLD) {
230 fwin->left_button =
231 wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
233 XSetWindowBackground(dpy, fwin->left_button->window,
234 scr->widget_texture->normal.pixel);
236 if (width < theight * 3) {
237 fwin->flags.lbutton_dont_fit = 1;
238 } else {
239 XMapRaised(dpy, fwin->left_button->window);
241 } else {
242 fwin->left_button =
243 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
244 bsize, bsize);
246 XSetWindowBackground(dpy, fwin->left_button->window,
247 scr->widget_texture->dark.pixel);
249 if (width < theight*3) {
250 fwin->flags.lbutton_dont_fit = 1;
251 } else {
252 XMapRaised(dpy, fwin->left_button->window);
256 #ifdef XKB_BUTTON_HINT
257 if (flags & WFF_LANGUAGE_BUTTON) {
258 fwin->flags.language_button = 1;
259 if (wPreferences.new_style == TS_NEW) {
260 fwin->language_button = wCoreCreate(fwin->core, bsize, 0, bsize, bsize);
262 if (width < theight * 4) {
263 fwin->flags.languagebutton_dont_fit = 1;
264 } else {
265 XMapRaised(dpy, fwin->language_button->window);
267 } else {
268 fwin->language_button =
269 wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
270 bsize, bsize);
272 XSetWindowBackground(dpy, fwin->language_button->window,
273 scr->widget_texture->normal.pixel);
275 if (width < theight * 3) {
276 fwin->flags.languagebutton_dont_fit = 1;
277 } else {
278 XMapRaised(dpy, fwin->language_button->window);
282 #endif
284 if (flags & WFF_RIGHT_BUTTON) {
285 fwin->flags.right_button = 1;
286 if (wPreferences.new_style == TS_NEW) {
287 fwin->right_button =
288 wCoreCreate(fwin->core, width - bsize + 1, 0, bsize, bsize);
289 } else if (wPreferences.new_style == TS_OLD) {
290 fwin->right_button =
291 wCoreCreate(fwin->titlebar, width - bsize - 3,
292 (theight - bsize) / 2, bsize, bsize);
293 XSetWindowBackground(dpy, fwin->right_button->window,
294 scr->widget_texture->normal.pixel);
295 } else {
296 fwin->right_button =
297 wCoreCreate(fwin->titlebar, width-bsize-3,
298 (theight-bsize)/2, bsize, bsize);
299 XSetWindowBackground(dpy, fwin->right_button->window,
300 scr->widget_texture->dark.pixel);
303 if (width < theight * 2) {
304 fwin->flags.rbutton_dont_fit = 1;
305 } else {
306 XMapRaised(dpy, fwin->right_button->window);
310 if (wPreferences.new_style == TS_NEW)
311 updateTitlebar(fwin);
313 XMapRaised(dpy, fwin->titlebar->window);
315 fwin->flags.need_texture_remake = 1;
318 checkTitleSize(fwin);
320 if (flags & WFF_RESIZEBAR) {
321 fwin->bottom_width = RESIZEBAR_HEIGHT;
323 if (!fwin->resizebar) {
324 fwin->flags.resizebar = 1;
325 fwin->resizebar = wCoreCreate(fwin->core, 0,
326 height + fwin->top_width, width, RESIZEBAR_HEIGHT);
327 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
328 if (width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
329 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH) / 2;
330 if (fwin->resizebar_corner_width < 0)
331 fwin->resizebar_corner_width = 0;
334 XMapWindow(dpy, fwin->resizebar->window);
335 XLowerWindow(dpy, fwin->resizebar->window);
337 fwin->flags.need_texture_remake = 1;
338 } else {
339 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height) {
340 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
341 width, RESIZEBAR_HEIGHT);
344 } else {
345 fwin->bottom_width = 0;
347 if (fwin->resizebar) {
348 fwin->bottom_width = 0;
349 wCoreDestroy(fwin->resizebar);
350 fwin->resizebar = NULL;
354 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED)) {
355 wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
358 if (flags & WFF_BORDER) {
359 XSetWindowBorderWidth(dpy, fwin->core->window, FRAME_BORDER_WIDTH);
360 } else {
361 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
364 /* setup object descriptors */
366 if (fwin->titlebar) {
367 fwin->titlebar->descriptor.handle_expose = handleExpose;
368 fwin->titlebar->descriptor.parent = fwin;
369 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
370 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
373 if (fwin->resizebar) {
374 fwin->resizebar->descriptor.handle_expose = handleExpose;
375 fwin->resizebar->descriptor.parent = fwin;
376 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
377 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
380 if (fwin->left_button) {
381 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
382 fwin->left_button->descriptor.parent = fwin;
383 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
384 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
386 #ifdef XKB_BUTTON_HINT
387 if (fwin->language_button) {
388 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
389 fwin->language_button->descriptor.parent = fwin;
390 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
391 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
393 #endif
395 if (fwin->right_button) {
396 fwin->right_button->descriptor.parent = fwin;
397 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
398 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
399 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
402 checkTitleSize(fwin);
405 void wFrameWindowDestroy(WFrameWindow * fwin)
407 int i;
409 if (fwin->left_button)
410 wCoreDestroy(fwin->left_button);
412 #ifdef XKB_BUTTON_HINT
413 if (fwin->language_button)
414 wCoreDestroy(fwin->language_button);
415 #endif
417 if (fwin->right_button)
418 wCoreDestroy(fwin->right_button);
420 if (fwin->resizebar)
421 wCoreDestroy(fwin->resizebar);
423 if (fwin->titlebar)
424 wCoreDestroy(fwin->titlebar);
426 RemoveFromStackList(fwin->core);
428 wCoreDestroy(fwin->core);
430 if (fwin->title)
431 wfree(fwin->title);
433 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
434 FREE_PIXMAP(fwin->title_back[i]);
435 if (wPreferences.new_style == TS_NEW) {
436 FREE_PIXMAP(fwin->lbutton_back[i]);
437 #ifdef XKB_BUTTON_HINT
438 FREE_PIXMAP(fwin->languagebutton_back[i]);
439 #endif
440 FREE_PIXMAP(fwin->rbutton_back[i]);
444 wfree(fwin);
447 void wFrameWindowChangeState(WFrameWindow * fwin, int state)
449 if (fwin->flags.state == state)
450 return;
452 fwin->flags.state = state;
453 fwin->flags.need_texture_change = 1;
455 wFrameWindowPaint(fwin);
458 static void updateTitlebar(WFrameWindow * fwin)
460 int x, w;
461 int theight;
463 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
465 x = 0;
466 w = fwin->core->width + 1;
468 if (wPreferences.new_style == TS_NEW) {
469 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
470 x = 0;
471 #ifdef XKB_BUTTON_HINT
472 if (fwin->language_button)
473 wCoreConfigure(fwin->language_button, 0, 0,
474 fwin->language_button->width, fwin->language_button->width);
475 #endif
476 } else {
477 #ifdef XKB_BUTTON_HINT
478 if (fwin->language_button)
479 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
480 fwin->language_button->width, fwin->language_button->width);
481 #endif
482 x = fwin->left_button->width;
483 w -= fwin->left_button->width;
485 #ifdef XKB_BUTTON_HINT
486 if (fwin->flags.hide_language_button || !fwin->language_button
487 || fwin->flags.languagebutton_dont_fit) {
488 } else {
489 x += fwin->language_button->width;
490 w -= fwin->language_button->width;
492 #endif
494 #ifdef XKB_BUTTON_HINT
495 else {
496 int bsize = theight - 7;
497 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
498 if (fwin->language_button)
499 wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
500 fwin->language_button->width, fwin->language_button->width);
501 } else {
502 if (fwin->language_button)
503 wCoreConfigure(fwin->language_button,
504 6 + fwin->left_button->width, (theight - bsize) / 2,
505 fwin->language_button->width, fwin->language_button->width);
508 #endif
510 if (wPreferences.new_style == TS_NEW) {
511 if (!fwin->flags.hide_right_button && fwin->right_button && !fwin->flags.rbutton_dont_fit) {
512 w -= fwin->right_button->width;
516 if (wPreferences.new_style == TS_NEW || fwin->titlebar->width != w)
517 fwin->flags.need_texture_remake = 1;
519 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
522 void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
524 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
525 XUnmapWindow(dpy, fwin->right_button->window);
526 fwin->flags.hide_right_button = 1;
529 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
530 XUnmapWindow(dpy, fwin->left_button->window);
531 fwin->flags.hide_left_button = 1;
533 #ifdef XKB_BUTTON_HINT
534 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
535 XUnmapWindow(dpy, fwin->language_button->window);
536 fwin->flags.hide_language_button = 1;
538 #endif
540 if (fwin->titlebar) {
541 if (wPreferences.new_style == TS_NEW) {
542 updateTitlebar(fwin);
543 } else {
544 #ifdef XKB_BUTTON_HINT
545 updateTitlebar(fwin);
546 #else
547 XClearWindow(dpy, fwin->titlebar->window);
548 wFrameWindowPaint(fwin);
549 #endif
551 checkTitleSize(fwin);
555 void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
557 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
559 if (!fwin->flags.rbutton_dont_fit)
560 XMapWindow(dpy, fwin->right_button->window);
562 fwin->flags.hide_right_button = 0;
564 #ifdef XKB_BUTTON_HINT
565 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
567 if (!fwin->flags.languagebutton_dont_fit)
568 XMapWindow(dpy, fwin->language_button->window);
570 fwin->flags.hide_language_button = 0;
572 #endif
574 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
576 if (!fwin->flags.lbutton_dont_fit)
577 XMapWindow(dpy, fwin->left_button->window);
579 fwin->flags.hide_left_button = 0;
582 if (fwin->titlebar) {
583 if (wPreferences.new_style == TS_NEW) {
584 updateTitlebar(fwin);
585 } else {
586 XClearWindow(dpy, fwin->titlebar->window);
587 wFrameWindowPaint(fwin);
589 checkTitleSize(fwin);
593 static void
594 #ifdef XKB_BUTTON_HINT
595 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
596 int bwidth, int bheight, int left, int language, int right,
597 Pixmap * title, Pixmap * lbutton, Pixmap * languagebutton, Pixmap * rbutton)
598 #else
599 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
600 int bwidth, int bheight, int left, int right, Pixmap * title, Pixmap * lbutton, Pixmap * rbutton)
601 #endif
603 RImage *img;
604 RImage *limg, *rimg, *mimg;
605 #ifdef XKB_BUTTON_HINT
606 RImage *timg;
607 #endif
608 int x, w;
610 *title = None;
611 *lbutton = None;
612 *rbutton = None;
613 #ifdef XKB_BUTTON_HINT
614 *languagebutton = None;
615 #endif
617 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
618 if (!img) {
619 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
620 return;
623 if (wPreferences.new_style == TS_NEW) {
624 if (left) {
625 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
626 } else
627 limg = NULL;
629 x = 0;
630 w = img->width;
632 #ifdef XKB_BUTTON_HINT
633 if (language) {
634 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
635 } else
636 timg = NULL;
637 #endif
639 if (limg) {
640 RBevelImage(limg, RBEV_RAISED2);
641 if (!RConvertImage(scr->rcontext, limg, lbutton)) {
642 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
644 x += limg->width;
645 w -= limg->width;
646 RReleaseImage(limg);
648 #ifdef XKB_BUTTON_HINT
649 if (timg) {
650 RBevelImage(timg, RBEV_RAISED2);
651 if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
652 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
654 x += timg->width;
655 w -= timg->width;
656 RReleaseImage(timg);
658 #endif
660 if (right) {
661 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
662 } else
663 rimg = NULL;
665 if (rimg) {
666 RBevelImage(rimg, RBEV_RAISED2);
667 if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
668 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
670 w -= rimg->width;
671 RReleaseImage(rimg);
674 if (w != width) {
675 mimg = RGetSubImage(img, x, 0, w, img->height);
676 RBevelImage(mimg, RBEV_RAISED2);
678 if (!RConvertImage(scr->rcontext, mimg, title)) {
679 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
681 RReleaseImage(mimg);
682 } else {
683 RBevelImage(img, RBEV_RAISED2);
685 if (!RConvertImage(scr->rcontext, img, title)) {
686 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
689 } else {
690 RBevelImage(img, RBEV_RAISED2);
692 if (!RConvertImage(scr->rcontext, img, title)) {
693 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
697 RReleaseImage(img);
700 static void
701 renderResizebarTexture(WScreen * scr, WTexture * texture, int width, int height, int cwidth, Pixmap * pmap)
703 RImage *img;
704 RColor light;
705 RColor dark;
707 *pmap = None;
709 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
710 if (!img) {
711 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
712 return;
715 light.alpha = 0;
716 light.red = light.green = light.blue = 80;
718 dark.alpha = 0;
719 dark.red = dark.green = dark.blue = 40;
721 ROperateLine(img, RSubtractOperation, 0, 0, width - 1, 0, &dark);
722 ROperateLine(img, RAddOperation, 0, 1, width - 1, 1, &light);
724 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height - 1, &dark);
725 ROperateLine(img, RAddOperation, cwidth + 1, 2, cwidth + 1, height - 1, &light);
727 if (width > 1)
728 ROperateLine(img, RSubtractOperation, width - cwidth - 2, 2,
729 width - cwidth - 2, height - 1, &dark);
730 ROperateLine(img, RAddOperation, width - cwidth - 1, 2, width - cwidth - 1, height - 1, &light);
732 #ifdef SHADOW_RESIZEBAR
733 ROperateLine(img, RAddOperation, 0, 1, 0, height - 1, &light);
734 ROperateLine(img, RSubtractOperation, width - 1, 1, width - 1, height - 1, &dark);
735 ROperateLine(img, RSubtractOperation, 0, height - 1, width - 1, height - 1, &dark);
736 #endif /* SHADOW_RESIZEBAR */
738 if (!RConvertImage(scr->rcontext, img, pmap)) {
739 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
742 RReleaseImage(img);
745 static void updateTexture(WFrameWindow * fwin)
747 int i;
748 unsigned long pixel;
750 i = fwin->flags.state;
751 if (fwin->titlebar) {
752 if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
753 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window, fwin->title_back[i]);
754 if (wPreferences.new_style == TS_NEW) {
755 if (fwin->left_button && fwin->lbutton_back[i])
756 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
757 fwin->lbutton_back[i]);
759 #ifdef XKB_BUTTON_HINT
760 if (fwin->language_button && fwin->languagebutton_back[i]) {
761 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
762 fwin->languagebutton_back[i]);
764 #endif
766 if (fwin->right_button && fwin->rbutton_back[i])
767 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
768 fwin->rbutton_back[i]);
770 } else {
771 pixel = fwin->title_texture[i]->solid.normal.pixel;
772 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
773 if (wPreferences.new_style == TS_NEW) {
774 if (fwin->left_button)
775 XSetWindowBackground(dpy, fwin->left_button->window, pixel);
776 #ifdef XKB_BUTTON_HINT
777 if (fwin->language_button)
778 XSetWindowBackground(dpy, fwin->language_button->window, pixel);
779 #endif
780 if (fwin->right_button)
781 XSetWindowBackground(dpy, fwin->right_button->window, pixel);
784 XClearWindow(dpy, fwin->titlebar->window);
786 if (fwin->left_button) {
787 XClearWindow(dpy, fwin->left_button->window);
788 handleButtonExpose(&fwin->left_button->descriptor, NULL);
790 #ifdef XKB_BUTTON_HINT
791 if (fwin->language_button) {
792 XClearWindow(dpy, fwin->language_button->window);
793 handleButtonExpose(&fwin->language_button->descriptor, NULL);
795 #endif
796 if (fwin->right_button) {
797 XClearWindow(dpy, fwin->right_button->window);
798 handleButtonExpose(&fwin->right_button->descriptor, NULL);
803 static void remakeTexture(WFrameWindow * fwin, int state)
805 Pixmap pmap, lpmap, rpmap;
806 #ifdef XKB_BUTTON_HINT
807 Pixmap tpmap;
808 #endif
810 if (fwin->title_texture[state] && fwin->titlebar) {
811 FREE_PIXMAP(fwin->title_back[state]);
812 if (wPreferences.new_style == TS_NEW) {
813 FREE_PIXMAP(fwin->lbutton_back[state]);
814 FREE_PIXMAP(fwin->rbutton_back[state]);
815 #ifdef XKB_BUTTON_HINT
816 FREE_PIXMAP(fwin->languagebutton_back[state]);
817 #endif
820 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
821 int left, right;
822 int width;
823 #ifdef XKB_BUTTON_HINT
824 int language;
825 #endif
827 /* eventually surrounded by if new_style */
828 left = fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit;
829 #ifdef XKB_BUTTON_HINT
830 language = fwin->language_button && !fwin->flags.hide_language_button
831 && !fwin->flags.languagebutton_dont_fit;
832 #endif
833 right = fwin->right_button && !fwin->flags.hide_right_button
834 && !fwin->flags.rbutton_dont_fit;
836 width = fwin->core->width + 1;
838 #ifdef XKB_BUTTON_HINT
839 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
840 width, fwin->titlebar->height,
841 fwin->titlebar->height, fwin->titlebar->height,
842 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
843 #else
844 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
845 width, fwin->titlebar->height,
846 fwin->titlebar->height, fwin->titlebar->height,
847 left, right, &pmap, &lpmap, &rpmap);
848 #endif
850 fwin->title_back[state] = pmap;
851 if (wPreferences.new_style == TS_NEW) {
852 fwin->lbutton_back[state] = lpmap;
853 fwin->rbutton_back[state] = rpmap;
854 #ifdef XKB_BUTTON_HINT
855 fwin->languagebutton_back[state] = tpmap;
856 #endif
860 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
861 && fwin->resizebar && state == 0) {
863 FREE_PIXMAP(fwin->resizebar_back[0]);
865 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
867 renderResizebarTexture(fwin->screen_ptr,
868 fwin->resizebar_texture[0],
869 fwin->resizebar->width,
870 fwin->resizebar->height, fwin->resizebar_corner_width, &pmap);
872 fwin->resizebar_back[0] = pmap;
875 /* this part should be in updateTexture() */
876 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
877 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
878 } else {
879 XSetWindowBackground(dpy, fwin->resizebar->window,
880 fwin->resizebar_texture[0]->solid.normal.pixel);
882 XClearWindow(dpy, fwin->resizebar->window);
886 void wFrameWindowPaint(WFrameWindow * fwin)
888 WScreen *scr = fwin->screen_ptr;
889 int state;
891 state = fwin->flags.state;
893 if (fwin->flags.is_client_window_frame)
894 fwin->flags.justification = wPreferences.title_justification;
896 if (fwin->flags.need_texture_remake) {
897 int i;
899 fwin->flags.need_texture_remake = 0;
900 fwin->flags.need_texture_change = 0;
902 if (fwin->flags.single_texture) {
903 remakeTexture(fwin, 0);
904 updateTexture(fwin);
905 } else {
906 /* first render the texture for the current state... */
907 remakeTexture(fwin, state);
908 /* ... and paint it */
909 updateTexture(fwin);
911 for (i = 0; i < 3; i++) {
912 if (i != state) {
913 remakeTexture(fwin, i);
919 if (fwin->flags.need_texture_change) {
920 fwin->flags.need_texture_change = 0;
922 updateTexture(fwin);
925 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
926 && fwin->title_texture[state]->any.type == WTEX_SOLID) {
927 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
928 fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
931 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
932 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
933 Window win;
934 int w, h;
935 int cw;
936 GC light_gc, dim_gc;
937 WTexSolid *texture = (WTexSolid *) fwin->resizebar_texture[0];
939 w = fwin->resizebar->width;
940 h = fwin->resizebar->height;
941 cw = fwin->resizebar_corner_width;
942 light_gc = texture->light_gc;
943 dim_gc = texture->dim_gc;
944 win = fwin->resizebar->window;
946 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
947 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
949 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
950 XDrawLine(dpy, win, light_gc, cw + 1, 2, cw + 1, h);
952 XDrawLine(dpy, win, dim_gc, w - cw - 2, 2, w - cw - 2, h);
953 XDrawLine(dpy, win, light_gc, w - cw - 1, 2, w - cw - 1, h);
955 #ifdef SHADOW_RESIZEBAR
956 XDrawLine(dpy, win, light_gc, 0, 1, 0, h - 1);
957 XDrawLine(dpy, win, dim_gc, w - 1, 2, w - 1, h - 1);
958 XDrawLine(dpy, win, dim_gc, 1, h - 1, cw, h - 1);
959 XDrawLine(dpy, win, dim_gc, cw + 2, h - 1, w - cw - 2, h - 1);
960 XDrawLine(dpy, win, dim_gc, w - cw, h - 1, w - 1, h - 1);
961 #endif /* SHADOW_RESIZEBAR */
964 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
965 int x, y, w, h;
966 int lofs = 6, rofs = 6;
967 int titlelen;
968 int allButtons = 1;
970 if (!wPreferences.new_style == TS_NEW) {
971 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
972 lofs += fwin->left_button->width + 3;
973 else
974 allButtons = 0;
976 #ifdef XKB_BUTTON_HINT
977 if (fwin->language_button && !fwin->flags.hide_language_button
978 && !fwin->flags.languagebutton_dont_fit)
979 lofs += fwin->language_button->width;
980 else
981 allButtons = 0;
982 #endif
984 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
985 rofs += fwin->right_button->width + 3;
986 else
987 allButtons = 0;
989 #ifdef XKB_BUTTON_HINT
990 fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
991 #endif
993 if (fwin->title) {
994 Drawable buf;
995 char *title;
997 title = ShrinkString(*fwin->font, fwin->title, fwin->titlebar->width - lofs - rofs);
998 titlelen = strlen(title);
999 w = WMWidthOfString(*fwin->font, title, titlelen);
1001 switch (fwin->flags.justification) {
1002 case WTJ_LEFT:
1003 x = lofs;
1004 break;
1006 case WTJ_RIGHT:
1007 x = fwin->titlebar->width - w - rofs;
1008 break;
1010 default:
1011 if (!allButtons)
1012 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1013 else
1014 x = (fwin->titlebar->width - w) / 2;
1015 break;
1018 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1019 h = WMFontHeight(*fwin->font);
1021 /* We use a w+2 buffer to have an extra pixel on the left and
1022 * another one on the right. This is because for some odd reason,
1023 * sometimes when using AA fonts (when libfreetype2 is compiled
1024 * with bytecode interpreter turned off), some fonts are drawn
1025 * starting from x = -1 not from 0 as requested. Observed with
1026 * capital A letter on the bold 'trebuchet ms' font. -Dan
1028 buf = XCreatePixmap(dpy, fwin->titlebar->window, w + 2, h, scr->w_depth);
1030 XSetClipMask(dpy, scr->copy_gc, None);
1032 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
1033 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1034 x - 1, y, w + 2, h, 0, 0);
1035 } else {
1036 XSetForeground(dpy, scr->copy_gc, fwin->title_texture[state]->solid.normal.pixel);
1037 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w + 2, h);
1040 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1); */
1041 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1042 *fwin->font, 1, 0, title, titlelen);
1044 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc, 0, 0, w + 2, h, x - 1, y);
1046 XFreePixmap(dpy, buf);
1048 wfree(title);
1051 if (fwin->left_button)
1052 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1053 if (fwin->right_button)
1054 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1055 #ifdef XKB_BUTTON_HINT
1056 if (fwin->language_button)
1057 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1058 #endif
1062 static void reconfigure(WFrameWindow * fwin, int x, int y, int width, int height, Bool dontMove)
1064 int k = (wPreferences.new_style == TS_NEW ? 4 : 3);
1065 int resizedHorizontally = 0;
1067 if (dontMove)
1068 XResizeWindow(dpy, fwin->core->window, width, height);
1069 else
1070 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1073 if (fwin->core->height != height && fwin->resizebar)
1074 XMoveWindow(dpy, fwin->resizebar->window, 0,
1075 height - fwin->resizebar->height);
1077 if (fwin->core->width != width) {
1078 fwin->flags.need_texture_remake = 1;
1079 resizedHorizontally = 1;
1082 fwin->core->width = width;
1083 fwin->core->height = height;
1085 if (fwin->titlebar && resizedHorizontally) {
1086 /* Check if the titlebar is wide enough to hold the buttons.
1087 * Temporarily remove them if can't
1089 if (fwin->left_button) {
1090 if (width < fwin->top_width * k && !fwin->flags.lbutton_dont_fit) {
1092 if (!fwin->flags.hide_left_button) {
1093 XUnmapWindow(dpy, fwin->left_button->window);
1095 fwin->flags.lbutton_dont_fit = 1;
1096 } else if (width >= fwin->top_width * k && fwin->flags.lbutton_dont_fit) {
1098 if (!fwin->flags.hide_left_button) {
1099 XMapWindow(dpy, fwin->left_button->window);
1101 fwin->flags.lbutton_dont_fit = 0;
1104 #ifdef XKB_BUTTON_HINT
1105 if (fwin->language_button) {
1106 if (width < fwin->top_width * k && !fwin->flags.languagebutton_dont_fit) {
1108 if (!fwin->flags.hide_language_button) {
1109 XUnmapWindow(dpy, fwin->language_button->window);
1111 fwin->flags.languagebutton_dont_fit = 1;
1112 } else if (width >= fwin->top_width * k && fwin->flags.languagebutton_dont_fit) {
1114 if (!fwin->flags.hide_language_button) {
1115 XMapWindow(dpy, fwin->language_button->window);
1117 fwin->flags.languagebutton_dont_fit = 0;
1120 #endif
1122 if (fwin->right_button) {
1123 if (width < fwin->top_width * 2 && !fwin->flags.rbutton_dont_fit) {
1125 if (!fwin->flags.hide_right_button) {
1126 XUnmapWindow(dpy, fwin->right_button->window);
1128 fwin->flags.rbutton_dont_fit = 1;
1129 } else if (width >= fwin->top_width * 2 && fwin->flags.rbutton_dont_fit) {
1131 if (!fwin->flags.hide_right_button) {
1132 XMapWindow(dpy, fwin->right_button->window);
1134 fwin->flags.rbutton_dont_fit = 0;
1138 if (wPreferences.new_style == TS_NEW) {
1139 if (fwin->right_button)
1140 XMoveWindow(dpy, fwin->right_button->window,
1141 width - fwin->right_button->width + 1, 0);
1142 } else {
1143 if (fwin->right_button)
1144 XMoveWindow(dpy, fwin->right_button->window,
1145 width - fwin->right_button->width - 3,
1146 (fwin->titlebar->height - fwin->right_button->height) / 2);
1148 updateTitlebar(fwin);
1149 checkTitleSize(fwin);
1152 if (fwin->resizebar) {
1153 wCoreConfigure(fwin->resizebar, 0,
1154 fwin->core->height - fwin->resizebar->height,
1155 fwin->core->width, fwin->resizebar->height);
1157 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1158 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
1159 fwin->resizebar_corner_width = fwin->core->width / 2;
1164 void wFrameWindowConfigure(WFrameWindow * fwin, int x, int y, int width, int height)
1166 reconfigure(fwin, x, y, width, height, False);
1169 void wFrameWindowResize(WFrameWindow * fwin, int width, int height)
1171 reconfigure(fwin, 0, 0, width, height, True);
1174 int wFrameWindowChangeTitle(WFrameWindow * fwin, char *new_title)
1176 /* check if the title is the same as before */
1177 if (fwin->title) {
1178 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1179 return 0;
1181 } else {
1182 if (!new_title)
1183 return 0;
1186 if (fwin->title)
1187 wfree(fwin->title);
1189 fwin->title = wstrdup(new_title);
1191 if (fwin->titlebar) {
1192 XClearWindow(dpy, fwin->titlebar->window);
1194 wFrameWindowPaint(fwin);
1196 checkTitleSize(fwin);
1198 return 1;
1201 #ifdef XKB_BUTTON_HINT
1202 void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
1204 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1205 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
1207 #endif /* XKB_BUTTON_HINT */
1209 /*********************************************************************/
1211 static void handleExpose(WObjDescriptor * desc, XEvent * event)
1213 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1215 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1216 fwin->flags.repaint_only_titlebar = 1;
1217 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1218 fwin->flags.repaint_only_resizebar = 1;
1219 wFrameWindowPaint(fwin);
1220 fwin->flags.repaint_only_titlebar = 0;
1221 fwin->flags.repaint_only_resizebar = 0;
1224 static void checkTitleSize(WFrameWindow * fwin)
1226 int width;
1228 if (!fwin->title) {
1229 fwin->flags.incomplete_title = 0;
1230 return;
1233 if (!fwin->titlebar) {
1234 fwin->flags.incomplete_title = 1;
1235 return;
1236 } else {
1237 width = fwin->titlebar->width - 6 - 6;
1240 if (!wPreferences.new_style == TS_NEW) {
1241 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1242 width -= fwin->left_button->width + 3;
1244 #ifdef XKB_BUTTON_HINT
1245 if (fwin->language_button && !fwin->flags.hide_language_button
1246 && !fwin->flags.languagebutton_dont_fit)
1247 width -= fwin->language_button->width + 3;
1248 #endif
1250 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1251 width -= fwin->right_button->width + 3;
1253 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1254 fwin->flags.incomplete_title = 1;
1255 } else {
1256 fwin->flags.incomplete_title = 0;
1260 static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
1262 WScreen *scr = button->screen_ptr;
1263 GC copy_gc = scr->copy_gc;
1264 int x = 0, y = 0, d = 0;
1265 int left = 0, width = 0;
1267 /* setup stuff according to the state */
1268 if (pushed) {
1269 if (image) {
1270 if (image->width >= image->height * 2) {
1271 /* the image contains 2 pictures: the second is for the
1272 * pushed state */
1273 width = image->width / 2;
1274 left = image->width / 2;
1275 } else {
1276 width = image->width;
1279 XSetClipMask(dpy, copy_gc, None);
1280 if (wPreferences.new_style == TS_NEXT) {
1281 XSetForeground(dpy, copy_gc, scr->black_pixel);
1282 } else {
1283 XSetForeground(dpy, copy_gc, scr->white_pixel);
1285 d = 1;
1286 if (wPreferences.new_style == TS_NEW) {
1287 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1288 XSetForeground(dpy, copy_gc, scr->black_pixel);
1289 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1290 } else if (wPreferences.new_style == TS_OLD) {
1291 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1292 XSetForeground(dpy, copy_gc, scr->black_pixel);
1293 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1294 } else {
1295 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1296 XSetForeground(dpy, copy_gc, scr->black_pixel);
1297 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width-3, button->height-3);
1299 } else {
1300 XClearWindow(dpy, button->window);
1302 if (image) {
1303 if (image->width >= image->height * 2)
1304 width = image->width / 2;
1305 else
1306 width = image->width;
1308 d = 0;
1310 if (wPreferences.new_style == TS_NEW) {
1311 if (texture->any.type == WTEX_SOLID || pushed) {
1312 wDrawBevel(button->window, button->width, button->height,
1313 (WTexSolid *) texture, WREL_RAISED);
1315 } else {
1316 wDrawBevel(button->window, button->width, button->height,
1317 scr->widget_texture, WREL_RAISED);
1321 if (image) {
1322 /* display image */
1323 XSetClipMask(dpy, copy_gc, image->mask);
1324 x = (button->width - width) / 2 + d;
1325 y = (button->height - image->height) / 2 + d;
1326 XSetClipOrigin(dpy, copy_gc, x - left, y);
1327 if (!wPreferences.new_style == TS_NEW) {
1328 XSetForeground(dpy, copy_gc, scr->black_pixel);
1329 if (!pushed) {
1330 if (image->depth == 1)
1331 XCopyPlane(dpy, image->image, button->window, copy_gc,
1332 left, 0, width, image->height, x, y, 1);
1333 else
1334 XCopyArea(dpy, image->image, button->window, copy_gc,
1335 left, 0, width, image->height, x, y);
1336 } else {
1337 if (wPreferences.new_style == TS_OLD) {
1338 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1339 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1340 button->width, button->height);
1341 } else {
1342 XSetForeground(dpy, copy_gc, scr->black_pixel);
1343 XCopyArea(dpy, image->image, button->window, copy_gc,
1344 left, 0, width, image->height, x, y);
1347 } else {
1348 if (pushed) {
1349 XSetForeground(dpy, copy_gc, scr->black_pixel);
1350 } else {
1351 XSetForeground(dpy, copy_gc, color);
1352 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1354 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1359 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
1361 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1362 WCoreWindow *button = (WCoreWindow *) desc->self;
1364 #ifdef XKB_BUTTON_HINT
1365 if (button == fwin->language_button) {
1366 if (wPreferences.modelock) {
1367 paintButton(button, fwin->title_texture[fwin->flags.state],
1368 WMColorPixel(fwin->title_color[fwin->flags.state]),
1369 fwin->languagebutton_image, False);
1371 } else
1372 #endif
1373 if (button == fwin->left_button) {
1374 paintButton(button, fwin->title_texture[fwin->flags.state],
1375 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
1376 } else {
1377 paintButton(button, fwin->title_texture[fwin->flags.state],
1378 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
1382 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
1384 WFrameWindow *fwin = desc->parent;
1385 WCoreWindow *titlebar = desc->self;
1387 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1388 if (fwin->on_dblclick_titlebar) {
1389 (*fwin->on_dblclick_titlebar) (titlebar, fwin->child, event);
1391 } else {
1392 if (fwin->on_mousedown_titlebar) {
1393 (*fwin->on_mousedown_titlebar) (titlebar, fwin->child, event);
1398 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event)
1400 WFrameWindow *fwin = desc->parent;
1401 WCoreWindow *resizebar = desc->self;
1403 if (fwin->on_mousedown_resizebar)
1404 (*fwin->on_mousedown_resizebar) (resizebar, fwin->child, event);
1407 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
1409 WFrameWindow *fwin = desc->parent;
1410 WCoreWindow *button = desc->self;
1411 WPixmap *image;
1412 XEvent ev;
1413 int done = 0, execute = 1;
1414 WTexture *texture;
1415 unsigned long pixel;
1416 int clickButton = event->xbutton.button;
1418 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1419 if (button == fwin->right_button && fwin->on_dblclick_right) {
1420 (*fwin->on_dblclick_right) (button, fwin->child, event);
1422 return;
1425 if (button == fwin->left_button) {
1426 image = fwin->lbutton_image;
1427 } else {
1428 image = fwin->rbutton_image;
1430 #ifdef XKB_BUTTON_HINT
1431 if (button == fwin->language_button) {
1432 if (!wPreferences.modelock)
1433 return;
1434 image = fwin->languagebutton_image;
1436 #endif
1438 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1439 texture = fwin->title_texture[fwin->flags.state];
1440 paintButton(button, texture, pixel, image, True);
1442 while (!done) {
1443 WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
1444 | ButtonPressMask | ExposureMask, &ev);
1445 switch (ev.type) {
1446 case LeaveNotify:
1447 execute = 0;
1448 paintButton(button, texture, pixel, image, False);
1449 break;
1451 case EnterNotify:
1452 execute = 1;
1453 paintButton(button, texture, pixel, image, True);
1454 break;
1456 case ButtonPress:
1457 break;
1459 case ButtonRelease:
1460 if (ev.xbutton.button == clickButton)
1461 done = 1;
1462 break;
1464 default:
1465 WMHandleEvent(&ev);
1468 paintButton(button, texture, pixel, image, False);
1470 if (execute) {
1471 if (button == fwin->left_button) {
1472 if (fwin->on_click_left)
1473 (*fwin->on_click_left) (button, fwin->child, &ev);
1474 } else if (button == fwin->right_button) {
1475 if (fwin->on_click_right)
1476 (*fwin->on_click_right) (button, fwin->child, &ev);
1478 #ifdef XKB_BUTTON_HINT
1479 else if (button == fwin->language_button) {
1480 if (fwin->on_click_language)
1481 (*fwin->on_click_language) (button, fwin->child, &ev);
1483 #endif