makefile.am for icons
[wmaker-crm.git] / src / framewin.c
bloba563b8db5d6a70e5df34ea7c7b8e03368912df3e
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 (flags & WFF_BORDER)
99 ? FRAME_BORDER_WIDTH : 0);
100 if (wPreferences.use_saveunders) {
101 unsigned long vmask;
102 XSetWindowAttributes attribs;
104 vmask = CWSaveUnder;
105 attribs.save_under = True;
106 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
109 /* setup stacking information */
110 fwin->core->stacking = wmalloc(sizeof(WStacking));
111 fwin->core->stacking->above = NULL;
112 fwin->core->stacking->under = NULL;
113 fwin->core->stacking->child_of = NULL;
114 fwin->core->stacking->window_level = wlevel;
116 AddToStackList(fwin->core);
118 wFrameWindowUpdateBorders(fwin, flags);
120 return fwin;
125 void
126 wFrameWindowUpdateBorders(WFrameWindow *fwin, int flags)
128 int theight;
129 int bsize;
130 int width, height;
131 int i;
132 WScreen *scr = fwin->screen_ptr;
134 width = fwin->core->width;
135 if (flags & WFF_IS_SHADED)
136 height = -1;
137 else
138 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
140 if (flags & WFF_TITLEBAR)
141 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
142 else
143 theight = 0;
145 if (wPreferences.new_style) {
146 bsize = theight;
147 } else {
148 bsize = theight - 7;
151 if (fwin->titlebar) {
152 /* if we had a titlebar and is requesting for one,
153 * check if the size has changed and resize it */
154 if (flags & WFF_TITLEBAR) {
155 fwin->top_width = theight;
157 fwin->flags.need_texture_remake = 1;
159 if (wPreferences.new_style) {
160 if (fwin->left_button) {
161 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
163 #ifdef XKB_BUTTON_HINT
164 if (fwin->language_button)
165 if (fwin->flags.hide_left_button || !fwin->left_button
166 || fwin->flags.lbutton_dont_fit) {
167 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
168 } else {
169 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
171 #endif
174 if (fwin->right_button) {
175 wCoreConfigure(fwin->right_button, width-bsize+1,
176 0, bsize, bsize);
178 } else { /* !new_style */
179 if (fwin->left_button) {
180 wCoreConfigure(fwin->left_button, 3, (theight-bsize)/2,
181 bsize, bsize);
184 #ifdef XKB_BUTTON_HINT
185 if (fwin->language_button) {
186 wCoreConfigure(fwin->language_button, 6 + bsize, (theight-bsize)/2,
187 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;
326 if (!fwin->resizebar) {
327 fwin->flags.resizebar = 1;
328 fwin->resizebar = wCoreCreate(fwin->core, 0,
329 height + fwin->top_width,
330 width, RESIZEBAR_HEIGHT);
331 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
332 if (width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
333 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH)/2;
334 if (fwin->resizebar_corner_width < 0)
335 fwin->resizebar_corner_width = 0;
338 XMapWindow(dpy, fwin->resizebar->window);
339 XLowerWindow(dpy, fwin->resizebar->window);
341 fwin->flags.need_texture_remake = 1;
342 } else {
343 if (height+fwin->top_width+fwin->bottom_width != fwin->core->height) {
344 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
345 width, RESIZEBAR_HEIGHT);
348 } else {
349 fwin->bottom_width = 0;
351 if (fwin->resizebar) {
352 fwin->bottom_width = 0;
353 wCoreDestroy(fwin->resizebar);
354 fwin->resizebar = NULL;
358 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height
359 && !(flags & WFF_IS_SHADED)) {
360 wFrameWindowResize(fwin, width,
361 height + fwin->top_width + fwin->bottom_width);
365 if (flags & WFF_BORDER) {
366 XSetWindowBorderWidth(dpy, fwin->core->window, FRAME_BORDER_WIDTH);
367 } else {
368 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
371 /* setup object descriptors */
373 if (fwin->titlebar) {
374 fwin->titlebar->descriptor.handle_expose = handleExpose;
375 fwin->titlebar->descriptor.parent = fwin;
376 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
377 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
380 if (fwin->resizebar) {
381 fwin->resizebar->descriptor.handle_expose = handleExpose;
382 fwin->resizebar->descriptor.parent = fwin;
383 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
384 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
387 if (fwin->left_button) {
388 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
389 fwin->left_button->descriptor.parent = fwin;
390 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
391 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
394 #ifdef XKB_BUTTON_HINT
395 if (fwin->language_button) {
396 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
397 fwin->language_button->descriptor.parent = fwin;
398 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
399 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
401 #endif
404 if (fwin->right_button) {
405 fwin->right_button->descriptor.parent = fwin;
406 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
407 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
408 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
411 checkTitleSize(fwin);
416 void
417 wFrameWindowDestroy(WFrameWindow *fwin)
419 int i;
421 if (fwin->left_button)
422 wCoreDestroy(fwin->left_button);
424 #ifdef XKB_BUTTON_HINT
425 if (fwin->language_button)
426 wCoreDestroy(fwin->language_button);
427 #endif
429 if (fwin->right_button)
430 wCoreDestroy(fwin->right_button);
432 if (fwin->resizebar)
433 wCoreDestroy(fwin->resizebar);
435 if (fwin->titlebar)
436 wCoreDestroy(fwin->titlebar);
438 RemoveFromStackList(fwin->core);
440 wCoreDestroy(fwin->core);
442 if (fwin->title)
443 free(fwin->title);
445 for (i=0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
446 FREE_PIXMAP(fwin->title_back[i]);
447 if (wPreferences.new_style) {
448 FREE_PIXMAP(fwin->lbutton_back[i]);
449 #ifdef XKB_BUTTON_HINT
450 FREE_PIXMAP(fwin->languagebutton_back[i]);
451 #endif
452 FREE_PIXMAP(fwin->rbutton_back[i]);
456 free(fwin);
460 void
461 wFrameWindowChangeState(WFrameWindow *fwin, int state)
463 if (fwin->flags.state==state)
464 return;
466 fwin->flags.state = state;
467 fwin->flags.need_texture_change = 1;
469 wFrameWindowPaint(fwin);
473 static void
474 updateTitlebar(WFrameWindow *fwin)
476 int x, w;
477 int theight;
479 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
481 x = 0;
482 w = fwin->core->width + 1;
484 if (wPreferences.new_style) {
485 if (fwin->flags.hide_left_button || !fwin->left_button
486 || fwin->flags.lbutton_dont_fit) {
487 x = 0;
488 #ifdef XKB_BUTTON_HINT
489 if(fwin->language_button)
490 wCoreConfigure(fwin->language_button, 0, 0,
491 fwin->language_button->width,
492 fwin->language_button->width);
493 #endif
494 } else {
495 #ifdef XKB_BUTTON_HINT
496 if(fwin->language_button)
497 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
498 fwin->language_button->width,
499 fwin->language_button->width);
500 #endif
501 x = fwin->left_button->width;
502 w -= fwin->left_button->width;
504 #ifdef XKB_BUTTON_HINT
505 if (fwin->flags.hide_language_button || !fwin->language_button
506 || fwin->flags.languagebutton_dont_fit) {
507 } else {
508 x += fwin->language_button->width;
509 w -= fwin->language_button->width;
511 #endif
513 #ifdef XKB_BUTTON_HINT
514 else {
515 int bsize = theight - 7;
516 if (fwin->flags.hide_left_button || !fwin->left_button
517 || fwin->flags.lbutton_dont_fit) {
518 if(fwin->language_button)
519 wCoreConfigure(fwin->language_button, 3, (theight-bsize)/2,
520 fwin->language_button->width,
521 fwin->language_button->width);
523 else {
524 if(fwin->language_button)
525 wCoreConfigure(fwin->language_button,
526 6 + fwin->left_button->width, (theight-bsize)/2,
527 fwin->language_button->width,
528 fwin->language_button->width);
531 #endif
533 if (wPreferences.new_style) {
534 if (!fwin->flags.hide_right_button && fwin->right_button
535 && !fwin->flags.rbutton_dont_fit) {
536 w -= fwin->right_button->width;
540 if (wPreferences.new_style || fwin->titlebar->width!=w)
541 fwin->flags.need_texture_remake = 1;
543 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
547 void
548 wFrameWindowHideButton(WFrameWindow *fwin, int flags)
550 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
551 XUnmapWindow(dpy, fwin->right_button->window);
552 fwin->flags.hide_right_button = 1;
555 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
556 XUnmapWindow(dpy, fwin->left_button->window);
557 fwin->flags.hide_left_button = 1;
560 #ifdef XKB_BUTTON_HINT
561 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
562 XUnmapWindow(dpy, fwin->language_button->window);
563 fwin->flags.hide_language_button = 1;
565 #endif
567 if (fwin->titlebar) {
568 if (wPreferences.new_style) {
569 updateTitlebar(fwin);
570 } else {
571 #ifdef XKB_BUTTON_HINT
572 updateTitlebar(fwin);
573 #else
574 XClearWindow(dpy, fwin->titlebar->window);
575 wFrameWindowPaint(fwin);
576 #endif
578 checkTitleSize(fwin);
583 void
584 wFrameWindowShowButton(WFrameWindow *fwin, int flags)
586 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button
587 && fwin->flags.hide_right_button) {
589 if (!fwin->flags.rbutton_dont_fit)
590 XMapWindow(dpy, fwin->right_button->window);
592 fwin->flags.hide_right_button = 0;
595 #ifdef XKB_BUTTON_HINT
596 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button
597 && fwin->flags.hide_language_button) {
599 if (!fwin->flags.languagebutton_dont_fit)
600 XMapWindow(dpy, fwin->language_button->window);
602 fwin->flags.hide_language_button = 0;
604 #endif
606 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button
607 && fwin->flags.hide_left_button) {
609 if (!fwin->flags.lbutton_dont_fit)
610 XMapWindow(dpy, fwin->left_button->window);
612 fwin->flags.hide_left_button = 0;
616 if (fwin->titlebar) {
617 if (wPreferences.new_style) {
618 updateTitlebar(fwin);
619 } else {
620 XClearWindow(dpy, fwin->titlebar->window);
621 wFrameWindowPaint(fwin);
623 checkTitleSize(fwin);
628 static void
629 #ifdef XKB_BUTTON_HINT
630 renderTexture(WScreen *scr, WTexture *texture, int width, int height,
631 int bwidth, int bheight, int left, int language, int right,
632 Pixmap *title, Pixmap *lbutton, Pixmap *languagebutton, Pixmap *rbutton)
633 #else
634 renderTexture(WScreen *scr, WTexture *texture, int width, int height,
635 int bwidth, int bheight, int left, int right,
636 Pixmap *title, Pixmap *lbutton, Pixmap *rbutton)
637 #endif
639 RImage *img;
640 RImage *limg, *rimg, *mimg;
641 #ifdef XKB_BUTTON_HINT
642 RImage *timg;
643 #endif
644 int x, w;
646 *title = None;
647 *lbutton = None;
648 *rbutton = None;
649 #ifdef XKB_BUTTON_HINT
650 *languagebutton = None;
651 #endif
653 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
654 if (!img) {
655 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
656 return;
659 if (wPreferences.new_style) {
660 if (left) {
661 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
662 } else
663 limg = NULL;
665 x = 0;
666 w = img->width;
668 #ifdef XKB_BUTTON_HINT
669 if (language) {
670 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
671 } else
672 timg = NULL;
673 #endif
675 if (limg) {
676 RBevelImage(limg, RBEV_RAISED2);
677 if (!RConvertImage(scr->rcontext, limg, lbutton)) {
678 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
680 x += limg->width;
681 w -= limg->width;
682 RDestroyImage(limg);
685 #ifdef XKB_BUTTON_HINT
686 if (timg) {
687 RBevelImage(timg, RBEV_RAISED2);
688 if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
689 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
691 x += timg->width;
692 w -= timg->width;
693 RDestroyImage(timg);
695 #endif
697 if (right) {
698 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
699 } else
700 rimg = NULL;
702 if (rimg) {
703 RBevelImage(rimg, RBEV_RAISED2);
704 if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
705 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
707 w -= rimg->width;
708 RDestroyImage(rimg);
711 if (w!=width) {
712 mimg = RGetSubImage(img, x, 0, w, img->height);
713 RBevelImage(mimg, RBEV_RAISED2);
715 if (!RConvertImage(scr->rcontext, mimg, title)) {
716 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
718 RDestroyImage(mimg);
719 } else {
720 RBevelImage(img, RBEV_RAISED2);
722 if (!RConvertImage(scr->rcontext, img, title)) {
723 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
726 } else {
727 RBevelImage(img, RBEV_RAISED2);
729 if (!RConvertImage(scr->rcontext, img, title)) {
730 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
734 RDestroyImage(img);
738 static void
739 renderResizebarTexture(WScreen *scr, WTexture *texture, int width, int height,
740 int cwidth, Pixmap *pmap)
742 RImage *img;
743 RColor light;
744 RColor dark;
746 *pmap = None;
748 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
749 if (!img) {
750 wwarning(_("could not render texture: %s"),
751 RMessageForError(RErrorCode));
752 return;
755 light.alpha = 0;
756 light.red = light.green = light.blue = 80;
758 dark.alpha = 0;
759 dark.red = dark.green = dark.blue = 40;
761 ROperateLine(img, RSubtractOperation, 0, 0, width-1, 0, &dark);
762 ROperateLine(img, RAddOperation, 0, 1, width-1, 1, &light);
764 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height-1, &dark);
765 ROperateLine(img, RAddOperation, cwidth+1, 2, cwidth+1, height-1, &light);
767 if (width > 1)
768 ROperateLine(img, RSubtractOperation, width-cwidth-2, 2,
769 width-cwidth-2, height-1, &dark);
770 ROperateLine(img, RAddOperation, width-cwidth-1, 2, width-cwidth-1,
771 height-1, &light);
773 #ifdef SHADOW_RESIZEBAR
774 ROperateLine(img, RAddOperation, 0, 1, 0, height-1, &light);
775 ROperateLine(img, RSubtractOperation, width-1, 1, width-1, height-1,
776 &dark);
777 ROperateLine(img, RSubtractOperation, 0, height-1, width-1, height-1,
778 &dark);
779 #endif /* SHADOW_RESIZEBAR */
782 if (!RConvertImage(scr->rcontext, img, pmap)) {
783 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
786 RDestroyImage(img);
791 static void
792 updateTexture(WFrameWindow *fwin)
794 int i;
795 unsigned long pixel;
797 i = fwin->flags.state;
798 if (fwin->titlebar) {
799 if (fwin->title_texture[i]->any.type!=WTEX_SOLID) {
800 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window,
801 fwin->title_back[i]);
802 if (wPreferences.new_style) {
803 if (fwin->left_button && fwin->lbutton_back[i])
804 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
805 fwin->lbutton_back[i]);
807 #ifdef XKB_BUTTON_HINT
808 if (fwin->language_button && fwin->languagebutton_back[i]) {
809 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
810 fwin->languagebutton_back[i]);
812 #endif
814 if (fwin->right_button && fwin->rbutton_back[i])
815 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
816 fwin->rbutton_back[i]);
818 } else {
819 pixel = fwin->title_texture[i]->solid.normal.pixel;
820 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
821 if (wPreferences.new_style) {
822 if (fwin->left_button)
823 XSetWindowBackground(dpy, fwin->left_button->window,
824 pixel);
825 #ifdef XKB_BUTTON_HINT
826 if (fwin->language_button)
827 XSetWindowBackground(dpy, fwin->language_button->window,
828 pixel);
829 #endif
830 if (fwin->right_button)
831 XSetWindowBackground(dpy, fwin->right_button->window,
832 pixel);
835 XClearWindow(dpy, fwin->titlebar->window);
837 if (fwin->left_button) {
838 XClearWindow(dpy, fwin->left_button->window);
839 handleButtonExpose(&fwin->left_button->descriptor, NULL);
841 #ifdef XKB_BUTTON_HINT
842 if (fwin->language_button) {
843 XClearWindow(dpy, fwin->language_button->window);
844 handleButtonExpose(&fwin->language_button->descriptor, NULL);
846 #endif
847 if (fwin->right_button) {
848 XClearWindow(dpy, fwin->right_button->window);
849 handleButtonExpose(&fwin->right_button->descriptor, NULL);
856 static void
857 remakeTexture(WFrameWindow *fwin, int state)
859 Pixmap pmap, lpmap, rpmap;
860 #ifdef XKB_BUTTON_HINT
861 Pixmap tpmap;
862 #endif
864 if (fwin->title_texture[state] && fwin->titlebar) {
865 FREE_PIXMAP(fwin->title_back[state]);
866 if (wPreferences.new_style) {
867 FREE_PIXMAP(fwin->lbutton_back[state]);
868 FREE_PIXMAP(fwin->rbutton_back[state]);
869 #ifdef XKB_BUTTON_HINT
870 FREE_PIXMAP(fwin->languagebutton_back[state]);
871 #endif
874 if (fwin->title_texture[state]->any.type!=WTEX_SOLID) {
875 int left, right;
876 #ifdef XKB_BUTTON_HINT
877 int language;
878 #endif
879 int width;
881 /* eventually surrounded by if new_style */
882 left = fwin->left_button && !fwin->flags.hide_left_button
883 && !fwin->flags.lbutton_dont_fit;
884 #ifdef XKB_BUTTON_HINT
885 language = fwin->language_button && !fwin->flags.hide_language_button
886 && !fwin->flags.languagebutton_dont_fit;
887 #endif
888 right = fwin->right_button && !fwin->flags.hide_right_button
889 && !fwin->flags.rbutton_dont_fit;
891 width = fwin->core->width+1;
893 #ifdef XKB_BUTTON_HINT
894 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
895 width, fwin->titlebar->height,
896 fwin->titlebar->height, fwin->titlebar->height,
897 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
898 #else
899 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
900 width, fwin->titlebar->height,
901 fwin->titlebar->height, fwin->titlebar->height,
902 left, right, &pmap, &lpmap, &rpmap);
903 #endif
905 fwin->title_back[state] = pmap;
906 if (wPreferences.new_style) {
907 fwin->lbutton_back[state] = lpmap;
908 fwin->rbutton_back[state] = rpmap;
909 #ifdef XKB_BUTTON_HINT
910 fwin->languagebutton_back[state] = tpmap;
911 #endif
915 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
916 && fwin->resizebar && state == 0) {
918 FREE_PIXMAP(fwin->resizebar_back[0]);
920 if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
922 renderResizebarTexture(fwin->screen_ptr,
923 fwin->resizebar_texture[0],
924 fwin->resizebar->width,
925 fwin->resizebar->height,
926 fwin->resizebar_corner_width,
927 &pmap);
929 fwin->resizebar_back[0] = pmap;
932 /* this part should be in updateTexture() */
933 if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
934 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window,
935 fwin->resizebar_back[0]);
936 } else {
937 XSetWindowBackground(dpy, fwin->resizebar->window,
938 fwin->resizebar_texture[0]->solid.normal.pixel);
940 XClearWindow(dpy, fwin->resizebar->window);
945 void
946 wFrameWindowPaint(WFrameWindow *fwin)
948 WScreen *scr = fwin->screen_ptr;
950 if (fwin->flags.is_client_window_frame)
951 fwin->flags.justification = wPreferences.title_justification;
953 if (fwin->flags.need_texture_remake) {
954 int i;
956 fwin->flags.need_texture_remake = 0;
957 fwin->flags.need_texture_change = 0;
959 if (fwin->flags.single_texture) {
960 remakeTexture(fwin, 0);
961 updateTexture(fwin);
962 } else {
963 /* first render the texture for the current state... */
964 remakeTexture(fwin, fwin->flags.state);
965 /* ... and paint it */
966 updateTexture(fwin);
968 for (i=0; i < 3; i++) {
969 if (i!=fwin->flags.state)
970 remakeTexture(fwin, i);
975 if (fwin->flags.need_texture_change) {
976 fwin->flags.need_texture_change = 0;
978 updateTexture(fwin);
981 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
982 && fwin->title_texture[fwin->flags.state]->any.type==WTEX_SOLID) {
983 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
984 fwin->titlebar->height,
985 (WTexSolid*)fwin->title_texture[fwin->flags.state],
986 WREL_RAISED);
989 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
990 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
991 Window win;
992 int w, h;
993 int cw;
994 GC light_gc, dim_gc;
995 WTexSolid *texture = (WTexSolid*)fwin->resizebar_texture[0];
997 w = fwin->resizebar->width;
998 h = fwin->resizebar->height;
999 cw = fwin->resizebar_corner_width;
1000 light_gc = texture->light_gc;
1001 dim_gc = texture->dim_gc;
1002 win = fwin->resizebar->window;
1004 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
1005 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
1007 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
1008 XDrawLine(dpy, win, light_gc, cw+1, 2, cw+1, h);
1010 XDrawLine(dpy, win, dim_gc, w-cw-2, 2, w-cw-2, h);
1011 XDrawLine(dpy, win, light_gc, w-cw-1, 2, w-cw-1, h);
1013 #ifdef SHADOW_RESIZEBAR
1014 XDrawLine(dpy, win, light_gc, 0, 1, 0, h-1);
1015 XDrawLine(dpy, win, dim_gc, w-1, 2, w-1, h-1);
1016 XDrawLine(dpy, win, dim_gc, 1, h-1, cw, h-1);
1017 XDrawLine(dpy, win, dim_gc, cw+2, h-1, w-cw-2, h-1);
1018 XDrawLine(dpy, win, dim_gc, w-cw, h-1, w-1, h-1);
1019 #endif /* SHADOW_RESIZEBAR */
1023 if (fwin->title && fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
1024 int x, w;
1025 int lofs = 6, rofs = 6;
1026 int titlelen;
1027 char *title;
1028 int allButtons = 1;
1031 if (!wPreferences.new_style) {
1032 if (fwin->left_button && !fwin->flags.hide_left_button
1033 && !fwin->flags.lbutton_dont_fit)
1034 lofs += fwin->left_button->width + 3;
1035 else
1036 allButtons = 0;
1038 #ifdef XKB_BUTTON_HINT
1039 if (fwin->language_button && !fwin->flags.hide_language_button
1040 && !fwin->flags.languagebutton_dont_fit)
1041 lofs += fwin->language_button->width;
1042 else
1043 allButtons = 0;
1044 #endif
1046 if (fwin->right_button && !fwin->flags.hide_right_button
1047 && !fwin->flags.rbutton_dont_fit)
1048 rofs += fwin->right_button->width + 3;
1049 else
1050 allButtons = 0;
1053 #ifdef XKB_BUTTON_HINT
1054 fwin->languagebutton_image =
1055 scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1056 #endif
1058 title = ShrinkString(*fwin->font, fwin->title,
1059 fwin->titlebar->width - lofs - rofs);
1060 titlelen = strlen(title);
1061 w = WMWidthOfString(*fwin->font, title, titlelen);
1063 switch (fwin->flags.justification) {
1064 case WTJ_LEFT:
1065 x = lofs;
1066 break;
1068 case WTJ_RIGHT:
1069 x = fwin->titlebar->width - w - rofs;
1070 break;
1072 default:
1073 if (!allButtons)
1074 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1075 else
1076 x = (fwin->titlebar->width - w) / 2;
1077 break;
1081 XSetForeground(dpy, *fwin->title_gc,
1082 fwin->title_pixel[fwin->flags.state]);
1084 #ifdef DRAWSTRING_PLUGIN
1085 if (scr->drawstring_func[fwin->flags.state + fwin->drawstring_proc_offset]) {
1086 scr->drawstring_func[fwin->flags.state + fwin->drawstring_proc_offset]->
1087 proc.drawString(scr->drawstring_func[fwin->flags.state
1088 + fwin->drawstring_proc_offset]->arg,
1089 fwin->titlebar->window, *fwin->title_gc,
1090 *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE,
1091 fwin->titlebar->width, fwin->top_width, title, titlelen);
1092 } else {
1093 WMDrawString(scr->wmscreen, fwin->titlebar->window,
1094 *fwin->title_gc, *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE,
1095 title, titlelen);
1097 #else
1098 WMDrawString(scr->wmscreen, fwin->titlebar->window,
1099 *fwin->title_gc, *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE,
1100 title, titlelen);
1101 #endif /* DRAWSTRING_PLUGIN */
1103 free(title);
1105 if (fwin->left_button)
1106 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1107 if (fwin->right_button)
1108 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1109 #ifdef XKB_BUTTON_HINT
1110 if (fwin->language_button)
1111 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1112 #endif
1117 static void
1118 reconfigure(WFrameWindow *fwin, int x, int y, int width, int height,
1119 Bool dontMove)
1121 int k = (wPreferences.new_style ? 4 : 3);
1122 int resizedHorizontally = 0;
1124 if (dontMove)
1125 XResizeWindow(dpy, fwin->core->window, width, height);
1126 else
1127 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1130 if (fwin->core->height != height && fwin->resizebar)
1131 XMoveWindow(dpy, fwin->resizebar->window, 0,
1132 height - fwin->resizebar->height);
1134 if (fwin->core->width != width) {
1135 fwin->flags.need_texture_remake = 1;
1136 resizedHorizontally = 1;
1139 fwin->core->width = width;
1140 fwin->core->height = height;
1142 if (fwin->titlebar && resizedHorizontally) {
1143 /* Check if the titlebar is wide enough to hold the buttons.
1144 * Temporarily remove them if can't
1146 if (fwin->left_button) {
1147 if (width < fwin->top_width*k && !fwin->flags.lbutton_dont_fit) {
1149 if (!fwin->flags.hide_left_button) {
1150 XUnmapWindow(dpy, fwin->left_button->window);
1152 fwin->flags.lbutton_dont_fit = 1;
1153 } else if (width >= fwin->top_width*k && fwin->flags.lbutton_dont_fit) {
1155 if (!fwin->flags.hide_left_button) {
1156 XMapWindow(dpy, fwin->left_button->window);
1158 fwin->flags.lbutton_dont_fit = 0;
1162 #ifdef XKB_BUTTON_HINT
1163 if (fwin->language_button) {
1164 if (width < fwin->top_width*k && !fwin->flags.languagebutton_dont_fit) {
1166 if (!fwin->flags.hide_language_button) {
1167 XUnmapWindow(dpy, fwin->language_button->window);
1169 fwin->flags.languagebutton_dont_fit = 1;
1170 } else if (width >= fwin->top_width*k && fwin->flags.languagebutton_dont_fit) {
1172 if (!fwin->flags.hide_language_button) {
1173 XMapWindow(dpy, fwin->language_button->window);
1175 fwin->flags.languagebutton_dont_fit = 0;
1178 #endif
1180 if (fwin->right_button) {
1181 if (width < fwin->top_width*2 && !fwin->flags.rbutton_dont_fit) {
1183 if (!fwin->flags.hide_right_button) {
1184 XUnmapWindow(dpy, fwin->right_button->window);
1186 fwin->flags.rbutton_dont_fit = 1;
1187 } else if (width >= fwin->top_width*2 && fwin->flags.rbutton_dont_fit) {
1189 if (!fwin->flags.hide_right_button) {
1190 XMapWindow(dpy, fwin->right_button->window);
1192 fwin->flags.rbutton_dont_fit = 0;
1196 if (wPreferences.new_style) {
1197 if (fwin->right_button)
1198 XMoveWindow(dpy, fwin->right_button->window,
1199 width - fwin->right_button->width + 1, 0);
1200 } else {
1201 if (fwin->right_button)
1202 XMoveWindow(dpy, fwin->right_button->window,
1203 width - fwin->right_button->width - 3,
1204 (fwin->titlebar->height - fwin->right_button->height)/2);
1206 updateTitlebar(fwin);
1207 checkTitleSize(fwin);
1210 if (fwin->resizebar) {
1211 wCoreConfigure(fwin->resizebar, 0,
1212 fwin->core->height - fwin->resizebar->height,
1213 fwin->core->width, fwin->resizebar->height);
1215 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1216 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
1217 fwin->resizebar_corner_width = fwin->core->width/2;
1222 void
1223 wFrameWindowConfigure(WFrameWindow *fwin, int x, int y, int width, int height)
1225 reconfigure(fwin, x, y, width, height, False);
1228 void
1229 wFrameWindowResize(WFrameWindow *fwin, int width, int height)
1231 reconfigure(fwin, 0, 0, width, height, True);
1236 int
1237 wFrameWindowChangeTitle(WFrameWindow *fwin, char *new_title)
1239 /* check if the title is the same as before */
1240 if (fwin->title) {
1241 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1242 return 0;
1244 } else {
1245 if (!new_title)
1246 return 0;
1249 if (fwin->title)
1250 free(fwin->title);
1252 fwin->title = wstrdup(new_title);
1254 if (fwin->titlebar) {
1255 XClearWindow(dpy, fwin->titlebar->window);
1257 wFrameWindowPaint(fwin);
1259 checkTitleSize(fwin);
1261 return 1;
1265 #ifdef OLWM_HINTS
1266 void
1267 wFrameWindowUpdatePushButton(WFrameWindow *fwin, Bool pushed)
1269 fwin->flags.right_button_pushed_in = pushed;
1271 paintButton(fwin->right_button, fwin->title_texture[fwin->flags.state],
1272 fwin->title_pixel[fwin->flags.state],
1273 fwin->rbutton_image, pushed);
1275 #endif /* OLWM_HINTS */
1278 #ifdef XKB_BUTTON_HINT
1279 void
1280 wFrameWindowUpdateLanguageButton(WFrameWindow *fwin)
1282 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1283 fwin->title_pixel[fwin->flags.state],
1284 fwin->languagebutton_image, True);
1286 #endif /* XKB_BUTTON_HINT */
1289 /*********************************************************************/
1291 static void
1292 handleExpose(WObjDescriptor *desc, XEvent *event)
1294 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1297 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1298 fwin->flags.repaint_only_titlebar = 1;
1299 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1300 fwin->flags.repaint_only_resizebar = 1;
1301 wFrameWindowPaint(fwin);
1302 fwin->flags.repaint_only_titlebar = 0;
1303 fwin->flags.repaint_only_resizebar = 0;
1307 static void
1308 checkTitleSize(WFrameWindow *fwin)
1310 int width;
1312 if (!fwin->title) {
1313 fwin->flags.incomplete_title = 0;
1314 return;
1317 if (!fwin->titlebar) {
1318 fwin->flags.incomplete_title = 1;
1319 return;
1320 } else {
1321 width = fwin->titlebar->width - 6 - 6;
1324 if (!wPreferences.new_style) {
1325 if (fwin->left_button && !fwin->flags.hide_left_button
1326 && !fwin->flags.lbutton_dont_fit)
1327 width -= fwin->left_button->width + 3;
1329 #ifdef XKB_BUTTON_HINT
1330 if (fwin->language_button && !fwin->flags.hide_language_button
1331 && !fwin->flags.languagebutton_dont_fit)
1332 width -= fwin->language_button->width + 3;
1333 #endif
1335 if (fwin->right_button && !fwin->flags.hide_right_button
1336 && !fwin->flags.rbutton_dont_fit)
1337 width -= fwin->right_button->width + 3;
1339 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1340 fwin->flags.incomplete_title = 1;
1341 } else {
1342 fwin->flags.incomplete_title = 0;
1347 static void
1348 paintButton(WCoreWindow *button, WTexture *texture, unsigned long color,
1349 WPixmap *image, int pushed)
1351 WScreen *scr = button->screen_ptr;
1352 GC copy_gc = scr->copy_gc;
1353 int x=0, y=0, d=0;
1354 int left=0, width=0;
1356 /* setup stuff according to the state */
1357 if (pushed) {
1358 if (image) {
1359 if (image->width>=image->height*2) {
1360 /* the image contains 2 pictures: the second is for the
1361 * pushed state */
1362 width = image->width/2;
1363 left = image->width/2;
1364 } else {
1365 width = image->width;
1368 XSetClipMask(dpy, copy_gc, None);
1369 XSetForeground(dpy, copy_gc, scr->white_pixel);
1370 d=1;
1371 if (wPreferences.new_style) {
1372 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1373 button->width-1, button->height-1);
1374 XSetForeground(dpy, copy_gc, scr->black_pixel);
1375 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1376 button->width-1, button->height-1);
1377 } else {
1378 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1379 button->width, button->height);
1380 XSetForeground(dpy, copy_gc, scr->black_pixel);
1381 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1382 button->width, button->height);
1384 } else {
1385 XClearWindow(dpy, button->window);
1387 if (image) {
1388 if (image->width>=image->height*2)
1389 width = image->width/2;
1390 else
1391 width = image->width;
1393 d=0;
1395 if (wPreferences.new_style) {
1396 if (texture->any.type==WTEX_SOLID || pushed) {
1397 wDrawBevel(button->window, button->width, button->height,
1398 (WTexSolid*)texture, WREL_RAISED);
1400 } else {
1401 wDrawBevel(button->window, button->width, button->height,
1402 scr->widget_texture, WREL_RAISED);
1406 if (image) {
1407 /* display image */
1408 XSetClipMask(dpy, copy_gc, image->mask);
1409 x = (button->width - width)/2 + d;
1410 y = (button->height - image->height)/2 + d;
1411 XSetClipOrigin(dpy, copy_gc, x-left, y);
1412 if (!wPreferences.new_style) {
1413 XSetForeground(dpy, copy_gc, scr->black_pixel);
1414 if (!pushed) {
1415 if (image->depth==1)
1416 XCopyPlane(dpy, image->image, button->window, copy_gc,
1417 left, 0, width, image->height, x, y, 1);
1418 else
1419 XCopyArea(dpy, image->image, button->window, copy_gc,
1420 left, 0, width, image->height, x, y);
1421 } else {
1422 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1423 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1424 button->width, button->height);
1426 } else {
1427 if (pushed) {
1428 XSetForeground(dpy, copy_gc, scr->black_pixel);
1429 } else {
1430 XSetForeground(dpy, copy_gc, color);
1431 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1433 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1434 button->width, button->height);
1440 static void
1441 handleButtonExpose(WObjDescriptor *desc, XEvent *event)
1443 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1444 WCoreWindow *button = (WCoreWindow*)desc->self;
1446 #ifdef XKB_BUTTON_HINT
1447 if (button == fwin->language_button) {
1448 if (wPreferences.modelock){
1449 paintButton(button, fwin->title_texture[fwin->flags.state],
1450 fwin->title_pixel[fwin->flags.state],
1451 fwin->languagebutton_image, False);
1453 } else
1454 #endif
1455 if (button == fwin->left_button) {
1456 paintButton(button, fwin->title_texture[fwin->flags.state],
1457 fwin->title_pixel[fwin->flags.state],
1458 fwin->lbutton_image, False);
1459 } else {
1460 Bool pushed = False;
1462 #ifdef OLWM_HINTS
1463 if (fwin->flags.right_button_pushed_in)
1464 pushed = True;
1465 #endif
1466 /* emulate the olwm pushpin in the "out" state */
1467 paintButton(button, fwin->title_texture[fwin->flags.state],
1468 fwin->title_pixel[fwin->flags.state],
1469 fwin->rbutton_image, pushed);
1474 static void
1475 titlebarMouseDown(WObjDescriptor *desc, XEvent *event)
1477 WFrameWindow *fwin = desc->parent;
1478 WCoreWindow *titlebar = desc->self;
1480 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1481 if (fwin->on_dblclick_titlebar)
1482 (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event);
1483 } else {
1484 if (fwin->on_mousedown_titlebar)
1485 (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event);
1490 static void
1491 resizebarMouseDown(WObjDescriptor *desc, XEvent *event)
1493 WFrameWindow *fwin = desc->parent;
1494 WCoreWindow *resizebar = desc->self;
1496 if (fwin->on_mousedown_resizebar)
1497 (*fwin->on_mousedown_resizebar)(resizebar, fwin->child, event);
1501 static void
1502 buttonMouseDown(WObjDescriptor *desc, XEvent *event)
1504 WFrameWindow *fwin = desc->parent;
1505 WCoreWindow *button = desc->self;
1506 WPixmap *image;
1507 XEvent ev;
1508 int done=0, execute=1;
1509 WTexture *texture;
1510 unsigned long pixel;
1511 int clickButton = event->xbutton.button;
1513 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1514 if (button == fwin->right_button && fwin->on_dblclick_right) {
1515 (*fwin->on_dblclick_right)(button, fwin->child, event);
1517 return;
1520 if (button == fwin->left_button) {
1521 image = fwin->lbutton_image;
1522 } else {
1523 image = fwin->rbutton_image;
1525 #ifdef XKB_BUTTON_HINT
1526 if (button == fwin->language_button) {
1527 if (!wPreferences.modelock) return;
1528 image = fwin->languagebutton_image;
1530 #endif
1532 pixel = fwin->title_pixel[fwin->flags.state];
1533 texture = fwin->title_texture[fwin->flags.state];
1534 paintButton(button, texture, pixel, image, True);
1536 while (!done) {
1537 WMMaskEvent(dpy, LeaveWindowMask|EnterWindowMask|ButtonReleaseMask
1538 |ButtonPressMask|ExposureMask, &ev);
1539 switch (ev.type) {
1540 case LeaveNotify:
1541 execute = 0;
1542 paintButton(button, texture, pixel, image, False);
1543 break;
1545 case EnterNotify:
1546 execute = 1;
1547 paintButton(button, texture, pixel, image, True);
1548 break;
1550 case ButtonPress:
1551 break;
1553 case ButtonRelease:
1554 if (ev.xbutton.button == clickButton)
1555 done = 1;
1556 break;
1558 default:
1559 WMHandleEvent(&ev);
1562 paintButton(button, texture, pixel, image, False);
1564 if (execute) {
1565 if (button == fwin->left_button) {
1566 if (fwin->on_click_left)
1567 (*fwin->on_click_left)(button, fwin->child, &ev);
1568 } else if (button == fwin->right_button) {
1569 if (fwin->on_click_right)
1570 (*fwin->on_click_right)(button, fwin->child, &ev);
1572 #ifdef XKB_BUTTON_HINT
1573 else if (button == fwin->language_button) {
1574 if (fwin->on_click_language)
1575 (*fwin->on_click_language)(button, fwin->child, &ev);
1577 #endif