fix a small bug relate to modelock.
[wmaker-crm.git] / src / framewin.c
blobae48c44c46ca21c4de9b404f977e933e9a988659
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 flags,
67 WTexture **title_texture, WTexture **resize_texture,
68 unsigned long *color, GC *gc, WMFont **font)
70 WFrameWindow *fwin;
72 fwin = wmalloc(sizeof(WFrameWindow));
73 memset(fwin, 0, sizeof(WFrameWindow));
75 fwin->screen_ptr = scr;
77 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
79 fwin->title_texture = title_texture;
80 fwin->resizebar_texture = resize_texture;
81 fwin->title_pixel = color;
82 fwin->title_gc = gc;
83 fwin->font = font;
84 #ifdef KEEP_XKB_LOCK_STATUS
85 fwin->languagemode = XkbGroup1Index;
86 fwin->last_languagemode = XkbGroup2Index;
87 #endif
89 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height,
90 FRAME_BORDER_WIDTH);
91 if (wPreferences.use_saveunders) {
92 unsigned long vmask;
93 XSetWindowAttributes attribs;
95 vmask = CWSaveUnder;
96 attribs.save_under = True;
97 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
100 /* setup stacking information */
101 fwin->core->stacking = wmalloc(sizeof(WStacking));
102 fwin->core->stacking->above = NULL;
103 fwin->core->stacking->under = NULL;
104 fwin->core->stacking->child_of = NULL;
105 fwin->core->stacking->window_level = wlevel;
107 AddToStackList(fwin->core);
109 wFrameWindowUpdateBorders(fwin, flags);
111 return fwin;
116 void
117 wFrameWindowUpdateBorders(WFrameWindow *fwin, int flags)
119 int theight;
120 int bsize;
121 int width, height;
122 int i;
123 WScreen *scr = fwin->screen_ptr;
125 width = fwin->core->width;
126 if (flags & WFF_IS_SHADED)
127 height = -1;
128 else
129 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
131 if (flags & WFF_TITLEBAR)
132 theight = WMFontHeight(*fwin->font) + TITLEBAR_EXTRA_HEIGHT;
133 else
134 theight = 0;
136 if (wPreferences.new_style) {
137 bsize = theight;
138 } else {
139 bsize = theight - 7;
142 if (fwin->titlebar) {
143 /* if we had a titlebar and is requesting for one,
144 * check if the size has changed and resize it */
145 if (flags & WFF_TITLEBAR) {
146 fwin->top_width = theight;
148 fwin->flags.need_texture_remake = 1;
150 if (wPreferences.new_style) {
151 if (fwin->left_button) {
152 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
154 #ifdef XKB_BUTTON_HINT
155 if (fwin->language_button)
156 if (fwin->flags.hide_left_button || !fwin->left_button
157 || fwin->flags.lbutton_dont_fit) {
158 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
159 } else {
160 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
162 #endif
165 if (fwin->right_button) {
166 wCoreConfigure(fwin->right_button, width-bsize+1,
167 0, bsize, bsize);
169 } else { /* !new_style */
170 if (fwin->left_button) {
171 wCoreConfigure(fwin->left_button, 3, (theight-bsize)/2,
172 bsize, bsize);
175 #ifdef XKB_BUTTON_HINT
176 if (fwin->language_button) {
177 wCoreConfigure(fwin->language_button, 6 + bsize, (theight-bsize)/2,
178 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) {
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) {
232 fwin->left_button = wCoreCreate(fwin->core, 0, 0,
233 bsize, bsize);
234 if (width < theight*4) {
235 fwin->flags.lbutton_dont_fit = 1;
236 } else {
237 XMapRaised(dpy, fwin->left_button->window);
239 } else {
240 fwin->left_button =
241 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
242 bsize, bsize);
244 XSetWindowBackground(dpy, fwin->left_button->window,
245 scr->widget_texture->normal.pixel);
247 if (width < theight*3) {
248 fwin->flags.lbutton_dont_fit = 1;
249 } else {
250 XMapRaised(dpy, fwin->left_button->window);
255 #ifdef XKB_BUTTON_HINT
256 if (flags & WFF_LANGUAGE_BUTTON) {
257 fwin->flags.language_button = 1;
258 if (wPreferences.new_style) {
259 fwin->language_button = wCoreCreate(fwin->core,
260 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) {
287 fwin->right_button =
288 wCoreCreate(fwin->core, width-bsize+1, 0,
289 bsize, bsize);
290 } else {
291 fwin->right_button =
292 wCoreCreate(fwin->titlebar, width-bsize-3,
293 (theight-bsize)/2, bsize, bsize);
294 XSetWindowBackground(dpy, fwin->right_button->window,
295 scr->widget_texture->normal.pixel);
298 if (width < theight*2) {
299 fwin->flags.rbutton_dont_fit = 1;
300 } else {
301 XMapRaised(dpy, fwin->right_button->window);
305 if (wPreferences.new_style)
306 updateTitlebar(fwin);
308 XMapRaised(dpy, fwin->titlebar->window);
310 fwin->flags.need_texture_remake = 1;
313 checkTitleSize(fwin);
315 if (flags & WFF_RESIZEBAR) {
316 fwin->bottom_width = RESIZEBAR_HEIGHT;
317 } else {
318 fwin->bottom_width = 0;
321 if (flags & WFF_RESIZEBAR) {
322 if (!fwin->resizebar) {
323 fwin->flags.resizebar = 1;
324 fwin->resizebar = wCoreCreate(fwin->core, 0,
325 height + fwin->top_width,
326 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 if (fwin->resizebar) {
346 fwin->bottom_width = 0;
347 wCoreDestroy(fwin->resizebar);
348 fwin->resizebar = NULL;
352 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height
353 && !(flags & WFF_IS_SHADED)) {
354 wFrameWindowResize(fwin, width,
355 height + fwin->top_width + fwin->bottom_width);
358 /* setup object descriptors */
360 if (fwin->titlebar) {
361 fwin->titlebar->descriptor.handle_expose = handleExpose;
362 fwin->titlebar->descriptor.parent = fwin;
363 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
364 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
367 if (fwin->resizebar) {
368 fwin->resizebar->descriptor.handle_expose = handleExpose;
369 fwin->resizebar->descriptor.parent = fwin;
370 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
371 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
374 if (fwin->left_button) {
375 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
376 fwin->left_button->descriptor.parent = fwin;
377 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
378 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
381 #ifdef XKB_BUTTON_HINT
382 if (fwin->language_button) {
383 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
384 fwin->language_button->descriptor.parent = fwin;
385 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
386 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
388 #endif
391 if (fwin->right_button) {
392 fwin->right_button->descriptor.parent = fwin;
393 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
394 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
395 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
398 checkTitleSize(fwin);
403 void
404 wFrameWindowDestroy(WFrameWindow *fwin)
406 int i;
408 if (fwin->left_button)
409 wCoreDestroy(fwin->left_button);
411 #ifdef XKB_BUTTON_HINT
412 if (fwin->language_button)
413 wCoreDestroy(fwin->language_button);
414 #endif
416 if (fwin->right_button)
417 wCoreDestroy(fwin->right_button);
419 if (fwin->resizebar)
420 wCoreDestroy(fwin->resizebar);
422 if (fwin->titlebar)
423 wCoreDestroy(fwin->titlebar);
425 RemoveFromStackList(fwin->core);
427 wCoreDestroy(fwin->core);
429 if (fwin->title)
430 free(fwin->title);
432 for (i=0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
433 FREE_PIXMAP(fwin->title_back[i]);
434 if (wPreferences.new_style) {
435 FREE_PIXMAP(fwin->lbutton_back[i]);
436 #ifdef XKB_BUTTON_HINT
437 FREE_PIXMAP(fwin->languagebutton_back[i]);
438 #endif
439 FREE_PIXMAP(fwin->rbutton_back[i]);
443 free(fwin);
447 void
448 wFrameWindowChangeState(WFrameWindow *fwin, int state)
450 if (fwin->flags.state==state)
451 return;
453 fwin->flags.state = state;
454 fwin->flags.need_texture_change = 1;
456 wFrameWindowPaint(fwin);
460 static void
461 updateTitlebar(WFrameWindow *fwin)
463 int x, w;
464 int theight;
466 theight = WMFontHeight(*fwin->font) + TITLEBAR_EXTRA_HEIGHT;
468 x = 0;
469 w = fwin->core->width + 1;
471 if (wPreferences.new_style) {
472 if (fwin->flags.hide_left_button || !fwin->left_button
473 || fwin->flags.lbutton_dont_fit) {
474 x = 0;
475 #ifdef XKB_BUTTON_HINT
476 if(fwin->language_button)
477 wCoreConfigure(fwin->language_button, 0, 0,
478 fwin->language_button->width,
479 fwin->language_button->width);
480 #endif
481 } else {
482 #ifdef XKB_BUTTON_HINT
483 if(fwin->language_button)
484 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
485 fwin->language_button->width,
486 fwin->language_button->width);
487 #endif
488 x = fwin->left_button->width;
489 w -= fwin->left_button->width;
491 #ifdef XKB_BUTTON_HINT
492 if (fwin->flags.hide_language_button || !fwin->language_button
493 || fwin->flags.languagebutton_dont_fit) {
494 } else {
495 x += fwin->language_button->width;
496 w -= fwin->language_button->width;
498 #endif
500 #ifdef XKB_BUTTON_HINT
501 else {
502 int bsize = theight - 7;
503 if (fwin->flags.hide_left_button || !fwin->left_button
504 || fwin->flags.lbutton_dont_fit) {
505 if(fwin->language_button)
506 wCoreConfigure(fwin->language_button, 3, (theight-bsize)/2,
507 fwin->language_button->width,
508 fwin->language_button->width);
510 else {
511 if(fwin->language_button)
512 wCoreConfigure(fwin->language_button,
513 6 + fwin->left_button->width, (theight-bsize)/2,
514 fwin->language_button->width,
515 fwin->language_button->width);
518 #endif
520 if (wPreferences.new_style) {
521 if (!fwin->flags.hide_right_button && fwin->right_button
522 && !fwin->flags.rbutton_dont_fit) {
523 w -= fwin->right_button->width;
527 if (wPreferences.new_style || fwin->titlebar->width!=w)
528 fwin->flags.need_texture_remake = 1;
530 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
534 void
535 wFrameWindowHideButton(WFrameWindow *fwin, int flags)
537 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
538 XUnmapWindow(dpy, fwin->right_button->window);
539 fwin->flags.hide_right_button = 1;
542 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
543 XUnmapWindow(dpy, fwin->left_button->window);
544 fwin->flags.hide_left_button = 1;
547 #ifdef XKB_BUTTON_HINT
548 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
549 XUnmapWindow(dpy, fwin->language_button->window);
550 fwin->flags.hide_language_button = 1;
552 #endif
554 if (fwin->titlebar) {
555 if (wPreferences.new_style) {
556 updateTitlebar(fwin);
557 } else {
558 #ifdef XKB_BUTTON_HINT
559 updateTitlebar(fwin);
560 #else
561 XClearWindow(dpy, fwin->titlebar->window);
562 wFrameWindowPaint(fwin);
563 #endif
565 checkTitleSize(fwin);
570 void
571 wFrameWindowShowButton(WFrameWindow *fwin, int flags)
573 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button
574 && fwin->flags.hide_right_button) {
576 if (!fwin->flags.rbutton_dont_fit)
577 XMapWindow(dpy, fwin->right_button->window);
579 fwin->flags.hide_right_button = 0;
582 #ifdef XKB_BUTTON_HINT
583 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button
584 && fwin->flags.hide_language_button) {
586 if (!fwin->flags.languagebutton_dont_fit)
587 XMapWindow(dpy, fwin->language_button->window);
589 fwin->flags.hide_language_button = 0;
591 #endif
593 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button
594 && fwin->flags.hide_left_button) {
596 if (!fwin->flags.lbutton_dont_fit)
597 XMapWindow(dpy, fwin->left_button->window);
599 fwin->flags.hide_left_button = 0;
603 if (fwin->titlebar) {
604 if (wPreferences.new_style) {
605 updateTitlebar(fwin);
606 } else {
607 XClearWindow(dpy, fwin->titlebar->window);
608 wFrameWindowPaint(fwin);
610 checkTitleSize(fwin);
615 static void
616 #ifdef XKB_BUTTON_HINT
617 renderTexture(WScreen *scr, WTexture *texture, int width, int height,
618 int bwidth, int bheight, int left, int language, int right,
619 Pixmap *title, Pixmap *lbutton, Pixmap *languagebutton, Pixmap *rbutton)
620 #else
621 renderTexture(WScreen *scr, WTexture *texture, int width, int height,
622 int bwidth, int bheight, int left, int right,
623 Pixmap *title, Pixmap *lbutton, Pixmap *rbutton)
624 #endif
626 RImage *img;
627 RImage *limg, *rimg, *mimg;
628 #ifdef XKB_BUTTON_HINT
629 RImage *timg;
630 #endif
631 int x, w;
633 *title = None;
634 *lbutton = None;
635 *rbutton = None;
636 #ifdef XKB_BUTTON_HINT
637 *languagebutton = None;
638 #endif
640 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
641 if (!img) {
642 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
643 return;
646 if (wPreferences.new_style) {
647 if (left) {
648 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
649 } else
650 limg = NULL;
652 x = 0;
653 w = img->width;
655 #ifdef XKB_BUTTON_HINT
656 if (language) {
657 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
658 } else
659 timg = NULL;
660 #endif
662 if (limg) {
663 RBevelImage(limg, RBEV_RAISED2);
664 if (!RConvertImage(scr->rcontext, limg, lbutton)) {
665 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
667 x += limg->width;
668 w -= limg->width;
669 RDestroyImage(limg);
672 #ifdef XKB_BUTTON_HINT
673 if (timg) {
674 RBevelImage(timg, RBEV_RAISED2);
675 if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
676 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
678 x += timg->width;
679 w -= timg->width;
680 RDestroyImage(timg);
682 #endif
684 if (right) {
685 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
686 } else
687 rimg = NULL;
689 if (rimg) {
690 RBevelImage(rimg, RBEV_RAISED2);
691 if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
692 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
694 w -= rimg->width;
695 RDestroyImage(rimg);
698 if (w!=width) {
699 mimg = RGetSubImage(img, x, 0, w, img->height);
700 RBevelImage(mimg, RBEV_RAISED2);
702 if (!RConvertImage(scr->rcontext, mimg, title)) {
703 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
705 RDestroyImage(mimg);
706 } else {
707 RBevelImage(img, RBEV_RAISED2);
709 if (!RConvertImage(scr->rcontext, img, title)) {
710 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
713 } else {
714 RBevelImage(img, RBEV_RAISED2);
716 if (!RConvertImage(scr->rcontext, img, title)) {
717 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
721 RDestroyImage(img);
725 static void
726 renderResizebarTexture(WScreen *scr, WTexture *texture, int width, int height,
727 int cwidth, Pixmap *pmap)
729 RImage *img;
730 RColor light;
731 RColor dark;
733 *pmap = None;
735 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
736 if (!img) {
737 wwarning(_("could not render texture: %s"),
738 RMessageForError(RErrorCode));
739 return;
742 light.alpha = 0;
743 light.red = light.green = light.blue = 80;
745 dark.alpha = 0;
746 dark.red = dark.green = dark.blue = 40;
748 ROperateLine(img, RSubtractOperation, 0, 0, width-1, 0, &dark);
749 ROperateLine(img, RAddOperation, 0, 1, width-1, 1, &light);
751 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height-1, &dark);
752 ROperateLine(img, RAddOperation, cwidth+1, 2, cwidth+1, height-1, &light);
754 if (width > 1)
755 ROperateLine(img, RSubtractOperation, width-cwidth-2, 2,
756 width-cwidth-2, height-1, &dark);
757 ROperateLine(img, RAddOperation, width-cwidth-1, 2, width-cwidth-1,
758 height-1, &light);
760 #ifdef SHADOW_RESIZEBAR
761 ROperateLine(img, RAddOperation, 0, 1, 0, height-1, &light);
762 ROperateLine(img, RSubtractOperation, width-1, 1, width-1, height-1,
763 &dark);
764 ROperateLine(img, RSubtractOperation, 0, height-1, width-1, height-1,
765 &dark);
766 #endif /* SHADOW_RESIZEBAR */
769 if (!RConvertImage(scr->rcontext, img, pmap)) {
770 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
773 RDestroyImage(img);
778 static void
779 updateTexture(WFrameWindow *fwin)
781 int i;
782 unsigned long pixel;
784 i = fwin->flags.state;
785 if (fwin->titlebar) {
786 if (fwin->title_texture[i]->any.type!=WTEX_SOLID) {
787 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window,
788 fwin->title_back[i]);
789 if (wPreferences.new_style) {
790 if (fwin->left_button && fwin->lbutton_back[i])
791 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
792 fwin->lbutton_back[i]);
794 #ifdef XKB_BUTTON_HINT
795 if (fwin->language_button && fwin->languagebutton_back[i]) {
796 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
797 fwin->languagebutton_back[i]);
799 #endif
801 if (fwin->right_button && fwin->rbutton_back[i])
802 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
803 fwin->rbutton_back[i]);
805 } else {
806 pixel = fwin->title_texture[i]->solid.normal.pixel;
807 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
808 if (wPreferences.new_style) {
809 if (fwin->left_button)
810 XSetWindowBackground(dpy, fwin->left_button->window,
811 pixel);
812 #ifdef XKB_BUTTON_HINT
813 if (fwin->language_button)
814 XSetWindowBackground(dpy, fwin->language_button->window,
815 pixel);
816 #endif
817 if (fwin->right_button)
818 XSetWindowBackground(dpy, fwin->right_button->window,
819 pixel);
822 XClearWindow(dpy, fwin->titlebar->window);
824 if (fwin->left_button) {
825 XClearWindow(dpy, fwin->left_button->window);
826 handleButtonExpose(&fwin->left_button->descriptor, NULL);
828 #ifdef XKB_BUTTON_HINT
829 if (fwin->language_button) {
830 XClearWindow(dpy, fwin->language_button->window);
831 handleButtonExpose(&fwin->language_button->descriptor, NULL);
833 #endif
834 if (fwin->right_button) {
835 XClearWindow(dpy, fwin->right_button->window);
836 handleButtonExpose(&fwin->right_button->descriptor, NULL);
843 static void
844 remakeTexture(WFrameWindow *fwin, int state)
846 Pixmap pmap, lpmap, rpmap;
847 #ifdef XKB_BUTTON_HINT
848 Pixmap tpmap;
849 #endif
851 if (fwin->title_texture[state] && fwin->titlebar) {
852 FREE_PIXMAP(fwin->title_back[state]);
853 if (wPreferences.new_style) {
854 FREE_PIXMAP(fwin->lbutton_back[state]);
855 FREE_PIXMAP(fwin->rbutton_back[state]);
856 #ifdef XKB_BUTTON_HINT
857 FREE_PIXMAP(fwin->languagebutton_back[state]);
858 #endif
861 if (fwin->title_texture[state]->any.type!=WTEX_SOLID) {
862 int left, right;
863 #ifdef XKB_BUTTON_HINT
864 int language;
865 #endif
866 int width;
868 /* eventually surrounded by if new_style */
869 left = fwin->left_button && !fwin->flags.hide_left_button
870 && !fwin->flags.lbutton_dont_fit;
871 #ifdef XKB_BUTTON_HINT
872 language = fwin->language_button && !fwin->flags.hide_language_button
873 && !fwin->flags.languagebutton_dont_fit;
874 #endif
875 right = fwin->right_button && !fwin->flags.hide_right_button
876 && !fwin->flags.rbutton_dont_fit;
878 width = fwin->core->width+1;
880 #ifdef XKB_BUTTON_HINT
881 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
882 width, fwin->titlebar->height,
883 fwin->titlebar->height, fwin->titlebar->height,
884 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
885 #else
886 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
887 width, fwin->titlebar->height,
888 fwin->titlebar->height, fwin->titlebar->height,
889 left, right, &pmap, &lpmap, &rpmap);
890 #endif
892 fwin->title_back[state] = pmap;
893 if (wPreferences.new_style) {
894 fwin->lbutton_back[state] = lpmap;
895 fwin->rbutton_back[state] = rpmap;
896 #ifdef XKB_BUTTON_HINT
897 fwin->languagebutton_back[state] = tpmap;
898 #endif
902 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
903 && fwin->resizebar && state == 0) {
905 FREE_PIXMAP(fwin->resizebar_back[0]);
907 if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
909 renderResizebarTexture(fwin->screen_ptr,
910 fwin->resizebar_texture[0],
911 fwin->resizebar->width,
912 fwin->resizebar->height,
913 fwin->resizebar_corner_width,
914 &pmap);
916 fwin->resizebar_back[0] = pmap;
919 /* this part should be in updateTexture() */
920 if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
921 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window,
922 fwin->resizebar_back[0]);
923 } else {
924 XSetWindowBackground(dpy, fwin->resizebar->window,
925 fwin->resizebar_texture[0]->solid.normal.pixel);
927 XClearWindow(dpy, fwin->resizebar->window);
932 void
933 wFrameWindowPaint(WFrameWindow *fwin)
935 if (fwin->flags.is_client_window_frame)
936 fwin->flags.justification = wPreferences.title_justification;
938 if (fwin->flags.need_texture_remake) {
939 int i;
941 fwin->flags.need_texture_remake = 0;
942 fwin->flags.need_texture_change = 0;
944 if (fwin->flags.single_texture) {
945 remakeTexture(fwin, 0);
946 updateTexture(fwin);
947 } else {
948 /* first render the texture for the current state... */
949 remakeTexture(fwin, fwin->flags.state);
950 /* ... and paint it */
951 updateTexture(fwin);
953 for (i=0; i < 3; i++) {
954 if (i!=fwin->flags.state)
955 remakeTexture(fwin, i);
960 if (fwin->flags.need_texture_change) {
961 fwin->flags.need_texture_change = 0;
963 updateTexture(fwin);
966 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
967 && fwin->title_texture[fwin->flags.state]->any.type==WTEX_SOLID) {
968 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
969 fwin->titlebar->height,
970 (WTexSolid*)fwin->title_texture[fwin->flags.state],
971 WREL_RAISED);
974 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
975 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
976 Window win;
977 int w, h;
978 int cw;
979 GC light_gc, dim_gc;
980 WTexSolid *texture = (WTexSolid*)fwin->resizebar_texture[0];
982 w = fwin->resizebar->width;
983 h = fwin->resizebar->height;
984 cw = fwin->resizebar_corner_width;
985 light_gc = texture->light_gc;
986 dim_gc = texture->dim_gc;
987 win = fwin->resizebar->window;
989 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
990 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
992 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
993 XDrawLine(dpy, win, light_gc, cw+1, 2, cw+1, h);
995 XDrawLine(dpy, win, dim_gc, w-cw-2, 2, w-cw-2, h);
996 XDrawLine(dpy, win, light_gc, w-cw-1, 2, w-cw-1, h);
998 #ifdef SHADOW_RESIZEBAR
999 XDrawLine(dpy, win, light_gc, 0, 1, 0, h-1);
1000 XDrawLine(dpy, win, dim_gc, w-1, 2, w-1, h-1);
1001 XDrawLine(dpy, win, dim_gc, 1, h-1, cw, h-1);
1002 XDrawLine(dpy, win, dim_gc, cw+2, h-1, w-cw-2, h-1);
1003 XDrawLine(dpy, win, dim_gc, w-cw, h-1, w-1, h-1);
1004 #endif /* SHADOW_RESIZEBAR */
1008 if (fwin->title && fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
1009 int x, w;
1010 int lofs = 6, rofs = 6;
1011 int titlelen;
1012 char *title;
1013 int allButtons = 1;
1016 if (!wPreferences.new_style) {
1017 if (fwin->left_button && !fwin->flags.hide_left_button
1018 && !fwin->flags.lbutton_dont_fit)
1019 lofs += fwin->left_button->width + 3;
1020 else
1021 allButtons = 0;
1023 #ifdef XKB_BUTTON_HINT
1024 if (fwin->language_button && !fwin->flags.hide_language_button
1025 && !fwin->flags.languagebutton_dont_fit)
1026 lofs += fwin->language_button->width;
1027 else
1028 allButtons = 0;
1029 #endif
1031 if (fwin->right_button && !fwin->flags.hide_right_button
1032 && !fwin->flags.rbutton_dont_fit)
1033 rofs += fwin->right_button->width + 3;
1034 else
1035 allButtons = 0;
1038 #ifdef XKB_BUTTON_HINT
1039 fwin->languagebutton_image =
1040 fwin->screen_ptr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1041 #endif
1043 title = ShrinkString(*fwin->font, fwin->title,
1044 fwin->titlebar->width - lofs - rofs);
1045 titlelen = strlen(title);
1046 w = WMWidthOfString(*fwin->font, title, titlelen);
1048 switch (fwin->flags.justification) {
1049 case WTJ_LEFT:
1050 x = lofs;
1051 break;
1053 case WTJ_RIGHT:
1054 x = fwin->titlebar->width - w - rofs;
1055 break;
1057 default:
1058 if (!allButtons)
1059 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1060 else
1061 x = (fwin->titlebar->width - w) / 2;
1062 break;
1065 #ifdef TITLE_TEXT_SHADOW
1066 if(wPreferences.title_shadow){
1067 int shadowx,shadowy;
1068 XSetForeground(dpy, *fwin->title_gc,
1069 fwin->title_pixel[fwin->flags.state+3]);
1070 for(shadowx=0;shadowx<TITLE_TEXT_SHADOW_WIDTH;shadowx++)
1071 for(shadowy=0;shadowy<TITLE_TEXT_SHADOW_HEIGHT;shadowy++)
1072 WMDrawString(fwin->screen_ptr->wmscreen, fwin->titlebar->window,
1073 *fwin->title_gc, *fwin->font,
1074 x + shadowx + TITLE_TEXT_SHADOW_X_OFFSET,
1075 TITLEBAR_EXTRA_HEIGHT/2
1076 + shadowy + TITLE_TEXT_SHADOW_Y_OFFSET, title,
1077 titlelen);
1079 #endif /* TITLE_TEXT_SHADOW */
1081 XSetForeground(dpy, *fwin->title_gc,
1082 fwin->title_pixel[fwin->flags.state]);
1084 WMDrawString(fwin->screen_ptr->wmscreen, fwin->titlebar->window,
1085 *fwin->title_gc, *fwin->font, x, TITLEBAR_EXTRA_HEIGHT/2,
1086 title, titlelen);
1088 free(title);
1090 if (fwin->left_button)
1091 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1092 if (fwin->right_button)
1093 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1094 #ifdef XKB_BUTTON_HINT
1095 if (fwin->language_button)
1096 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1097 #endif
1102 static void
1103 reconfigure(WFrameWindow *fwin, int x, int y, int width, int height,
1104 Bool dontMove)
1106 int k = (wPreferences.new_style ? 4 : 3);
1107 int resizedHorizontally = 0;
1109 if (dontMove)
1110 XResizeWindow(dpy, fwin->core->window, width, height);
1111 else
1112 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1115 if (fwin->core->height != height && fwin->resizebar)
1116 XMoveWindow(dpy, fwin->resizebar->window, 0,
1117 height - fwin->resizebar->height);
1119 if (fwin->core->width != width) {
1120 fwin->flags.need_texture_remake = 1;
1121 resizedHorizontally = 1;
1124 fwin->core->width = width;
1125 fwin->core->height = height;
1127 if (fwin->titlebar && resizedHorizontally) {
1128 /* Check if the titlebar is wide enough to hold the buttons.
1129 * Temporarily remove them if can't
1131 if (fwin->left_button) {
1132 if (width < fwin->top_width*k && !fwin->flags.lbutton_dont_fit) {
1134 if (!fwin->flags.hide_left_button) {
1135 XUnmapWindow(dpy, fwin->left_button->window);
1137 fwin->flags.lbutton_dont_fit = 1;
1138 } else if (width >= fwin->top_width*k && fwin->flags.lbutton_dont_fit) {
1140 if (!fwin->flags.hide_left_button) {
1141 XMapWindow(dpy, fwin->left_button->window);
1143 fwin->flags.lbutton_dont_fit = 0;
1147 #ifdef XKB_BUTTON_HINT
1148 if (fwin->language_button) {
1149 if (width < fwin->top_width*k && !fwin->flags.languagebutton_dont_fit) {
1151 if (!fwin->flags.hide_language_button) {
1152 XUnmapWindow(dpy, fwin->language_button->window);
1154 fwin->flags.languagebutton_dont_fit = 1;
1155 } else if (width >= fwin->top_width*k && fwin->flags.languagebutton_dont_fit) {
1157 if (!fwin->flags.hide_language_button) {
1158 XMapWindow(dpy, fwin->language_button->window);
1160 fwin->flags.languagebutton_dont_fit = 0;
1163 #endif
1165 if (fwin->right_button) {
1166 if (width < fwin->top_width*2 && !fwin->flags.rbutton_dont_fit) {
1168 if (!fwin->flags.hide_right_button) {
1169 XUnmapWindow(dpy, fwin->right_button->window);
1171 fwin->flags.rbutton_dont_fit = 1;
1172 } else if (width >= fwin->top_width*2 && fwin->flags.rbutton_dont_fit) {
1174 if (!fwin->flags.hide_right_button) {
1175 XMapWindow(dpy, fwin->right_button->window);
1177 fwin->flags.rbutton_dont_fit = 0;
1181 if (wPreferences.new_style) {
1182 if (fwin->right_button)
1183 XMoveWindow(dpy, fwin->right_button->window,
1184 width - fwin->right_button->width + 1, 0);
1185 } else {
1186 if (fwin->right_button)
1187 XMoveWindow(dpy, fwin->right_button->window,
1188 width - fwin->right_button->width - 3,
1189 (fwin->titlebar->height - fwin->right_button->height)/2);
1191 updateTitlebar(fwin);
1192 checkTitleSize(fwin);
1195 if (fwin->resizebar) {
1196 wCoreConfigure(fwin->resizebar, 0,
1197 fwin->core->height - fwin->resizebar->height,
1198 fwin->core->width, fwin->resizebar->height);
1200 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1201 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
1202 fwin->resizebar_corner_width = fwin->core->width/2;
1207 void
1208 wFrameWindowConfigure(WFrameWindow *fwin, int x, int y, int width, int height)
1210 reconfigure(fwin, x, y, width, height, False);
1213 void
1214 wFrameWindowResize(WFrameWindow *fwin, int width, int height)
1216 reconfigure(fwin, 0, 0, width, height, True);
1221 int
1222 wFrameWindowChangeTitle(WFrameWindow *fwin, char *new_title)
1224 /* check if the title is the same as before */
1225 if (fwin->title) {
1226 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1227 return 0;
1229 } else {
1230 if (!new_title)
1231 return 0;
1234 if (fwin->title)
1235 free(fwin->title);
1237 fwin->title = wstrdup(new_title);
1239 if (fwin->titlebar) {
1240 XClearWindow(dpy, fwin->titlebar->window);
1242 wFrameWindowPaint(fwin);
1244 checkTitleSize(fwin);
1246 return 1;
1250 #ifdef OLWM_HINTS
1251 void
1252 wFrameWindowUpdatePushButton(WFrameWindow *fwin, Bool pushed)
1254 fwin->flags.right_button_pushed_in = pushed;
1256 paintButton(fwin->right_button, fwin->title_texture[fwin->flags.state],
1257 fwin->title_pixel[fwin->flags.state],
1258 fwin->rbutton_image, pushed);
1260 #endif /* OLWM_HINTS */
1263 #ifdef XKB_BUTTON_HINT
1264 void
1265 wFrameWindowUpdateLanguageButton(WFrameWindow *fwin)
1267 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1268 fwin->title_pixel[fwin->flags.state],
1269 fwin->languagebutton_image, True);
1271 #endif /* XKB_BUTTON_HINT */
1274 /*********************************************************************/
1276 static void
1277 handleExpose(WObjDescriptor *desc, XEvent *event)
1279 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1282 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1283 fwin->flags.repaint_only_titlebar = 1;
1284 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1285 fwin->flags.repaint_only_resizebar = 1;
1286 wFrameWindowPaint(fwin);
1287 fwin->flags.repaint_only_titlebar = 0;
1288 fwin->flags.repaint_only_resizebar = 0;
1292 static void
1293 checkTitleSize(WFrameWindow *fwin)
1295 int width;
1297 if (!fwin->title) {
1298 fwin->flags.incomplete_title = 0;
1299 return;
1302 if (!fwin->titlebar) {
1303 fwin->flags.incomplete_title = 1;
1304 return;
1305 } else {
1306 width = fwin->titlebar->width - 6 - 6;
1309 if (!wPreferences.new_style) {
1310 if (fwin->left_button && !fwin->flags.hide_left_button
1311 && !fwin->flags.lbutton_dont_fit)
1312 width -= fwin->left_button->width + 3;
1314 #ifdef XKB_BUTTON_HINT
1315 if (fwin->language_button && !fwin->flags.hide_language_button
1316 && !fwin->flags.languagebutton_dont_fit)
1317 width -= fwin->language_button->width + 3;
1318 #endif
1320 if (fwin->right_button && !fwin->flags.hide_right_button
1321 && !fwin->flags.rbutton_dont_fit)
1322 width -= fwin->right_button->width + 3;
1324 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1325 fwin->flags.incomplete_title = 1;
1326 } else {
1327 fwin->flags.incomplete_title = 0;
1332 static void
1333 paintButton(WCoreWindow *button, WTexture *texture, unsigned long color,
1334 WPixmap *image, int pushed)
1336 WScreen *scr = button->screen_ptr;
1337 GC copy_gc = scr->copy_gc;
1338 int x=0, y=0, d=0;
1339 int left=0, width=0;
1341 /* setup stuff according to the state */
1342 if (pushed) {
1343 if (image) {
1344 if (image->width>=image->height*2) {
1345 /* the image contains 2 pictures: the second is for the
1346 * pushed state */
1347 width = image->width/2;
1348 left = image->width/2;
1349 } else {
1350 width = image->width;
1353 XSetClipMask(dpy, copy_gc, None);
1354 XSetForeground(dpy, copy_gc, scr->white_pixel);
1355 d=1;
1356 if (wPreferences.new_style) {
1357 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1358 button->width-1, button->height-1);
1359 XSetForeground(dpy, copy_gc, scr->black_pixel);
1360 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1361 button->width-1, button->height-1);
1362 } else {
1363 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1364 button->width, button->height);
1365 XSetForeground(dpy, copy_gc, scr->black_pixel);
1366 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1367 button->width, button->height);
1369 } else {
1370 XClearWindow(dpy, button->window);
1372 if (image) {
1373 if (image->width>=image->height*2)
1374 width = image->width/2;
1375 else
1376 width = image->width;
1378 d=0;
1380 if (wPreferences.new_style) {
1381 if (texture->any.type==WTEX_SOLID || pushed) {
1382 wDrawBevel(button->window, button->width, button->height,
1383 (WTexSolid*)texture, WREL_RAISED);
1385 } else {
1386 wDrawBevel(button->window, button->width, button->height,
1387 scr->widget_texture, WREL_RAISED);
1391 if (image) {
1392 /* display image */
1393 XSetClipMask(dpy, copy_gc, image->mask);
1394 x = (button->width - width)/2 + d;
1395 y = (button->height - image->height)/2 + d;
1396 XSetClipOrigin(dpy, copy_gc, x-left, y);
1397 if (!wPreferences.new_style) {
1398 XSetForeground(dpy, copy_gc, scr->black_pixel);
1399 if (!pushed) {
1400 if (image->depth==1)
1401 XCopyPlane(dpy, image->image, button->window, copy_gc,
1402 left, 0, width, image->height, x, y, 1);
1403 else
1404 XCopyArea(dpy, image->image, button->window, copy_gc,
1405 left, 0, width, image->height, x, y);
1406 } else {
1407 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1408 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1409 button->width, button->height);
1411 } else {
1412 if (pushed) {
1413 XSetForeground(dpy, copy_gc, scr->black_pixel);
1414 } else {
1415 XSetForeground(dpy, copy_gc, color);
1416 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1418 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1419 button->width, button->height);
1425 static void
1426 handleButtonExpose(WObjDescriptor *desc, XEvent *event)
1428 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1429 WCoreWindow *button = (WCoreWindow*)desc->self;
1431 #ifdef XKB_BUTTON_HINT
1432 if (button == fwin->language_button) {
1433 if (wPreferences.modelock){
1434 paintButton(button, fwin->title_texture[fwin->flags.state],
1435 fwin->title_pixel[fwin->flags.state],
1436 fwin->languagebutton_image, False);
1438 } else
1439 #endif
1440 if (button == fwin->left_button) {
1441 paintButton(button, fwin->title_texture[fwin->flags.state],
1442 fwin->title_pixel[fwin->flags.state],
1443 fwin->lbutton_image, False);
1444 } else {
1445 Bool pushed = False;
1447 #ifdef OLWM_HINTS
1448 if (fwin->flags.right_button_pushed_in)
1449 pushed = True;
1450 #endif
1451 /* emulate the olwm pushpin in the "out" state */
1452 paintButton(button, fwin->title_texture[fwin->flags.state],
1453 fwin->title_pixel[fwin->flags.state],
1454 fwin->rbutton_image, pushed);
1459 static void
1460 titlebarMouseDown(WObjDescriptor *desc, XEvent *event)
1462 WFrameWindow *fwin = desc->parent;
1463 WCoreWindow *titlebar = desc->self;
1465 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1466 if (fwin->on_dblclick_titlebar)
1467 (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event);
1468 } else {
1469 if (fwin->on_mousedown_titlebar)
1470 (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event);
1475 static void
1476 resizebarMouseDown(WObjDescriptor *desc, XEvent *event)
1478 WFrameWindow *fwin = desc->parent;
1479 WCoreWindow *resizebar = desc->self;
1481 if (fwin->on_mousedown_resizebar)
1482 (*fwin->on_mousedown_resizebar)(resizebar, fwin->child, event);
1486 static void
1487 buttonMouseDown(WObjDescriptor *desc, XEvent *event)
1489 WFrameWindow *fwin = desc->parent;
1490 WCoreWindow *button = desc->self;
1491 WPixmap *image;
1492 XEvent ev;
1493 int done=0, execute=1;
1494 WTexture *texture;
1495 unsigned long pixel;
1496 int clickButton = event->xbutton.button;
1498 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1499 if (button == fwin->right_button && fwin->on_dblclick_right) {
1500 (*fwin->on_dblclick_right)(button, fwin->child, event);
1502 return;
1505 if (button == fwin->left_button) {
1506 image = fwin->lbutton_image;
1507 } else {
1508 image = fwin->rbutton_image;
1510 #ifdef XKB_BUTTON_HINT
1511 if (button == fwin->language_button) {
1512 if (!wPreferences.modelock) return;
1513 image = fwin->languagebutton_image;
1515 #endif
1517 pixel = fwin->title_pixel[fwin->flags.state];
1518 texture = fwin->title_texture[fwin->flags.state];
1519 paintButton(button, texture, pixel, image, True);
1521 while (!done) {
1522 WMMaskEvent(dpy, LeaveWindowMask|EnterWindowMask|ButtonReleaseMask
1523 |ButtonPressMask|ExposureMask, &ev);
1524 switch (ev.type) {
1525 case LeaveNotify:
1526 execute = 0;
1527 paintButton(button, texture, pixel, image, False);
1528 break;
1530 case EnterNotify:
1531 execute = 1;
1532 paintButton(button, texture, pixel, image, True);
1533 break;
1535 case ButtonPress:
1536 break;
1538 case ButtonRelease:
1539 if (ev.xbutton.button == clickButton)
1540 done = 1;
1541 break;
1543 default:
1544 WMHandleEvent(&ev);
1547 paintButton(button, texture, pixel, image, False);
1549 if (execute) {
1550 if (button == fwin->left_button) {
1551 if (fwin->on_click_left)
1552 (*fwin->on_click_left)(button, fwin->child, &ev);
1553 } else if (button == fwin->right_button) {
1554 if (fwin->on_click_right)
1555 (*fwin->on_click_right)(button, fwin->child, &ev);
1557 #ifdef XKB_BUTTON_HINT
1558 else if (button == fwin->language_button) {
1559 if (fwin->on_click_language)
1560 (*fwin->on_click_language)(button, fwin->child, &ev);
1562 #endif