change Clearance to ExtendSpace. Also add ExtendSpace option for menu
[wmaker-crm.git] / src / framewin.c
blob7d9d0a8d0d821f1bc184a1db6a3977cb583b3141
1 /*
2 * Window Maker window manager
3 *
4 * Copyright (c) 1997, 1998 Alfredo K. Kojima
5 *
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
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19 * USA.
22 #include "wconfig.h"
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 #ifdef KEEP_XKB_LOCK_STATUS
27 #include <X11/XKBlib.h>
28 #endif /* KEEP_XKB_LOCK_STATUS */
30 #include <stdlib.h>
31 #include <string.h>
33 #include <wraster.h>
35 #include "WindowMaker.h"
36 #include "GNUstep.h"
37 #include "texture.h"
38 #include "screen.h"
39 #include "wcore.h"
40 #include "framewin.h"
41 #include "stacking.h"
42 #include "funcs.h"
44 #define DBLCLICK_TIME wPreferences.dblclick_time
46 extern WPreferences wPreferences;
48 static void handleExpose(WObjDescriptor *desc, XEvent *event);
49 static void handleButtonExpose(WObjDescriptor *desc, XEvent *event);
51 static void buttonMouseDown(WObjDescriptor *desc, XEvent *event);
52 static void titlebarMouseDown(WObjDescriptor *desc, XEvent *event);
53 static void resizebarMouseDown(WObjDescriptor *desc, XEvent *event);
55 static void checkTitleSize(WFrameWindow *fwin);
58 static void paintButton(WCoreWindow *button, WTexture *texture,
59 unsigned long color, WPixmap *image, int pushed);
61 static void updateTitlebar(WFrameWindow *fwin);
64 WFrameWindow*
65 wFrameWindowCreate(WScreen *scr, int wlevel, int x, int y,
66 int width, int height, int *clearance, int flags,
67 WTexture **title_texture, WTexture **resize_texture,
68 unsigned long *color,
69 #ifdef DRAWSTRING_PLUGIN
70 int function_offset,
71 #endif
72 GC *gc, WMFont **font)
74 WFrameWindow *fwin;
76 fwin = wmalloc(sizeof(WFrameWindow));
77 memset(fwin, 0, sizeof(WFrameWindow));
79 fwin->screen_ptr = scr;
81 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
83 fwin->title_texture = title_texture;
84 fwin->resizebar_texture = resize_texture;
85 fwin->title_pixel = color;
86 fwin->title_clearance = clearance;
87 #ifdef DRAWSTRING_PLUGIN
88 fwin->drawstring_proc_offset = function_offset;
89 #endif
90 fwin->title_gc = gc;
91 fwin->font = font;
92 #ifdef KEEP_XKB_LOCK_STATUS
93 fwin->languagemode = XkbGroup1Index;
94 fwin->last_languagemode = XkbGroup2Index;
95 #endif
97 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height,
98 FRAME_BORDER_WIDTH);
99 if (wPreferences.use_saveunders) {
100 unsigned long vmask;
101 XSetWindowAttributes attribs;
103 vmask = CWSaveUnder;
104 attribs.save_under = True;
105 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
108 /* setup stacking information */
109 fwin->core->stacking = wmalloc(sizeof(WStacking));
110 fwin->core->stacking->above = NULL;
111 fwin->core->stacking->under = NULL;
112 fwin->core->stacking->child_of = NULL;
113 fwin->core->stacking->window_level = wlevel;
115 AddToStackList(fwin->core);
117 wFrameWindowUpdateBorders(fwin, flags);
119 return fwin;
124 void
125 wFrameWindowUpdateBorders(WFrameWindow *fwin, int flags)
127 int theight;
128 int bsize;
129 int width, height;
130 int i;
131 WScreen *scr = fwin->screen_ptr;
133 width = fwin->core->width;
134 if (flags & WFF_IS_SHADED)
135 height = -1;
136 else
137 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
139 if (flags & WFF_TITLEBAR)
140 theight = WMFontHeight(*fwin->font) + TITLEBAR_EXTRA_HEIGHT + *fwin->title_clearance * 2;
141 else
142 theight = 0;
144 if (wPreferences.new_style) {
145 bsize = theight;
146 } else {
147 bsize = theight - 7;
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) {
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);
170 #endif
173 if (fwin->right_button) {
174 wCoreConfigure(fwin->right_button, width-bsize+1,
175 0, bsize, bsize);
177 } else { /* !new_style */
178 if (fwin->left_button) {
179 wCoreConfigure(fwin->left_button, 3, (theight-bsize)/2,
180 bsize, bsize);
183 #ifdef XKB_BUTTON_HINT
184 if (fwin->language_button) {
185 wCoreConfigure(fwin->language_button, 6 + bsize, (theight-bsize)/2,
186 bsize, bsize);
189 #endif
191 if (fwin->right_button) {
192 wCoreConfigure(fwin->right_button, width-bsize-3,
193 (theight-bsize)/2, bsize, bsize);
196 updateTitlebar(fwin);
197 } else {
198 /* we had a titlebar, but now we don't need it anymore */
199 for (i=0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
200 FREE_PIXMAP(fwin->title_back[i]);
201 if (wPreferences.new_style) {
202 FREE_PIXMAP(fwin->lbutton_back[i]);
203 FREE_PIXMAP(fwin->rbutton_back[i]);
204 #ifdef XKB_BUTTON_HINT
205 FREE_PIXMAP(fwin->languagebutton_back[i]);
206 #endif
209 if (fwin->left_button)
210 wCoreDestroy(fwin->left_button);
211 fwin->left_button = NULL;
213 #ifdef XKB_BUTTON_HINT
214 if (fwin->language_button)
215 wCoreDestroy(fwin->language_button);
216 fwin->language_button = NULL;
217 #endif
219 if (fwin->right_button)
220 wCoreDestroy(fwin->right_button);
221 fwin->right_button = NULL;
223 wCoreDestroy(fwin->titlebar);
224 fwin->titlebar = NULL;
226 fwin->top_width = 0;
228 } else {
229 /* if we didn't have a titlebar and are being requested for
230 * one, create it */
231 if (flags & WFF_TITLEBAR) {
232 fwin->top_width = theight;
234 fwin->flags.titlebar = 1;
235 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width+1, theight);
237 if (flags & WFF_LEFT_BUTTON) {
238 fwin->flags.left_button = 1;
239 if (wPreferences.new_style) {
240 fwin->left_button = wCoreCreate(fwin->core, 0, 0,
241 bsize, bsize);
242 if (width < theight*4) {
243 fwin->flags.lbutton_dont_fit = 1;
244 } else {
245 XMapRaised(dpy, fwin->left_button->window);
247 } else {
248 fwin->left_button =
249 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
250 bsize, bsize);
252 XSetWindowBackground(dpy, fwin->left_button->window,
253 scr->widget_texture->normal.pixel);
255 if (width < theight*3) {
256 fwin->flags.lbutton_dont_fit = 1;
257 } else {
258 XMapRaised(dpy, fwin->left_button->window);
263 #ifdef XKB_BUTTON_HINT
264 if (flags & WFF_LANGUAGE_BUTTON) {
265 fwin->flags.language_button = 1;
266 if (wPreferences.new_style) {
267 fwin->language_button = wCoreCreate(fwin->core,
268 bsize, 0, bsize, bsize);
270 if (width < theight*4) {
271 fwin->flags.languagebutton_dont_fit = 1;
272 } else {
273 XMapRaised(dpy, fwin->language_button->window);
275 } else {
276 fwin->language_button =
277 wCoreCreate(fwin->titlebar, bsize + 6, (theight-bsize)/2,
278 bsize, bsize);
280 XSetWindowBackground(dpy, fwin->language_button->window,
281 scr->widget_texture->normal.pixel);
283 if (width < theight*3) {
284 fwin->flags.languagebutton_dont_fit = 1;
285 } else {
286 XMapRaised(dpy, fwin->language_button->window);
290 #endif
292 if (flags & WFF_RIGHT_BUTTON) {
293 fwin->flags.right_button = 1;
294 if (wPreferences.new_style) {
295 fwin->right_button =
296 wCoreCreate(fwin->core, width-bsize+1, 0,
297 bsize, bsize);
298 } else {
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);
306 if (width < theight*2) {
307 fwin->flags.rbutton_dont_fit = 1;
308 } else {
309 XMapRaised(dpy, fwin->right_button->window);
313 if (wPreferences.new_style)
314 updateTitlebar(fwin);
316 XMapRaised(dpy, fwin->titlebar->window);
318 fwin->flags.need_texture_remake = 1;
321 checkTitleSize(fwin);
323 if (flags & WFF_RESIZEBAR) {
324 fwin->bottom_width = RESIZEBAR_HEIGHT;
325 } else {
326 fwin->bottom_width = 0;
329 if (flags & WFF_RESIZEBAR) {
330 if (!fwin->resizebar) {
331 fwin->flags.resizebar = 1;
332 fwin->resizebar = wCoreCreate(fwin->core, 0,
333 height + fwin->top_width,
334 width, RESIZEBAR_HEIGHT);
335 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
336 if (width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
337 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH)/2;
338 if (fwin->resizebar_corner_width < 0)
339 fwin->resizebar_corner_width = 0;
342 XMapWindow(dpy, fwin->resizebar->window);
343 XLowerWindow(dpy, fwin->resizebar->window);
345 fwin->flags.need_texture_remake = 1;
346 } else {
347 if (height+fwin->top_width+fwin->bottom_width != fwin->core->height) {
348 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
349 width, RESIZEBAR_HEIGHT);
352 } else {
353 if (fwin->resizebar) {
354 fwin->bottom_width = 0;
355 wCoreDestroy(fwin->resizebar);
356 fwin->resizebar = NULL;
360 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height
361 && !(flags & WFF_IS_SHADED)) {
362 wFrameWindowResize(fwin, width,
363 height + fwin->top_width + fwin->bottom_width);
366 /* setup object descriptors */
368 if (fwin->titlebar) {
369 fwin->titlebar->descriptor.handle_expose = handleExpose;
370 fwin->titlebar->descriptor.parent = fwin;
371 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
372 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
375 if (fwin->resizebar) {
376 fwin->resizebar->descriptor.handle_expose = handleExpose;
377 fwin->resizebar->descriptor.parent = fwin;
378 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
379 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
382 if (fwin->left_button) {
383 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
384 fwin->left_button->descriptor.parent = fwin;
385 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
386 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
389 #ifdef XKB_BUTTON_HINT
390 if (fwin->language_button) {
391 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
392 fwin->language_button->descriptor.parent = fwin;
393 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
394 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
396 #endif
399 if (fwin->right_button) {
400 fwin->right_button->descriptor.parent = fwin;
401 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
402 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
403 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
406 checkTitleSize(fwin);
411 void
412 wFrameWindowDestroy(WFrameWindow *fwin)
414 int i;
416 if (fwin->left_button)
417 wCoreDestroy(fwin->left_button);
419 #ifdef XKB_BUTTON_HINT
420 if (fwin->language_button)
421 wCoreDestroy(fwin->language_button);
422 #endif
424 if (fwin->right_button)
425 wCoreDestroy(fwin->right_button);
427 if (fwin->resizebar)
428 wCoreDestroy(fwin->resizebar);
430 if (fwin->titlebar)
431 wCoreDestroy(fwin->titlebar);
433 RemoveFromStackList(fwin->core);
435 wCoreDestroy(fwin->core);
437 if (fwin->title)
438 free(fwin->title);
440 for (i=0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
441 FREE_PIXMAP(fwin->title_back[i]);
442 if (wPreferences.new_style) {
443 FREE_PIXMAP(fwin->lbutton_back[i]);
444 #ifdef XKB_BUTTON_HINT
445 FREE_PIXMAP(fwin->languagebutton_back[i]);
446 #endif
447 FREE_PIXMAP(fwin->rbutton_back[i]);
451 free(fwin);
455 void
456 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);
468 static void
469 updateTitlebar(WFrameWindow *fwin)
471 int x, w;
472 int theight;
474 theight = WMFontHeight(*fwin->font) + TITLEBAR_EXTRA_HEIGHT + *fwin->title_clearance * 2;
476 x = 0;
477 w = fwin->core->width + 1;
479 if (wPreferences.new_style) {
480 if (fwin->flags.hide_left_button || !fwin->left_button
481 || fwin->flags.lbutton_dont_fit) {
482 x = 0;
483 #ifdef XKB_BUTTON_HINT
484 if(fwin->language_button)
485 wCoreConfigure(fwin->language_button, 0, 0,
486 fwin->language_button->width,
487 fwin->language_button->width);
488 #endif
489 } else {
490 #ifdef XKB_BUTTON_HINT
491 if(fwin->language_button)
492 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
493 fwin->language_button->width,
494 fwin->language_button->width);
495 #endif
496 x = fwin->left_button->width;
497 w -= fwin->left_button->width;
499 #ifdef XKB_BUTTON_HINT
500 if (fwin->flags.hide_language_button || !fwin->language_button
501 || fwin->flags.languagebutton_dont_fit) {
502 } else {
503 x += fwin->language_button->width;
504 w -= fwin->language_button->width;
506 #endif
508 #ifdef XKB_BUTTON_HINT
509 else {
510 int bsize = theight - 7;
511 if (fwin->flags.hide_left_button || !fwin->left_button
512 || fwin->flags.lbutton_dont_fit) {
513 if(fwin->language_button)
514 wCoreConfigure(fwin->language_button, 3, (theight-bsize)/2,
515 fwin->language_button->width,
516 fwin->language_button->width);
518 else {
519 if(fwin->language_button)
520 wCoreConfigure(fwin->language_button,
521 6 + fwin->left_button->width, (theight-bsize)/2,
522 fwin->language_button->width,
523 fwin->language_button->width);
526 #endif
528 if (wPreferences.new_style) {
529 if (!fwin->flags.hide_right_button && fwin->right_button
530 && !fwin->flags.rbutton_dont_fit) {
531 w -= fwin->right_button->width;
535 if (wPreferences.new_style || fwin->titlebar->width!=w)
536 fwin->flags.need_texture_remake = 1;
538 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
542 void
543 wFrameWindowHideButton(WFrameWindow *fwin, int flags)
545 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
546 XUnmapWindow(dpy, fwin->right_button->window);
547 fwin->flags.hide_right_button = 1;
550 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
551 XUnmapWindow(dpy, fwin->left_button->window);
552 fwin->flags.hide_left_button = 1;
555 #ifdef XKB_BUTTON_HINT
556 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
557 XUnmapWindow(dpy, fwin->language_button->window);
558 fwin->flags.hide_language_button = 1;
560 #endif
562 if (fwin->titlebar) {
563 if (wPreferences.new_style) {
564 updateTitlebar(fwin);
565 } else {
566 #ifdef XKB_BUTTON_HINT
567 updateTitlebar(fwin);
568 #else
569 XClearWindow(dpy, fwin->titlebar->window);
570 wFrameWindowPaint(fwin);
571 #endif
573 checkTitleSize(fwin);
578 void
579 wFrameWindowShowButton(WFrameWindow *fwin, int flags)
581 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button
582 && fwin->flags.hide_right_button) {
584 if (!fwin->flags.rbutton_dont_fit)
585 XMapWindow(dpy, fwin->right_button->window);
587 fwin->flags.hide_right_button = 0;
590 #ifdef XKB_BUTTON_HINT
591 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button
592 && fwin->flags.hide_language_button) {
594 if (!fwin->flags.languagebutton_dont_fit)
595 XMapWindow(dpy, fwin->language_button->window);
597 fwin->flags.hide_language_button = 0;
599 #endif
601 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button
602 && fwin->flags.hide_left_button) {
604 if (!fwin->flags.lbutton_dont_fit)
605 XMapWindow(dpy, fwin->left_button->window);
607 fwin->flags.hide_left_button = 0;
611 if (fwin->titlebar) {
612 if (wPreferences.new_style) {
613 updateTitlebar(fwin);
614 } else {
615 XClearWindow(dpy, fwin->titlebar->window);
616 wFrameWindowPaint(fwin);
618 checkTitleSize(fwin);
623 static void
624 #ifdef XKB_BUTTON_HINT
625 renderTexture(WScreen *scr, WTexture *texture, int width, int height,
626 int bwidth, int bheight, int left, int language, int right,
627 Pixmap *title, Pixmap *lbutton, Pixmap *languagebutton, Pixmap *rbutton)
628 #else
629 renderTexture(WScreen *scr, WTexture *texture, int width, int height,
630 int bwidth, int bheight, int left, int right,
631 Pixmap *title, Pixmap *lbutton, Pixmap *rbutton)
632 #endif
634 RImage *img;
635 RImage *limg, *rimg, *mimg;
636 #ifdef XKB_BUTTON_HINT
637 RImage *timg;
638 #endif
639 int x, w;
641 *title = None;
642 *lbutton = None;
643 *rbutton = None;
644 #ifdef XKB_BUTTON_HINT
645 *languagebutton = None;
646 #endif
648 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
649 if (!img) {
650 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
651 return;
654 if (wPreferences.new_style) {
655 if (left) {
656 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
657 } else
658 limg = NULL;
660 x = 0;
661 w = img->width;
663 #ifdef XKB_BUTTON_HINT
664 if (language) {
665 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
666 } else
667 timg = NULL;
668 #endif
670 if (limg) {
671 RBevelImage(limg, RBEV_RAISED2);
672 if (!RConvertImage(scr->rcontext, limg, lbutton)) {
673 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
675 x += limg->width;
676 w -= limg->width;
677 RDestroyImage(limg);
680 #ifdef XKB_BUTTON_HINT
681 if (timg) {
682 RBevelImage(timg, RBEV_RAISED2);
683 if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
684 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
686 x += timg->width;
687 w -= timg->width;
688 RDestroyImage(timg);
690 #endif
692 if (right) {
693 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
694 } else
695 rimg = NULL;
697 if (rimg) {
698 RBevelImage(rimg, RBEV_RAISED2);
699 if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
700 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
702 w -= rimg->width;
703 RDestroyImage(rimg);
706 if (w!=width) {
707 mimg = RGetSubImage(img, x, 0, w, img->height);
708 RBevelImage(mimg, RBEV_RAISED2);
710 if (!RConvertImage(scr->rcontext, mimg, title)) {
711 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
713 RDestroyImage(mimg);
714 } else {
715 RBevelImage(img, RBEV_RAISED2);
717 if (!RConvertImage(scr->rcontext, img, title)) {
718 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
721 } else {
722 RBevelImage(img, RBEV_RAISED2);
724 if (!RConvertImage(scr->rcontext, img, title)) {
725 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
729 RDestroyImage(img);
733 static void
734 renderResizebarTexture(WScreen *scr, WTexture *texture, int width, int height,
735 int cwidth, Pixmap *pmap)
737 RImage *img;
738 RColor light;
739 RColor dark;
741 *pmap = None;
743 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
744 if (!img) {
745 wwarning(_("could not render texture: %s"),
746 RMessageForError(RErrorCode));
747 return;
750 light.alpha = 0;
751 light.red = light.green = light.blue = 80;
753 dark.alpha = 0;
754 dark.red = dark.green = dark.blue = 40;
756 ROperateLine(img, RSubtractOperation, 0, 0, width-1, 0, &dark);
757 ROperateLine(img, RAddOperation, 0, 1, width-1, 1, &light);
759 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height-1, &dark);
760 ROperateLine(img, RAddOperation, cwidth+1, 2, cwidth+1, height-1, &light);
762 if (width > 1)
763 ROperateLine(img, RSubtractOperation, width-cwidth-2, 2,
764 width-cwidth-2, height-1, &dark);
765 ROperateLine(img, RAddOperation, width-cwidth-1, 2, width-cwidth-1,
766 height-1, &light);
768 #ifdef SHADOW_RESIZEBAR
769 ROperateLine(img, RAddOperation, 0, 1, 0, height-1, &light);
770 ROperateLine(img, RSubtractOperation, width-1, 1, width-1, height-1,
771 &dark);
772 ROperateLine(img, RSubtractOperation, 0, height-1, width-1, height-1,
773 &dark);
774 #endif /* SHADOW_RESIZEBAR */
777 if (!RConvertImage(scr->rcontext, img, pmap)) {
778 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
781 RDestroyImage(img);
786 static void
787 updateTexture(WFrameWindow *fwin)
789 int i;
790 unsigned long pixel;
792 i = fwin->flags.state;
793 if (fwin->titlebar) {
794 if (fwin->title_texture[i]->any.type!=WTEX_SOLID) {
795 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window,
796 fwin->title_back[i]);
797 if (wPreferences.new_style) {
798 if (fwin->left_button && fwin->lbutton_back[i])
799 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
800 fwin->lbutton_back[i]);
802 #ifdef XKB_BUTTON_HINT
803 if (fwin->language_button && fwin->languagebutton_back[i]) {
804 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
805 fwin->languagebutton_back[i]);
807 #endif
809 if (fwin->right_button && fwin->rbutton_back[i])
810 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
811 fwin->rbutton_back[i]);
813 } else {
814 pixel = fwin->title_texture[i]->solid.normal.pixel;
815 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
816 if (wPreferences.new_style) {
817 if (fwin->left_button)
818 XSetWindowBackground(dpy, fwin->left_button->window,
819 pixel);
820 #ifdef XKB_BUTTON_HINT
821 if (fwin->language_button)
822 XSetWindowBackground(dpy, fwin->language_button->window,
823 pixel);
824 #endif
825 if (fwin->right_button)
826 XSetWindowBackground(dpy, fwin->right_button->window,
827 pixel);
830 XClearWindow(dpy, fwin->titlebar->window);
832 if (fwin->left_button) {
833 XClearWindow(dpy, fwin->left_button->window);
834 handleButtonExpose(&fwin->left_button->descriptor, NULL);
836 #ifdef XKB_BUTTON_HINT
837 if (fwin->language_button) {
838 XClearWindow(dpy, fwin->language_button->window);
839 handleButtonExpose(&fwin->language_button->descriptor, NULL);
841 #endif
842 if (fwin->right_button) {
843 XClearWindow(dpy, fwin->right_button->window);
844 handleButtonExpose(&fwin->right_button->descriptor, NULL);
851 static void
852 remakeTexture(WFrameWindow *fwin, int state)
854 Pixmap pmap, lpmap, rpmap;
855 #ifdef XKB_BUTTON_HINT
856 Pixmap tpmap;
857 #endif
859 if (fwin->title_texture[state] && fwin->titlebar) {
860 FREE_PIXMAP(fwin->title_back[state]);
861 if (wPreferences.new_style) {
862 FREE_PIXMAP(fwin->lbutton_back[state]);
863 FREE_PIXMAP(fwin->rbutton_back[state]);
864 #ifdef XKB_BUTTON_HINT
865 FREE_PIXMAP(fwin->languagebutton_back[state]);
866 #endif
869 if (fwin->title_texture[state]->any.type!=WTEX_SOLID) {
870 int left, right;
871 #ifdef XKB_BUTTON_HINT
872 int language;
873 #endif
874 int width;
876 /* eventually surrounded by if new_style */
877 left = fwin->left_button && !fwin->flags.hide_left_button
878 && !fwin->flags.lbutton_dont_fit;
879 #ifdef XKB_BUTTON_HINT
880 language = fwin->language_button && !fwin->flags.hide_language_button
881 && !fwin->flags.languagebutton_dont_fit;
882 #endif
883 right = fwin->right_button && !fwin->flags.hide_right_button
884 && !fwin->flags.rbutton_dont_fit;
886 width = fwin->core->width+1;
888 #ifdef XKB_BUTTON_HINT
889 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
890 width, fwin->titlebar->height,
891 fwin->titlebar->height, fwin->titlebar->height,
892 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
893 #else
894 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
895 width, fwin->titlebar->height,
896 fwin->titlebar->height, fwin->titlebar->height,
897 left, right, &pmap, &lpmap, &rpmap);
898 #endif
900 fwin->title_back[state] = pmap;
901 if (wPreferences.new_style) {
902 fwin->lbutton_back[state] = lpmap;
903 fwin->rbutton_back[state] = rpmap;
904 #ifdef XKB_BUTTON_HINT
905 fwin->languagebutton_back[state] = tpmap;
906 #endif
910 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
911 && fwin->resizebar && state == 0) {
913 FREE_PIXMAP(fwin->resizebar_back[0]);
915 if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
917 renderResizebarTexture(fwin->screen_ptr,
918 fwin->resizebar_texture[0],
919 fwin->resizebar->width,
920 fwin->resizebar->height,
921 fwin->resizebar_corner_width,
922 &pmap);
924 fwin->resizebar_back[0] = pmap;
927 /* this part should be in updateTexture() */
928 if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
929 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window,
930 fwin->resizebar_back[0]);
931 } else {
932 XSetWindowBackground(dpy, fwin->resizebar->window,
933 fwin->resizebar_texture[0]->solid.normal.pixel);
935 XClearWindow(dpy, fwin->resizebar->window);
940 void
941 wFrameWindowPaint(WFrameWindow *fwin)
943 WScreen *scr = fwin->screen_ptr;
945 if (fwin->flags.is_client_window_frame)
946 fwin->flags.justification = wPreferences.title_justification;
948 if (fwin->flags.need_texture_remake) {
949 int i;
951 fwin->flags.need_texture_remake = 0;
952 fwin->flags.need_texture_change = 0;
954 if (fwin->flags.single_texture) {
955 remakeTexture(fwin, 0);
956 updateTexture(fwin);
957 } else {
958 /* first render the texture for the current state... */
959 remakeTexture(fwin, fwin->flags.state);
960 /* ... and paint it */
961 updateTexture(fwin);
963 for (i=0; i < 3; i++) {
964 if (i!=fwin->flags.state)
965 remakeTexture(fwin, i);
970 if (fwin->flags.need_texture_change) {
971 fwin->flags.need_texture_change = 0;
973 updateTexture(fwin);
976 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
977 && fwin->title_texture[fwin->flags.state]->any.type==WTEX_SOLID) {
978 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
979 fwin->titlebar->height,
980 (WTexSolid*)fwin->title_texture[fwin->flags.state],
981 WREL_RAISED);
984 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
985 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
986 Window win;
987 int w, h;
988 int cw;
989 GC light_gc, dim_gc;
990 WTexSolid *texture = (WTexSolid*)fwin->resizebar_texture[0];
992 w = fwin->resizebar->width;
993 h = fwin->resizebar->height;
994 cw = fwin->resizebar_corner_width;
995 light_gc = texture->light_gc;
996 dim_gc = texture->dim_gc;
997 win = fwin->resizebar->window;
999 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
1000 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
1002 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
1003 XDrawLine(dpy, win, light_gc, cw+1, 2, cw+1, h);
1005 XDrawLine(dpy, win, dim_gc, w-cw-2, 2, w-cw-2, h);
1006 XDrawLine(dpy, win, light_gc, w-cw-1, 2, w-cw-1, h);
1008 #ifdef SHADOW_RESIZEBAR
1009 XDrawLine(dpy, win, light_gc, 0, 1, 0, h-1);
1010 XDrawLine(dpy, win, dim_gc, w-1, 2, w-1, h-1);
1011 XDrawLine(dpy, win, dim_gc, 1, h-1, cw, h-1);
1012 XDrawLine(dpy, win, dim_gc, cw+2, h-1, w-cw-2, h-1);
1013 XDrawLine(dpy, win, dim_gc, w-cw, h-1, w-1, h-1);
1014 #endif /* SHADOW_RESIZEBAR */
1018 if (fwin->title && fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
1019 int x, w;
1020 int lofs = 6, rofs = 6;
1021 int titlelen;
1022 char *title;
1023 int allButtons = 1;
1026 if (!wPreferences.new_style) {
1027 if (fwin->left_button && !fwin->flags.hide_left_button
1028 && !fwin->flags.lbutton_dont_fit)
1029 lofs += fwin->left_button->width + 3;
1030 else
1031 allButtons = 0;
1033 #ifdef XKB_BUTTON_HINT
1034 if (fwin->language_button && !fwin->flags.hide_language_button
1035 && !fwin->flags.languagebutton_dont_fit)
1036 lofs += fwin->language_button->width;
1037 else
1038 allButtons = 0;
1039 #endif
1041 if (fwin->right_button && !fwin->flags.hide_right_button
1042 && !fwin->flags.rbutton_dont_fit)
1043 rofs += fwin->right_button->width + 3;
1044 else
1045 allButtons = 0;
1048 #ifdef XKB_BUTTON_HINT
1049 fwin->languagebutton_image =
1050 scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1051 #endif
1053 title = ShrinkString(*fwin->font, fwin->title,
1054 fwin->titlebar->width - lofs - rofs);
1055 titlelen = strlen(title);
1056 w = WMWidthOfString(*fwin->font, title, titlelen);
1058 switch (fwin->flags.justification) {
1059 case WTJ_LEFT:
1060 x = lofs;
1061 break;
1063 case WTJ_RIGHT:
1064 x = fwin->titlebar->width - w - rofs;
1065 break;
1067 default:
1068 if (!allButtons)
1069 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1070 else
1071 x = (fwin->titlebar->width - w) / 2;
1072 break;
1076 XSetForeground(dpy, *fwin->title_gc,
1077 fwin->title_pixel[fwin->flags.state]);
1079 #ifdef DRAWSTRING_PLUGIN
1080 if (scr->drawstring_func[fwin->flags.state + fwin->drawstring_proc_offset]) {
1081 scr->drawstring_func[fwin->flags.state + fwin->drawstring_proc_offset]->
1082 proc.drawString(scr->drawstring_func[fwin->flags.state
1083 + fwin->drawstring_proc_offset]->arg,
1084 fwin->titlebar->window, *fwin->title_gc,
1085 *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTRA_HEIGHT/2,
1086 fwin->titlebar->width, fwin->top_width, title, titlelen);
1087 } else {
1088 WMDrawString(scr->wmscreen, fwin->titlebar->window,
1089 *fwin->title_gc, *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTRA_HEIGHT/2,
1090 title, titlelen);
1092 #else
1093 WMDrawString(scr->wmscreen, fwin->titlebar->window,
1094 *fwin->title_gc, *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTRA_HEIGHT/2,
1095 title, titlelen);
1096 #endif /* DRAWSTRING_PLUGIN */
1098 free(title);
1100 if (fwin->left_button)
1101 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1102 if (fwin->right_button)
1103 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1104 #ifdef XKB_BUTTON_HINT
1105 if (fwin->language_button)
1106 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1107 #endif
1112 static void
1113 reconfigure(WFrameWindow *fwin, int x, int y, int width, int height,
1114 Bool dontMove)
1116 int k = (wPreferences.new_style ? 4 : 3);
1117 int resizedHorizontally = 0;
1119 if (dontMove)
1120 XResizeWindow(dpy, fwin->core->window, width, height);
1121 else
1122 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1125 if (fwin->core->height != height && fwin->resizebar)
1126 XMoveWindow(dpy, fwin->resizebar->window, 0,
1127 height - fwin->resizebar->height);
1129 if (fwin->core->width != width) {
1130 fwin->flags.need_texture_remake = 1;
1131 resizedHorizontally = 1;
1134 fwin->core->width = width;
1135 fwin->core->height = height;
1137 if (fwin->titlebar && resizedHorizontally) {
1138 /* Check if the titlebar is wide enough to hold the buttons.
1139 * Temporarily remove them if can't
1141 if (fwin->left_button) {
1142 if (width < fwin->top_width*k && !fwin->flags.lbutton_dont_fit) {
1144 if (!fwin->flags.hide_left_button) {
1145 XUnmapWindow(dpy, fwin->left_button->window);
1147 fwin->flags.lbutton_dont_fit = 1;
1148 } else if (width >= fwin->top_width*k && fwin->flags.lbutton_dont_fit) {
1150 if (!fwin->flags.hide_left_button) {
1151 XMapWindow(dpy, fwin->left_button->window);
1153 fwin->flags.lbutton_dont_fit = 0;
1157 #ifdef XKB_BUTTON_HINT
1158 if (fwin->language_button) {
1159 if (width < fwin->top_width*k && !fwin->flags.languagebutton_dont_fit) {
1161 if (!fwin->flags.hide_language_button) {
1162 XUnmapWindow(dpy, fwin->language_button->window);
1164 fwin->flags.languagebutton_dont_fit = 1;
1165 } else if (width >= fwin->top_width*k && fwin->flags.languagebutton_dont_fit) {
1167 if (!fwin->flags.hide_language_button) {
1168 XMapWindow(dpy, fwin->language_button->window);
1170 fwin->flags.languagebutton_dont_fit = 0;
1173 #endif
1175 if (fwin->right_button) {
1176 if (width < fwin->top_width*2 && !fwin->flags.rbutton_dont_fit) {
1178 if (!fwin->flags.hide_right_button) {
1179 XUnmapWindow(dpy, fwin->right_button->window);
1181 fwin->flags.rbutton_dont_fit = 1;
1182 } else if (width >= fwin->top_width*2 && fwin->flags.rbutton_dont_fit) {
1184 if (!fwin->flags.hide_right_button) {
1185 XMapWindow(dpy, fwin->right_button->window);
1187 fwin->flags.rbutton_dont_fit = 0;
1191 if (wPreferences.new_style) {
1192 if (fwin->right_button)
1193 XMoveWindow(dpy, fwin->right_button->window,
1194 width - fwin->right_button->width + 1, 0);
1195 } else {
1196 if (fwin->right_button)
1197 XMoveWindow(dpy, fwin->right_button->window,
1198 width - fwin->right_button->width - 3,
1199 (fwin->titlebar->height - fwin->right_button->height)/2);
1201 updateTitlebar(fwin);
1202 checkTitleSize(fwin);
1205 if (fwin->resizebar) {
1206 wCoreConfigure(fwin->resizebar, 0,
1207 fwin->core->height - fwin->resizebar->height,
1208 fwin->core->width, fwin->resizebar->height);
1210 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1211 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
1212 fwin->resizebar_corner_width = fwin->core->width/2;
1217 void
1218 wFrameWindowConfigure(WFrameWindow *fwin, int x, int y, int width, int height)
1220 reconfigure(fwin, x, y, width, height, False);
1223 void
1224 wFrameWindowResize(WFrameWindow *fwin, int width, int height)
1226 reconfigure(fwin, 0, 0, width, height, True);
1231 int
1232 wFrameWindowChangeTitle(WFrameWindow *fwin, char *new_title)
1234 /* check if the title is the same as before */
1235 if (fwin->title) {
1236 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1237 return 0;
1239 } else {
1240 if (!new_title)
1241 return 0;
1244 if (fwin->title)
1245 free(fwin->title);
1247 fwin->title = wstrdup(new_title);
1249 if (fwin->titlebar) {
1250 XClearWindow(dpy, fwin->titlebar->window);
1252 wFrameWindowPaint(fwin);
1254 checkTitleSize(fwin);
1256 return 1;
1260 #ifdef OLWM_HINTS
1261 void
1262 wFrameWindowUpdatePushButton(WFrameWindow *fwin, Bool pushed)
1264 fwin->flags.right_button_pushed_in = pushed;
1266 paintButton(fwin->right_button, fwin->title_texture[fwin->flags.state],
1267 fwin->title_pixel[fwin->flags.state],
1268 fwin->rbutton_image, pushed);
1270 #endif /* OLWM_HINTS */
1273 #ifdef XKB_BUTTON_HINT
1274 void
1275 wFrameWindowUpdateLanguageButton(WFrameWindow *fwin)
1277 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1278 fwin->title_pixel[fwin->flags.state],
1279 fwin->languagebutton_image, True);
1281 #endif /* XKB_BUTTON_HINT */
1284 /*********************************************************************/
1286 static void
1287 handleExpose(WObjDescriptor *desc, XEvent *event)
1289 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1292 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1293 fwin->flags.repaint_only_titlebar = 1;
1294 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1295 fwin->flags.repaint_only_resizebar = 1;
1296 wFrameWindowPaint(fwin);
1297 fwin->flags.repaint_only_titlebar = 0;
1298 fwin->flags.repaint_only_resizebar = 0;
1302 static void
1303 checkTitleSize(WFrameWindow *fwin)
1305 int width;
1307 if (!fwin->title) {
1308 fwin->flags.incomplete_title = 0;
1309 return;
1312 if (!fwin->titlebar) {
1313 fwin->flags.incomplete_title = 1;
1314 return;
1315 } else {
1316 width = fwin->titlebar->width - 6 - 6;
1319 if (!wPreferences.new_style) {
1320 if (fwin->left_button && !fwin->flags.hide_left_button
1321 && !fwin->flags.lbutton_dont_fit)
1322 width -= fwin->left_button->width + 3;
1324 #ifdef XKB_BUTTON_HINT
1325 if (fwin->language_button && !fwin->flags.hide_language_button
1326 && !fwin->flags.languagebutton_dont_fit)
1327 width -= fwin->language_button->width + 3;
1328 #endif
1330 if (fwin->right_button && !fwin->flags.hide_right_button
1331 && !fwin->flags.rbutton_dont_fit)
1332 width -= fwin->right_button->width + 3;
1334 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1335 fwin->flags.incomplete_title = 1;
1336 } else {
1337 fwin->flags.incomplete_title = 0;
1342 static void
1343 paintButton(WCoreWindow *button, WTexture *texture, unsigned long color,
1344 WPixmap *image, int pushed)
1346 WScreen *scr = button->screen_ptr;
1347 GC copy_gc = scr->copy_gc;
1348 int x=0, y=0, d=0;
1349 int left=0, width=0;
1351 /* setup stuff according to the state */
1352 if (pushed) {
1353 if (image) {
1354 if (image->width>=image->height*2) {
1355 /* the image contains 2 pictures: the second is for the
1356 * pushed state */
1357 width = image->width/2;
1358 left = image->width/2;
1359 } else {
1360 width = image->width;
1363 XSetClipMask(dpy, copy_gc, None);
1364 XSetForeground(dpy, copy_gc, scr->white_pixel);
1365 d=1;
1366 if (wPreferences.new_style) {
1367 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1368 button->width-1, button->height-1);
1369 XSetForeground(dpy, copy_gc, scr->black_pixel);
1370 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1371 button->width-1, button->height-1);
1372 } else {
1373 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1374 button->width, button->height);
1375 XSetForeground(dpy, copy_gc, scr->black_pixel);
1376 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1377 button->width, button->height);
1379 } else {
1380 XClearWindow(dpy, button->window);
1382 if (image) {
1383 if (image->width>=image->height*2)
1384 width = image->width/2;
1385 else
1386 width = image->width;
1388 d=0;
1390 if (wPreferences.new_style) {
1391 if (texture->any.type==WTEX_SOLID || pushed) {
1392 wDrawBevel(button->window, button->width, button->height,
1393 (WTexSolid*)texture, WREL_RAISED);
1395 } else {
1396 wDrawBevel(button->window, button->width, button->height,
1397 scr->widget_texture, WREL_RAISED);
1401 if (image) {
1402 /* display image */
1403 XSetClipMask(dpy, copy_gc, image->mask);
1404 x = (button->width - width)/2 + d;
1405 y = (button->height - image->height)/2 + d;
1406 XSetClipOrigin(dpy, copy_gc, x-left, y);
1407 if (!wPreferences.new_style) {
1408 XSetForeground(dpy, copy_gc, scr->black_pixel);
1409 if (!pushed) {
1410 if (image->depth==1)
1411 XCopyPlane(dpy, image->image, button->window, copy_gc,
1412 left, 0, width, image->height, x, y, 1);
1413 else
1414 XCopyArea(dpy, image->image, button->window, copy_gc,
1415 left, 0, width, image->height, x, y);
1416 } else {
1417 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1418 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1419 button->width, button->height);
1421 } else {
1422 if (pushed) {
1423 XSetForeground(dpy, copy_gc, scr->black_pixel);
1424 } else {
1425 XSetForeground(dpy, copy_gc, color);
1426 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1428 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1429 button->width, button->height);
1435 static void
1436 handleButtonExpose(WObjDescriptor *desc, XEvent *event)
1438 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1439 WCoreWindow *button = (WCoreWindow*)desc->self;
1441 #ifdef XKB_BUTTON_HINT
1442 if (button == fwin->language_button) {
1443 if (wPreferences.modelock){
1444 paintButton(button, fwin->title_texture[fwin->flags.state],
1445 fwin->title_pixel[fwin->flags.state],
1446 fwin->languagebutton_image, False);
1448 } else
1449 #endif
1450 if (button == fwin->left_button) {
1451 paintButton(button, fwin->title_texture[fwin->flags.state],
1452 fwin->title_pixel[fwin->flags.state],
1453 fwin->lbutton_image, False);
1454 } else {
1455 Bool pushed = False;
1457 #ifdef OLWM_HINTS
1458 if (fwin->flags.right_button_pushed_in)
1459 pushed = True;
1460 #endif
1461 /* emulate the olwm pushpin in the "out" state */
1462 paintButton(button, fwin->title_texture[fwin->flags.state],
1463 fwin->title_pixel[fwin->flags.state],
1464 fwin->rbutton_image, pushed);
1469 static void
1470 titlebarMouseDown(WObjDescriptor *desc, XEvent *event)
1472 WFrameWindow *fwin = desc->parent;
1473 WCoreWindow *titlebar = desc->self;
1475 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1476 if (fwin->on_dblclick_titlebar)
1477 (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event);
1478 } else {
1479 if (fwin->on_mousedown_titlebar)
1480 (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event);
1485 static void
1486 resizebarMouseDown(WObjDescriptor *desc, XEvent *event)
1488 WFrameWindow *fwin = desc->parent;
1489 WCoreWindow *resizebar = desc->self;
1491 if (fwin->on_mousedown_resizebar)
1492 (*fwin->on_mousedown_resizebar)(resizebar, fwin->child, event);
1496 static void
1497 buttonMouseDown(WObjDescriptor *desc, XEvent *event)
1499 WFrameWindow *fwin = desc->parent;
1500 WCoreWindow *button = desc->self;
1501 WPixmap *image;
1502 XEvent ev;
1503 int done=0, execute=1;
1504 WTexture *texture;
1505 unsigned long pixel;
1506 int clickButton = event->xbutton.button;
1508 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1509 if (button == fwin->right_button && fwin->on_dblclick_right) {
1510 (*fwin->on_dblclick_right)(button, fwin->child, event);
1512 return;
1515 if (button == fwin->left_button) {
1516 image = fwin->lbutton_image;
1517 } else {
1518 image = fwin->rbutton_image;
1520 #ifdef XKB_BUTTON_HINT
1521 if (button == fwin->language_button) {
1522 if (!wPreferences.modelock) return;
1523 image = fwin->languagebutton_image;
1525 #endif
1527 pixel = fwin->title_pixel[fwin->flags.state];
1528 texture = fwin->title_texture[fwin->flags.state];
1529 paintButton(button, texture, pixel, image, True);
1531 while (!done) {
1532 WMMaskEvent(dpy, LeaveWindowMask|EnterWindowMask|ButtonReleaseMask
1533 |ButtonPressMask|ExposureMask, &ev);
1534 switch (ev.type) {
1535 case LeaveNotify:
1536 execute = 0;
1537 paintButton(button, texture, pixel, image, False);
1538 break;
1540 case EnterNotify:
1541 execute = 1;
1542 paintButton(button, texture, pixel, image, True);
1543 break;
1545 case ButtonPress:
1546 break;
1548 case ButtonRelease:
1549 if (ev.xbutton.button == clickButton)
1550 done = 1;
1551 break;
1553 default:
1554 WMHandleEvent(&ev);
1557 paintButton(button, texture, pixel, image, False);
1559 if (execute) {
1560 if (button == fwin->left_button) {
1561 if (fwin->on_click_left)
1562 (*fwin->on_click_left)(button, fwin->child, &ev);
1563 } else if (button == fwin->right_button) {
1564 if (fwin->on_click_right)
1565 (*fwin->on_click_right)(button, fwin->child, &ev);
1567 #ifdef XKB_BUTTON_HINT
1568 else if (button == fwin->language_button) {
1569 if (fwin->on_click_language)
1570 (*fwin->on_click_language)(button, fwin->child, &ev);
1572 #endif