changes related to plugin system & drawstring
[wmaker-crm.git] / src / framewin.c
blob72d43ad195510e11650e5ff25397e0c7a4912d91
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 wfree(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 wfree(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;
949 #ifdef DRAWSTRING_PLUGIN
950 #define DRAWSTRING_CURRENT_STATE fwin->flags.state + fwin->drawstring_proc_offset
951 Pixmap *background;
952 Pixmap tmp_bg;
953 int tb = fwin->top_width;
954 WPluginData *pd;
955 #endif
957 if (fwin->flags.is_client_window_frame)
958 fwin->flags.justification = wPreferences.title_justification;
960 if (fwin->flags.need_texture_remake) {
961 int i;
963 fwin->flags.need_texture_remake = 0;
964 fwin->flags.need_texture_change = 0;
966 if (fwin->flags.single_texture) {
967 remakeTexture(fwin, 0);
968 updateTexture(fwin);
969 } else {
970 /* first render the texture for the current state... */
971 remakeTexture(fwin, fwin->flags.state);
972 /* ... and paint it */
973 updateTexture(fwin);
975 for (i=0; i < 3; i++) {
976 if (i!=fwin->flags.state)
977 remakeTexture(fwin, i);
982 if (fwin->flags.need_texture_change) {
983 fwin->flags.need_texture_change = 0;
985 updateTexture(fwin);
988 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
989 && fwin->title_texture[fwin->flags.state]->any.type==WTEX_SOLID) {
990 #ifdef DRAWSTRING_PLUGIN
991 if (fwin->title) {
992 tmp_bg = XCreatePixmap(dpy, fwin->titlebar->window,
993 fwin->titlebar->width, tb,
994 DefaultDepth(dpy, DefaultScreen(dpy)));
995 XFillRectangle(dpy, tmp_bg, (*fwin->title_texture)->solid.normal_gc,
996 0, 0, fwin->titlebar->width, tb);
997 wDrawBevel(tmp_bg, fwin->titlebar->width,
998 fwin->titlebar->height,
999 (WTexSolid*)fwin->title_texture[fwin->flags.state],
1000 WREL_RAISED);
1001 background = &tmp_bg;
1002 } else {
1003 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
1004 fwin->titlebar->height,
1005 (WTexSolid*)fwin->title_texture[fwin->flags.state],
1006 WREL_RAISED);
1008 #else
1009 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
1010 fwin->titlebar->height,
1011 (WTexSolid*)fwin->title_texture[fwin->flags.state],
1012 WREL_RAISED);
1013 #endif
1015 #ifdef DRAWSTRING_PLUGIN
1016 else background = &fwin->title_back[fwin->flags.state];
1017 #endif
1019 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
1020 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
1021 Window win;
1022 int w, h;
1023 int cw;
1024 GC light_gc, dim_gc;
1025 WTexSolid *texture = (WTexSolid*)fwin->resizebar_texture[0];
1027 w = fwin->resizebar->width;
1028 h = fwin->resizebar->height;
1029 cw = fwin->resizebar_corner_width;
1030 light_gc = texture->light_gc;
1031 dim_gc = texture->dim_gc;
1032 win = fwin->resizebar->window;
1034 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
1035 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
1037 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
1038 XDrawLine(dpy, win, light_gc, cw+1, 2, cw+1, h);
1040 XDrawLine(dpy, win, dim_gc, w-cw-2, 2, w-cw-2, h);
1041 XDrawLine(dpy, win, light_gc, w-cw-1, 2, w-cw-1, h);
1043 #ifdef SHADOW_RESIZEBAR
1044 XDrawLine(dpy, win, light_gc, 0, 1, 0, h-1);
1045 XDrawLine(dpy, win, dim_gc, w-1, 2, w-1, h-1);
1046 XDrawLine(dpy, win, dim_gc, 1, h-1, cw, h-1);
1047 XDrawLine(dpy, win, dim_gc, cw+2, h-1, w-cw-2, h-1);
1048 XDrawLine(dpy, win, dim_gc, w-cw, h-1, w-1, h-1);
1049 #endif /* SHADOW_RESIZEBAR */
1053 if (fwin->title && fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
1054 int x, w;
1055 int lofs = 6, rofs = 6;
1056 int titlelen;
1057 char *title;
1058 int allButtons = 1;
1061 if (!wPreferences.new_style) {
1062 if (fwin->left_button && !fwin->flags.hide_left_button
1063 && !fwin->flags.lbutton_dont_fit)
1064 lofs += fwin->left_button->width + 3;
1065 else
1066 allButtons = 0;
1068 #ifdef XKB_BUTTON_HINT
1069 if (fwin->language_button && !fwin->flags.hide_language_button
1070 && !fwin->flags.languagebutton_dont_fit)
1071 lofs += fwin->language_button->width;
1072 else
1073 allButtons = 0;
1074 #endif
1076 if (fwin->right_button && !fwin->flags.hide_right_button
1077 && !fwin->flags.rbutton_dont_fit)
1078 rofs += fwin->right_button->width + 3;
1079 else
1080 allButtons = 0;
1083 #ifdef XKB_BUTTON_HINT
1084 fwin->languagebutton_image =
1085 scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1086 #endif
1088 #ifdef DRAWSTRING_PLUGIN
1089 if(scr->drawstring_func[DRAWSTRING_CURRENT_STATE]) {
1090 title = ShrinkString(*fwin->font, fwin->title,
1091 fwin->titlebar->width - lofs - rofs,
1092 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]);
1093 titlelen = strlen(title);
1094 pd = wPluginPackData(1, scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->data);
1095 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->proc.widthOfString[W_DSPROC_WIDTHOFSTRING](
1096 title, titlelen, pd, &w, NULL, NULL);
1097 wfree(pd);
1098 } else {
1099 title = ShrinkString(*fwin->font, fwin->title,
1100 fwin->titlebar->width - lofs - rofs, NULL);
1101 titlelen = strlen(title);
1102 w = WMWidthOfString(*fwin->font, title, titlelen);
1104 #else
1105 title = ShrinkString(*fwin->font, fwin->title,
1106 fwin->titlebar->width - lofs - rofs);
1107 titlelen = strlen(title);
1108 w = WMWidthOfString(*fwin->font, title, titlelen);
1109 #endif
1110 switch (fwin->flags.justification) {
1111 case WTJ_LEFT:
1112 x = lofs;
1113 break;
1115 case WTJ_RIGHT:
1116 x = fwin->titlebar->width - w - rofs;
1117 break;
1119 default:
1120 if (!allButtons)
1121 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1122 else
1123 x = (fwin->titlebar->width - w) / 2;
1124 break;
1127 XSetForeground(dpy, *fwin->title_gc,
1128 fwin->title_pixel[fwin->flags.state]);
1130 #ifdef DRAWSTRING_PLUGIN
1131 /* if the plugin want to do shrinking locally, they can trick
1132 * wmaker by returning a very short value (such as 0) to widthOfString -- I think */
1133 if (scr->drawstring_func[DRAWSTRING_CURRENT_STATE]) {
1134 pd = wPluginPackData(6, /* number of argument, will be passed */
1135 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->data,
1136 /* 0 plugin data, as it was initialized */
1137 background, /* 1 current background Pixmap */
1138 fwin->title_gc, /* 2 gc */
1139 *fwin->font, /* 3 WMFont** */
1140 &fwin->titlebar->width,
1141 /* 4 suggested width */
1142 &tb /* 5 suggested height */
1144 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->proc.drawString[W_DSPROC_DRAWSTRING](
1145 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->arg,
1146 fwin->titlebar->window,
1147 x, 0,
1148 title, strlen(fwin->title), pd);
1149 wfree(pd);
1150 } else {
1151 WMDrawString(scr->wmscreen, fwin->titlebar->window,
1152 *fwin->title_gc, *fwin->font,
1153 x, ((signed)fwin->top_width - (signed)WMFontHeight(*fwin->font))/2,
1154 title, titlelen);
1157 if (fwin->title && fwin->title_texture[fwin->flags.state]->any.type==WTEX_SOLID) {
1158 XFreePixmap(dpy, tmp_bg);
1160 #undef DRAWSTRING_CURRENT_STATE
1161 #else
1162 WMDrawString(scr->wmscreen, fwin->titlebar->window,
1163 *fwin->title_gc, *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE,
1164 title, titlelen);
1165 #endif /* DRAWSTRING_PLUGIN */
1167 wfree(title);
1169 if (fwin->left_button)
1170 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1171 if (fwin->right_button)
1172 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1173 #ifdef XKB_BUTTON_HINT
1174 if (fwin->language_button)
1175 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1176 #endif
1181 static void
1182 reconfigure(WFrameWindow *fwin, int x, int y, int width, int height,
1183 Bool dontMove)
1185 int k = (wPreferences.new_style ? 4 : 3);
1186 int resizedHorizontally = 0;
1188 if (dontMove)
1189 XResizeWindow(dpy, fwin->core->window, width, height);
1190 else
1191 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1194 if (fwin->core->height != height && fwin->resizebar)
1195 XMoveWindow(dpy, fwin->resizebar->window, 0,
1196 height - fwin->resizebar->height);
1198 if (fwin->core->width != width) {
1199 fwin->flags.need_texture_remake = 1;
1200 resizedHorizontally = 1;
1203 fwin->core->width = width;
1204 fwin->core->height = height;
1206 if (fwin->titlebar && resizedHorizontally) {
1207 /* Check if the titlebar is wide enough to hold the buttons.
1208 * Temporarily remove them if can't
1210 if (fwin->left_button) {
1211 if (width < fwin->top_width*k && !fwin->flags.lbutton_dont_fit) {
1213 if (!fwin->flags.hide_left_button) {
1214 XUnmapWindow(dpy, fwin->left_button->window);
1216 fwin->flags.lbutton_dont_fit = 1;
1217 } else if (width >= fwin->top_width*k && fwin->flags.lbutton_dont_fit) {
1219 if (!fwin->flags.hide_left_button) {
1220 XMapWindow(dpy, fwin->left_button->window);
1222 fwin->flags.lbutton_dont_fit = 0;
1226 #ifdef XKB_BUTTON_HINT
1227 if (fwin->language_button) {
1228 if (width < fwin->top_width*k && !fwin->flags.languagebutton_dont_fit) {
1230 if (!fwin->flags.hide_language_button) {
1231 XUnmapWindow(dpy, fwin->language_button->window);
1233 fwin->flags.languagebutton_dont_fit = 1;
1234 } else if (width >= fwin->top_width*k && fwin->flags.languagebutton_dont_fit) {
1236 if (!fwin->flags.hide_language_button) {
1237 XMapWindow(dpy, fwin->language_button->window);
1239 fwin->flags.languagebutton_dont_fit = 0;
1242 #endif
1244 if (fwin->right_button) {
1245 if (width < fwin->top_width*2 && !fwin->flags.rbutton_dont_fit) {
1247 if (!fwin->flags.hide_right_button) {
1248 XUnmapWindow(dpy, fwin->right_button->window);
1250 fwin->flags.rbutton_dont_fit = 1;
1251 } else if (width >= fwin->top_width*2 && fwin->flags.rbutton_dont_fit) {
1253 if (!fwin->flags.hide_right_button) {
1254 XMapWindow(dpy, fwin->right_button->window);
1256 fwin->flags.rbutton_dont_fit = 0;
1260 if (wPreferences.new_style) {
1261 if (fwin->right_button)
1262 XMoveWindow(dpy, fwin->right_button->window,
1263 width - fwin->right_button->width + 1, 0);
1264 } else {
1265 if (fwin->right_button)
1266 XMoveWindow(dpy, fwin->right_button->window,
1267 width - fwin->right_button->width - 3,
1268 (fwin->titlebar->height - fwin->right_button->height)/2);
1270 updateTitlebar(fwin);
1271 checkTitleSize(fwin);
1274 if (fwin->resizebar) {
1275 wCoreConfigure(fwin->resizebar, 0,
1276 fwin->core->height - fwin->resizebar->height,
1277 fwin->core->width, fwin->resizebar->height);
1279 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1280 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
1281 fwin->resizebar_corner_width = fwin->core->width/2;
1286 void
1287 wFrameWindowConfigure(WFrameWindow *fwin, int x, int y, int width, int height)
1289 reconfigure(fwin, x, y, width, height, False);
1292 void
1293 wFrameWindowResize(WFrameWindow *fwin, int width, int height)
1295 reconfigure(fwin, 0, 0, width, height, True);
1300 int
1301 wFrameWindowChangeTitle(WFrameWindow *fwin, char *new_title)
1303 /* check if the title is the same as before */
1304 if (fwin->title) {
1305 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1306 return 0;
1308 } else {
1309 if (!new_title)
1310 return 0;
1313 if (fwin->title)
1314 wfree(fwin->title);
1316 fwin->title = wstrdup(new_title);
1318 if (fwin->titlebar) {
1319 XClearWindow(dpy, fwin->titlebar->window);
1321 wFrameWindowPaint(fwin);
1323 checkTitleSize(fwin);
1325 return 1;
1329 #ifdef OLWM_HINTS
1330 void
1331 wFrameWindowUpdatePushButton(WFrameWindow *fwin, Bool pushed)
1333 fwin->flags.right_button_pushed_in = pushed;
1335 paintButton(fwin->right_button, fwin->title_texture[fwin->flags.state],
1336 fwin->title_pixel[fwin->flags.state],
1337 fwin->rbutton_image, pushed);
1339 #endif /* OLWM_HINTS */
1342 #ifdef XKB_BUTTON_HINT
1343 void
1344 wFrameWindowUpdateLanguageButton(WFrameWindow *fwin)
1346 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1347 fwin->title_pixel[fwin->flags.state],
1348 fwin->languagebutton_image, True);
1350 #endif /* XKB_BUTTON_HINT */
1353 /*********************************************************************/
1355 static void
1356 handleExpose(WObjDescriptor *desc, XEvent *event)
1358 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1361 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1362 fwin->flags.repaint_only_titlebar = 1;
1363 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1364 fwin->flags.repaint_only_resizebar = 1;
1365 wFrameWindowPaint(fwin);
1366 fwin->flags.repaint_only_titlebar = 0;
1367 fwin->flags.repaint_only_resizebar = 0;
1371 static void
1372 checkTitleSize(WFrameWindow *fwin)
1374 int width;
1376 if (!fwin->title) {
1377 fwin->flags.incomplete_title = 0;
1378 return;
1381 if (!fwin->titlebar) {
1382 fwin->flags.incomplete_title = 1;
1383 return;
1384 } else {
1385 width = fwin->titlebar->width - 6 - 6;
1388 if (!wPreferences.new_style) {
1389 if (fwin->left_button && !fwin->flags.hide_left_button
1390 && !fwin->flags.lbutton_dont_fit)
1391 width -= fwin->left_button->width + 3;
1393 #ifdef XKB_BUTTON_HINT
1394 if (fwin->language_button && !fwin->flags.hide_language_button
1395 && !fwin->flags.languagebutton_dont_fit)
1396 width -= fwin->language_button->width + 3;
1397 #endif
1399 if (fwin->right_button && !fwin->flags.hide_right_button
1400 && !fwin->flags.rbutton_dont_fit)
1401 width -= fwin->right_button->width + 3;
1403 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1404 fwin->flags.incomplete_title = 1;
1405 } else {
1406 fwin->flags.incomplete_title = 0;
1411 static void
1412 paintButton(WCoreWindow *button, WTexture *texture, unsigned long color,
1413 WPixmap *image, int pushed)
1415 WScreen *scr = button->screen_ptr;
1416 GC copy_gc = scr->copy_gc;
1417 int x=0, y=0, d=0;
1418 int left=0, width=0;
1420 /* setup stuff according to the state */
1421 if (pushed) {
1422 if (image) {
1423 if (image->width>=image->height*2) {
1424 /* the image contains 2 pictures: the second is for the
1425 * pushed state */
1426 width = image->width/2;
1427 left = image->width/2;
1428 } else {
1429 width = image->width;
1432 XSetClipMask(dpy, copy_gc, None);
1433 XSetForeground(dpy, copy_gc, scr->white_pixel);
1434 d=1;
1435 if (wPreferences.new_style) {
1436 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1437 button->width-1, button->height-1);
1438 XSetForeground(dpy, copy_gc, scr->black_pixel);
1439 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1440 button->width-1, button->height-1);
1441 } else {
1442 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1443 button->width, button->height);
1444 XSetForeground(dpy, copy_gc, scr->black_pixel);
1445 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1446 button->width, button->height);
1448 } else {
1449 XClearWindow(dpy, button->window);
1451 if (image) {
1452 if (image->width>=image->height*2)
1453 width = image->width/2;
1454 else
1455 width = image->width;
1457 d=0;
1459 if (wPreferences.new_style) {
1460 if (texture->any.type==WTEX_SOLID || pushed) {
1461 wDrawBevel(button->window, button->width, button->height,
1462 (WTexSolid*)texture, WREL_RAISED);
1464 } else {
1465 wDrawBevel(button->window, button->width, button->height,
1466 scr->widget_texture, WREL_RAISED);
1470 if (image) {
1471 /* display image */
1472 XSetClipMask(dpy, copy_gc, image->mask);
1473 x = (button->width - width)/2 + d;
1474 y = (button->height - image->height)/2 + d;
1475 XSetClipOrigin(dpy, copy_gc, x-left, y);
1476 if (!wPreferences.new_style) {
1477 XSetForeground(dpy, copy_gc, scr->black_pixel);
1478 if (!pushed) {
1479 if (image->depth==1)
1480 XCopyPlane(dpy, image->image, button->window, copy_gc,
1481 left, 0, width, image->height, x, y, 1);
1482 else
1483 XCopyArea(dpy, image->image, button->window, copy_gc,
1484 left, 0, width, image->height, x, y);
1485 } else {
1486 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1487 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1488 button->width, button->height);
1490 } else {
1491 if (pushed) {
1492 XSetForeground(dpy, copy_gc, scr->black_pixel);
1493 } else {
1494 XSetForeground(dpy, copy_gc, color);
1495 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1497 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1498 button->width, button->height);
1504 static void
1505 handleButtonExpose(WObjDescriptor *desc, XEvent *event)
1507 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1508 WCoreWindow *button = (WCoreWindow*)desc->self;
1510 #ifdef XKB_BUTTON_HINT
1511 if (button == fwin->language_button) {
1512 if (wPreferences.modelock){
1513 paintButton(button, fwin->title_texture[fwin->flags.state],
1514 fwin->title_pixel[fwin->flags.state],
1515 fwin->languagebutton_image, False);
1517 } else
1518 #endif
1519 if (button == fwin->left_button) {
1520 paintButton(button, fwin->title_texture[fwin->flags.state],
1521 fwin->title_pixel[fwin->flags.state],
1522 fwin->lbutton_image, False);
1523 } else {
1524 Bool pushed = False;
1526 #ifdef OLWM_HINTS
1527 if (fwin->flags.right_button_pushed_in)
1528 pushed = True;
1529 #endif
1530 /* emulate the olwm pushpin in the "out" state */
1531 paintButton(button, fwin->title_texture[fwin->flags.state],
1532 fwin->title_pixel[fwin->flags.state],
1533 fwin->rbutton_image, pushed);
1538 static void
1539 titlebarMouseDown(WObjDescriptor *desc, XEvent *event)
1541 WFrameWindow *fwin = desc->parent;
1542 WCoreWindow *titlebar = desc->self;
1544 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1545 if (fwin->on_dblclick_titlebar)
1546 (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event);
1547 } else {
1548 if (fwin->on_mousedown_titlebar)
1549 (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event);
1554 static void
1555 resizebarMouseDown(WObjDescriptor *desc, XEvent *event)
1557 WFrameWindow *fwin = desc->parent;
1558 WCoreWindow *resizebar = desc->self;
1560 if (fwin->on_mousedown_resizebar)
1561 (*fwin->on_mousedown_resizebar)(resizebar, fwin->child, event);
1565 static void
1566 buttonMouseDown(WObjDescriptor *desc, XEvent *event)
1568 WFrameWindow *fwin = desc->parent;
1569 WCoreWindow *button = desc->self;
1570 WPixmap *image;
1571 XEvent ev;
1572 int done=0, execute=1;
1573 WTexture *texture;
1574 unsigned long pixel;
1575 int clickButton = event->xbutton.button;
1577 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1578 if (button == fwin->right_button && fwin->on_dblclick_right) {
1579 (*fwin->on_dblclick_right)(button, fwin->child, event);
1581 return;
1584 if (button == fwin->left_button) {
1585 image = fwin->lbutton_image;
1586 } else {
1587 image = fwin->rbutton_image;
1589 #ifdef XKB_BUTTON_HINT
1590 if (button == fwin->language_button) {
1591 if (!wPreferences.modelock) return;
1592 image = fwin->languagebutton_image;
1594 #endif
1596 pixel = fwin->title_pixel[fwin->flags.state];
1597 texture = fwin->title_texture[fwin->flags.state];
1598 paintButton(button, texture, pixel, image, True);
1600 while (!done) {
1601 WMMaskEvent(dpy, LeaveWindowMask|EnterWindowMask|ButtonReleaseMask
1602 |ButtonPressMask|ExposureMask, &ev);
1603 switch (ev.type) {
1604 case LeaveNotify:
1605 execute = 0;
1606 paintButton(button, texture, pixel, image, False);
1607 break;
1609 case EnterNotify:
1610 execute = 1;
1611 paintButton(button, texture, pixel, image, True);
1612 break;
1614 case ButtonPress:
1615 break;
1617 case ButtonRelease:
1618 if (ev.xbutton.button == clickButton)
1619 done = 1;
1620 break;
1622 default:
1623 WMHandleEvent(&ev);
1626 paintButton(button, texture, pixel, image, False);
1628 if (execute) {
1629 if (button == fwin->left_button) {
1630 if (fwin->on_click_left)
1631 (*fwin->on_click_left)(button, fwin->child, &ev);
1632 } else if (button == fwin->right_button) {
1633 if (fwin->on_click_right)
1634 (*fwin->on_click_right)(button, fwin->child, &ev);
1636 #ifdef XKB_BUTTON_HINT
1637 else if (button == fwin->language_button) {
1638 if (fwin->on_click_language)
1639 (*fwin->on_click_language)(button, fwin->child, &ev);
1641 #endif