fix fix
[wmaker-crm.git] / src / framewin.c
blob67cc36d98a6b0b146371837f8191ef7c3d7fab38
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 Pixmap *background;
951 Pixmap tmp_bg;
952 int tb = fwin->top_width;
953 #endif
955 if (fwin->flags.is_client_window_frame)
956 fwin->flags.justification = wPreferences.title_justification;
958 if (fwin->flags.need_texture_remake) {
959 int i;
961 fwin->flags.need_texture_remake = 0;
962 fwin->flags.need_texture_change = 0;
964 if (fwin->flags.single_texture) {
965 remakeTexture(fwin, 0);
966 updateTexture(fwin);
967 } else {
968 /* first render the texture for the current state... */
969 remakeTexture(fwin, fwin->flags.state);
970 /* ... and paint it */
971 updateTexture(fwin);
973 for (i=0; i < 3; i++) {
974 if (i!=fwin->flags.state)
975 remakeTexture(fwin, i);
980 if (fwin->flags.need_texture_change) {
981 fwin->flags.need_texture_change = 0;
983 updateTexture(fwin);
986 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
987 && fwin->title_texture[fwin->flags.state]->any.type==WTEX_SOLID) {
988 #ifdef DRAWSTRING_PLUGIN
989 if (fwin->title) {
990 tmp_bg = XCreatePixmap(dpy, fwin->titlebar->window,
991 fwin->titlebar->width, tb,
992 DefaultDepth(dpy, DefaultScreen(dpy)));
993 XFillRectangle(dpy, tmp_bg, (*fwin->title_texture)->solid.normal_gc,
994 0, 0, fwin->titlebar->width, tb);
995 wDrawBevel(tmp_bg, fwin->titlebar->width,
996 fwin->titlebar->height,
997 (WTexSolid*)fwin->title_texture[fwin->flags.state],
998 WREL_RAISED);
999 background = &tmp_bg;
1000 } else {
1001 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
1002 fwin->titlebar->height,
1003 (WTexSolid*)fwin->title_texture[fwin->flags.state],
1004 WREL_RAISED);
1006 #else
1007 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
1008 fwin->titlebar->height,
1009 (WTexSolid*)fwin->title_texture[fwin->flags.state],
1010 WREL_RAISED);
1011 #endif
1013 #ifdef DRAWSTRING_PLUGIN
1014 else background = &fwin->title_back[fwin->flags.state];
1015 #endif
1017 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
1018 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
1019 Window win;
1020 int w, h;
1021 int cw;
1022 GC light_gc, dim_gc;
1023 WTexSolid *texture = (WTexSolid*)fwin->resizebar_texture[0];
1025 w = fwin->resizebar->width;
1026 h = fwin->resizebar->height;
1027 cw = fwin->resizebar_corner_width;
1028 light_gc = texture->light_gc;
1029 dim_gc = texture->dim_gc;
1030 win = fwin->resizebar->window;
1032 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
1033 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
1035 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
1036 XDrawLine(dpy, win, light_gc, cw+1, 2, cw+1, h);
1038 XDrawLine(dpy, win, dim_gc, w-cw-2, 2, w-cw-2, h);
1039 XDrawLine(dpy, win, light_gc, w-cw-1, 2, w-cw-1, h);
1041 #ifdef SHADOW_RESIZEBAR
1042 XDrawLine(dpy, win, light_gc, 0, 1, 0, h-1);
1043 XDrawLine(dpy, win, dim_gc, w-1, 2, w-1, h-1);
1044 XDrawLine(dpy, win, dim_gc, 1, h-1, cw, h-1);
1045 XDrawLine(dpy, win, dim_gc, cw+2, h-1, w-cw-2, h-1);
1046 XDrawLine(dpy, win, dim_gc, w-cw, h-1, w-1, h-1);
1047 #endif /* SHADOW_RESIZEBAR */
1051 if (fwin->title && fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
1052 int x, w;
1053 int lofs = 6, rofs = 6;
1054 int titlelen;
1055 char *title;
1056 int allButtons = 1;
1059 if (!wPreferences.new_style) {
1060 if (fwin->left_button && !fwin->flags.hide_left_button
1061 && !fwin->flags.lbutton_dont_fit)
1062 lofs += fwin->left_button->width + 3;
1063 else
1064 allButtons = 0;
1066 #ifdef XKB_BUTTON_HINT
1067 if (fwin->language_button && !fwin->flags.hide_language_button
1068 && !fwin->flags.languagebutton_dont_fit)
1069 lofs += fwin->language_button->width;
1070 else
1071 allButtons = 0;
1072 #endif
1074 if (fwin->right_button && !fwin->flags.hide_right_button
1075 && !fwin->flags.rbutton_dont_fit)
1076 rofs += fwin->right_button->width + 3;
1077 else
1078 allButtons = 0;
1081 #ifdef XKB_BUTTON_HINT
1082 fwin->languagebutton_image =
1083 scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1084 #endif
1086 title = ShrinkString(*fwin->font, fwin->title,
1087 fwin->titlebar->width - lofs - rofs);
1088 titlelen = strlen(title);
1089 w = WMWidthOfString(*fwin->font, title, titlelen);
1091 switch (fwin->flags.justification) {
1092 case WTJ_LEFT:
1093 x = lofs;
1094 break;
1096 case WTJ_RIGHT:
1097 x = fwin->titlebar->width - w - rofs;
1098 break;
1100 default:
1101 if (!allButtons)
1102 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1103 else
1104 x = (fwin->titlebar->width - w) / 2;
1105 break;
1108 XSetForeground(dpy, *fwin->title_gc,
1109 fwin->title_pixel[fwin->flags.state]);
1111 #ifdef DRAWSTRING_PLUGIN
1112 #define DRAWSTRING_CURRENT_STATE fwin->flags.state + fwin->drawstring_proc_offset
1113 if (scr->drawstring_func[DRAWSTRING_CURRENT_STATE]) {
1114 void **p;
1116 p = wPluginPackData(6,
1117 /* 0 number of argument, will be passed */
1118 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->data,
1119 /* 1 plugin data, as it was initialized */
1120 background,
1121 /* 2 current background Pixmap */
1122 fwin->title_gc, /* 3 gc */
1123 *fwin->font, /* 4 WMFont** */
1124 &fwin->titlebar->width,
1125 /* 5 suggested width */
1126 &tb /* 6 suggested height */
1128 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->proc.drawString(
1129 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->arg,
1130 fwin->titlebar->window,
1131 x, 0,
1132 fwin->title, strlen(fwin->title), p);
1133 free(p);
1134 } else {
1135 WMDrawString(scr->wmscreen, fwin->titlebar->window,
1136 *fwin->title_gc, *fwin->font,
1137 x, ((signed)fwin->top_width - (signed)WMFontHeight(*fwin->font))/2,
1138 title, titlelen);
1141 if (fwin->title && fwin->title_texture[fwin->flags.state]->any.type==WTEX_SOLID) {
1142 XFreePixmap(dpy, tmp_bg);
1144 #undef DRAWSTRING_CURRENT_STATE
1145 #else
1146 WMDrawString(scr->wmscreen, fwin->titlebar->window,
1147 *fwin->title_gc, *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE,
1148 title, titlelen);
1149 #endif /* DRAWSTRING_PLUGIN */
1151 wfree(title);
1153 if (fwin->left_button)
1154 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1155 if (fwin->right_button)
1156 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1157 #ifdef XKB_BUTTON_HINT
1158 if (fwin->language_button)
1159 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1160 #endif
1165 static void
1166 reconfigure(WFrameWindow *fwin, int x, int y, int width, int height,
1167 Bool dontMove)
1169 int k = (wPreferences.new_style ? 4 : 3);
1170 int resizedHorizontally = 0;
1172 if (dontMove)
1173 XResizeWindow(dpy, fwin->core->window, width, height);
1174 else
1175 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1178 if (fwin->core->height != height && fwin->resizebar)
1179 XMoveWindow(dpy, fwin->resizebar->window, 0,
1180 height - fwin->resizebar->height);
1182 if (fwin->core->width != width) {
1183 fwin->flags.need_texture_remake = 1;
1184 resizedHorizontally = 1;
1187 fwin->core->width = width;
1188 fwin->core->height = height;
1190 if (fwin->titlebar && resizedHorizontally) {
1191 /* Check if the titlebar is wide enough to hold the buttons.
1192 * Temporarily remove them if can't
1194 if (fwin->left_button) {
1195 if (width < fwin->top_width*k && !fwin->flags.lbutton_dont_fit) {
1197 if (!fwin->flags.hide_left_button) {
1198 XUnmapWindow(dpy, fwin->left_button->window);
1200 fwin->flags.lbutton_dont_fit = 1;
1201 } else if (width >= fwin->top_width*k && fwin->flags.lbutton_dont_fit) {
1203 if (!fwin->flags.hide_left_button) {
1204 XMapWindow(dpy, fwin->left_button->window);
1206 fwin->flags.lbutton_dont_fit = 0;
1210 #ifdef XKB_BUTTON_HINT
1211 if (fwin->language_button) {
1212 if (width < fwin->top_width*k && !fwin->flags.languagebutton_dont_fit) {
1214 if (!fwin->flags.hide_language_button) {
1215 XUnmapWindow(dpy, fwin->language_button->window);
1217 fwin->flags.languagebutton_dont_fit = 1;
1218 } else if (width >= fwin->top_width*k && fwin->flags.languagebutton_dont_fit) {
1220 if (!fwin->flags.hide_language_button) {
1221 XMapWindow(dpy, fwin->language_button->window);
1223 fwin->flags.languagebutton_dont_fit = 0;
1226 #endif
1228 if (fwin->right_button) {
1229 if (width < fwin->top_width*2 && !fwin->flags.rbutton_dont_fit) {
1231 if (!fwin->flags.hide_right_button) {
1232 XUnmapWindow(dpy, fwin->right_button->window);
1234 fwin->flags.rbutton_dont_fit = 1;
1235 } else if (width >= fwin->top_width*2 && fwin->flags.rbutton_dont_fit) {
1237 if (!fwin->flags.hide_right_button) {
1238 XMapWindow(dpy, fwin->right_button->window);
1240 fwin->flags.rbutton_dont_fit = 0;
1244 if (wPreferences.new_style) {
1245 if (fwin->right_button)
1246 XMoveWindow(dpy, fwin->right_button->window,
1247 width - fwin->right_button->width + 1, 0);
1248 } else {
1249 if (fwin->right_button)
1250 XMoveWindow(dpy, fwin->right_button->window,
1251 width - fwin->right_button->width - 3,
1252 (fwin->titlebar->height - fwin->right_button->height)/2);
1254 updateTitlebar(fwin);
1255 checkTitleSize(fwin);
1258 if (fwin->resizebar) {
1259 wCoreConfigure(fwin->resizebar, 0,
1260 fwin->core->height - fwin->resizebar->height,
1261 fwin->core->width, fwin->resizebar->height);
1263 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1264 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
1265 fwin->resizebar_corner_width = fwin->core->width/2;
1270 void
1271 wFrameWindowConfigure(WFrameWindow *fwin, int x, int y, int width, int height)
1273 reconfigure(fwin, x, y, width, height, False);
1276 void
1277 wFrameWindowResize(WFrameWindow *fwin, int width, int height)
1279 reconfigure(fwin, 0, 0, width, height, True);
1284 int
1285 wFrameWindowChangeTitle(WFrameWindow *fwin, char *new_title)
1287 /* check if the title is the same as before */
1288 if (fwin->title) {
1289 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1290 return 0;
1292 } else {
1293 if (!new_title)
1294 return 0;
1297 if (fwin->title)
1298 wfree(fwin->title);
1300 fwin->title = wstrdup(new_title);
1302 if (fwin->titlebar) {
1303 XClearWindow(dpy, fwin->titlebar->window);
1305 wFrameWindowPaint(fwin);
1307 checkTitleSize(fwin);
1309 return 1;
1313 #ifdef OLWM_HINTS
1314 void
1315 wFrameWindowUpdatePushButton(WFrameWindow *fwin, Bool pushed)
1317 fwin->flags.right_button_pushed_in = pushed;
1319 paintButton(fwin->right_button, fwin->title_texture[fwin->flags.state],
1320 fwin->title_pixel[fwin->flags.state],
1321 fwin->rbutton_image, pushed);
1323 #endif /* OLWM_HINTS */
1326 #ifdef XKB_BUTTON_HINT
1327 void
1328 wFrameWindowUpdateLanguageButton(WFrameWindow *fwin)
1330 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1331 fwin->title_pixel[fwin->flags.state],
1332 fwin->languagebutton_image, True);
1334 #endif /* XKB_BUTTON_HINT */
1337 /*********************************************************************/
1339 static void
1340 handleExpose(WObjDescriptor *desc, XEvent *event)
1342 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1345 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1346 fwin->flags.repaint_only_titlebar = 1;
1347 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1348 fwin->flags.repaint_only_resizebar = 1;
1349 wFrameWindowPaint(fwin);
1350 fwin->flags.repaint_only_titlebar = 0;
1351 fwin->flags.repaint_only_resizebar = 0;
1355 static void
1356 checkTitleSize(WFrameWindow *fwin)
1358 int width;
1360 if (!fwin->title) {
1361 fwin->flags.incomplete_title = 0;
1362 return;
1365 if (!fwin->titlebar) {
1366 fwin->flags.incomplete_title = 1;
1367 return;
1368 } else {
1369 width = fwin->titlebar->width - 6 - 6;
1372 if (!wPreferences.new_style) {
1373 if (fwin->left_button && !fwin->flags.hide_left_button
1374 && !fwin->flags.lbutton_dont_fit)
1375 width -= fwin->left_button->width + 3;
1377 #ifdef XKB_BUTTON_HINT
1378 if (fwin->language_button && !fwin->flags.hide_language_button
1379 && !fwin->flags.languagebutton_dont_fit)
1380 width -= fwin->language_button->width + 3;
1381 #endif
1383 if (fwin->right_button && !fwin->flags.hide_right_button
1384 && !fwin->flags.rbutton_dont_fit)
1385 width -= fwin->right_button->width + 3;
1387 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1388 fwin->flags.incomplete_title = 1;
1389 } else {
1390 fwin->flags.incomplete_title = 0;
1395 static void
1396 paintButton(WCoreWindow *button, WTexture *texture, unsigned long color,
1397 WPixmap *image, int pushed)
1399 WScreen *scr = button->screen_ptr;
1400 GC copy_gc = scr->copy_gc;
1401 int x=0, y=0, d=0;
1402 int left=0, width=0;
1404 /* setup stuff according to the state */
1405 if (pushed) {
1406 if (image) {
1407 if (image->width>=image->height*2) {
1408 /* the image contains 2 pictures: the second is for the
1409 * pushed state */
1410 width = image->width/2;
1411 left = image->width/2;
1412 } else {
1413 width = image->width;
1416 XSetClipMask(dpy, copy_gc, None);
1417 XSetForeground(dpy, copy_gc, scr->white_pixel);
1418 d=1;
1419 if (wPreferences.new_style) {
1420 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1421 button->width-1, button->height-1);
1422 XSetForeground(dpy, copy_gc, scr->black_pixel);
1423 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1424 button->width-1, button->height-1);
1425 } else {
1426 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1427 button->width, button->height);
1428 XSetForeground(dpy, copy_gc, scr->black_pixel);
1429 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1430 button->width, button->height);
1432 } else {
1433 XClearWindow(dpy, button->window);
1435 if (image) {
1436 if (image->width>=image->height*2)
1437 width = image->width/2;
1438 else
1439 width = image->width;
1441 d=0;
1443 if (wPreferences.new_style) {
1444 if (texture->any.type==WTEX_SOLID || pushed) {
1445 wDrawBevel(button->window, button->width, button->height,
1446 (WTexSolid*)texture, WREL_RAISED);
1448 } else {
1449 wDrawBevel(button->window, button->width, button->height,
1450 scr->widget_texture, WREL_RAISED);
1454 if (image) {
1455 /* display image */
1456 XSetClipMask(dpy, copy_gc, image->mask);
1457 x = (button->width - width)/2 + d;
1458 y = (button->height - image->height)/2 + d;
1459 XSetClipOrigin(dpy, copy_gc, x-left, y);
1460 if (!wPreferences.new_style) {
1461 XSetForeground(dpy, copy_gc, scr->black_pixel);
1462 if (!pushed) {
1463 if (image->depth==1)
1464 XCopyPlane(dpy, image->image, button->window, copy_gc,
1465 left, 0, width, image->height, x, y, 1);
1466 else
1467 XCopyArea(dpy, image->image, button->window, copy_gc,
1468 left, 0, width, image->height, x, y);
1469 } else {
1470 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1471 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1472 button->width, button->height);
1474 } else {
1475 if (pushed) {
1476 XSetForeground(dpy, copy_gc, scr->black_pixel);
1477 } else {
1478 XSetForeground(dpy, copy_gc, color);
1479 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1481 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1482 button->width, button->height);
1488 static void
1489 handleButtonExpose(WObjDescriptor *desc, XEvent *event)
1491 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1492 WCoreWindow *button = (WCoreWindow*)desc->self;
1494 #ifdef XKB_BUTTON_HINT
1495 if (button == fwin->language_button) {
1496 if (wPreferences.modelock){
1497 paintButton(button, fwin->title_texture[fwin->flags.state],
1498 fwin->title_pixel[fwin->flags.state],
1499 fwin->languagebutton_image, False);
1501 } else
1502 #endif
1503 if (button == fwin->left_button) {
1504 paintButton(button, fwin->title_texture[fwin->flags.state],
1505 fwin->title_pixel[fwin->flags.state],
1506 fwin->lbutton_image, False);
1507 } else {
1508 Bool pushed = False;
1510 #ifdef OLWM_HINTS
1511 if (fwin->flags.right_button_pushed_in)
1512 pushed = True;
1513 #endif
1514 /* emulate the olwm pushpin in the "out" state */
1515 paintButton(button, fwin->title_texture[fwin->flags.state],
1516 fwin->title_pixel[fwin->flags.state],
1517 fwin->rbutton_image, pushed);
1522 static void
1523 titlebarMouseDown(WObjDescriptor *desc, XEvent *event)
1525 WFrameWindow *fwin = desc->parent;
1526 WCoreWindow *titlebar = desc->self;
1528 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1529 if (fwin->on_dblclick_titlebar)
1530 (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event);
1531 } else {
1532 if (fwin->on_mousedown_titlebar)
1533 (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event);
1538 static void
1539 resizebarMouseDown(WObjDescriptor *desc, XEvent *event)
1541 WFrameWindow *fwin = desc->parent;
1542 WCoreWindow *resizebar = desc->self;
1544 if (fwin->on_mousedown_resizebar)
1545 (*fwin->on_mousedown_resizebar)(resizebar, fwin->child, event);
1549 static void
1550 buttonMouseDown(WObjDescriptor *desc, XEvent *event)
1552 WFrameWindow *fwin = desc->parent;
1553 WCoreWindow *button = desc->self;
1554 WPixmap *image;
1555 XEvent ev;
1556 int done=0, execute=1;
1557 WTexture *texture;
1558 unsigned long pixel;
1559 int clickButton = event->xbutton.button;
1561 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1562 if (button == fwin->right_button && fwin->on_dblclick_right) {
1563 (*fwin->on_dblclick_right)(button, fwin->child, event);
1565 return;
1568 if (button == fwin->left_button) {
1569 image = fwin->lbutton_image;
1570 } else {
1571 image = fwin->rbutton_image;
1573 #ifdef XKB_BUTTON_HINT
1574 if (button == fwin->language_button) {
1575 if (!wPreferences.modelock) return;
1576 image = fwin->languagebutton_image;
1578 #endif
1580 pixel = fwin->title_pixel[fwin->flags.state];
1581 texture = fwin->title_texture[fwin->flags.state];
1582 paintButton(button, texture, pixel, image, True);
1584 while (!done) {
1585 WMMaskEvent(dpy, LeaveWindowMask|EnterWindowMask|ButtonReleaseMask
1586 |ButtonPressMask|ExposureMask, &ev);
1587 switch (ev.type) {
1588 case LeaveNotify:
1589 execute = 0;
1590 paintButton(button, texture, pixel, image, False);
1591 break;
1593 case EnterNotify:
1594 execute = 1;
1595 paintButton(button, texture, pixel, image, True);
1596 break;
1598 case ButtonPress:
1599 break;
1601 case ButtonRelease:
1602 if (ev.xbutton.button == clickButton)
1603 done = 1;
1604 break;
1606 default:
1607 WMHandleEvent(&ev);
1610 paintButton(button, texture, pixel, image, False);
1612 if (execute) {
1613 if (button == fwin->left_button) {
1614 if (fwin->on_click_left)
1615 (*fwin->on_click_left)(button, fwin->child, &ev);
1616 } else if (button == fwin->right_button) {
1617 if (fwin->on_click_right)
1618 (*fwin->on_click_right)(button, fwin->child, &ev);
1620 #ifdef XKB_BUTTON_HINT
1621 else if (button == fwin->language_button) {
1622 if (fwin->on_click_language)
1623 (*fwin->on_click_language)(button, fwin->child, &ev);
1625 #endif