pass pixmap to the plugin.
[wmaker-crm.git] / src / framewin.c
blob0ec28d6c9a7240c2b39dc0a39516ec2314638ab4
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;
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 #define DRAWSTRING_CURRENT_STATE fwin->flags.state + fwin->drawstring_proc_offset
1086 if (scr->drawstring_func[DRAWSTRING_CURRENT_STATE]) {
1087 void **p = wPluginPackData(4,
1088 *fwin->title_gc,
1089 *fwin->font,
1090 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->data,
1091 fwin->title_back[fwin->flags.state],
1092 "extendable");
1093 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->proc.drawString(
1094 scr->drawstring_func[DRAWSTRING_CURRENT_STATE]->arg,
1095 fwin->titlebar->window,
1096 x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE,
1097 fwin->titlebar->width, fwin->top_width,
1098 fwin->title, p);
1099 free(p);
1100 } else {
1101 WMDrawString(scr->wmscreen, fwin->titlebar->window,
1102 *fwin->title_gc, *fwin->font,
1103 x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE,
1104 title, titlelen);
1106 #else
1107 WMDrawString(scr->wmscreen, fwin->titlebar->window,
1108 *fwin->title_gc, *fwin->font, x, *fwin->title_clearance + TITLEBAR_EXTEND_SPACE,
1109 title, titlelen);
1110 #endif /* DRAWSTRING_PLUGIN */
1112 wfree(title);
1114 if (fwin->left_button)
1115 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1116 if (fwin->right_button)
1117 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1118 #ifdef XKB_BUTTON_HINT
1119 if (fwin->language_button)
1120 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1121 #endif
1126 static void
1127 reconfigure(WFrameWindow *fwin, int x, int y, int width, int height,
1128 Bool dontMove)
1130 int k = (wPreferences.new_style ? 4 : 3);
1131 int resizedHorizontally = 0;
1133 if (dontMove)
1134 XResizeWindow(dpy, fwin->core->window, width, height);
1135 else
1136 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1139 if (fwin->core->height != height && fwin->resizebar)
1140 XMoveWindow(dpy, fwin->resizebar->window, 0,
1141 height - fwin->resizebar->height);
1143 if (fwin->core->width != width) {
1144 fwin->flags.need_texture_remake = 1;
1145 resizedHorizontally = 1;
1148 fwin->core->width = width;
1149 fwin->core->height = height;
1151 if (fwin->titlebar && resizedHorizontally) {
1152 /* Check if the titlebar is wide enough to hold the buttons.
1153 * Temporarily remove them if can't
1155 if (fwin->left_button) {
1156 if (width < fwin->top_width*k && !fwin->flags.lbutton_dont_fit) {
1158 if (!fwin->flags.hide_left_button) {
1159 XUnmapWindow(dpy, fwin->left_button->window);
1161 fwin->flags.lbutton_dont_fit = 1;
1162 } else if (width >= fwin->top_width*k && fwin->flags.lbutton_dont_fit) {
1164 if (!fwin->flags.hide_left_button) {
1165 XMapWindow(dpy, fwin->left_button->window);
1167 fwin->flags.lbutton_dont_fit = 0;
1171 #ifdef XKB_BUTTON_HINT
1172 if (fwin->language_button) {
1173 if (width < fwin->top_width*k && !fwin->flags.languagebutton_dont_fit) {
1175 if (!fwin->flags.hide_language_button) {
1176 XUnmapWindow(dpy, fwin->language_button->window);
1178 fwin->flags.languagebutton_dont_fit = 1;
1179 } else if (width >= fwin->top_width*k && fwin->flags.languagebutton_dont_fit) {
1181 if (!fwin->flags.hide_language_button) {
1182 XMapWindow(dpy, fwin->language_button->window);
1184 fwin->flags.languagebutton_dont_fit = 0;
1187 #endif
1189 if (fwin->right_button) {
1190 if (width < fwin->top_width*2 && !fwin->flags.rbutton_dont_fit) {
1192 if (!fwin->flags.hide_right_button) {
1193 XUnmapWindow(dpy, fwin->right_button->window);
1195 fwin->flags.rbutton_dont_fit = 1;
1196 } else if (width >= fwin->top_width*2 && fwin->flags.rbutton_dont_fit) {
1198 if (!fwin->flags.hide_right_button) {
1199 XMapWindow(dpy, fwin->right_button->window);
1201 fwin->flags.rbutton_dont_fit = 0;
1205 if (wPreferences.new_style) {
1206 if (fwin->right_button)
1207 XMoveWindow(dpy, fwin->right_button->window,
1208 width - fwin->right_button->width + 1, 0);
1209 } else {
1210 if (fwin->right_button)
1211 XMoveWindow(dpy, fwin->right_button->window,
1212 width - fwin->right_button->width - 3,
1213 (fwin->titlebar->height - fwin->right_button->height)/2);
1215 updateTitlebar(fwin);
1216 checkTitleSize(fwin);
1219 if (fwin->resizebar) {
1220 wCoreConfigure(fwin->resizebar, 0,
1221 fwin->core->height - fwin->resizebar->height,
1222 fwin->core->width, fwin->resizebar->height);
1224 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1225 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
1226 fwin->resizebar_corner_width = fwin->core->width/2;
1231 void
1232 wFrameWindowConfigure(WFrameWindow *fwin, int x, int y, int width, int height)
1234 reconfigure(fwin, x, y, width, height, False);
1237 void
1238 wFrameWindowResize(WFrameWindow *fwin, int width, int height)
1240 reconfigure(fwin, 0, 0, width, height, True);
1245 int
1246 wFrameWindowChangeTitle(WFrameWindow *fwin, char *new_title)
1248 /* check if the title is the same as before */
1249 if (fwin->title) {
1250 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1251 return 0;
1253 } else {
1254 if (!new_title)
1255 return 0;
1258 if (fwin->title)
1259 wfree(fwin->title);
1261 fwin->title = wstrdup(new_title);
1263 if (fwin->titlebar) {
1264 XClearWindow(dpy, fwin->titlebar->window);
1266 wFrameWindowPaint(fwin);
1268 checkTitleSize(fwin);
1270 return 1;
1274 #ifdef OLWM_HINTS
1275 void
1276 wFrameWindowUpdatePushButton(WFrameWindow *fwin, Bool pushed)
1278 fwin->flags.right_button_pushed_in = pushed;
1280 paintButton(fwin->right_button, fwin->title_texture[fwin->flags.state],
1281 fwin->title_pixel[fwin->flags.state],
1282 fwin->rbutton_image, pushed);
1284 #endif /* OLWM_HINTS */
1287 #ifdef XKB_BUTTON_HINT
1288 void
1289 wFrameWindowUpdateLanguageButton(WFrameWindow *fwin)
1291 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1292 fwin->title_pixel[fwin->flags.state],
1293 fwin->languagebutton_image, True);
1295 #endif /* XKB_BUTTON_HINT */
1298 /*********************************************************************/
1300 static void
1301 handleExpose(WObjDescriptor *desc, XEvent *event)
1303 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1306 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1307 fwin->flags.repaint_only_titlebar = 1;
1308 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1309 fwin->flags.repaint_only_resizebar = 1;
1310 wFrameWindowPaint(fwin);
1311 fwin->flags.repaint_only_titlebar = 0;
1312 fwin->flags.repaint_only_resizebar = 0;
1316 static void
1317 checkTitleSize(WFrameWindow *fwin)
1319 int width;
1321 if (!fwin->title) {
1322 fwin->flags.incomplete_title = 0;
1323 return;
1326 if (!fwin->titlebar) {
1327 fwin->flags.incomplete_title = 1;
1328 return;
1329 } else {
1330 width = fwin->titlebar->width - 6 - 6;
1333 if (!wPreferences.new_style) {
1334 if (fwin->left_button && !fwin->flags.hide_left_button
1335 && !fwin->flags.lbutton_dont_fit)
1336 width -= fwin->left_button->width + 3;
1338 #ifdef XKB_BUTTON_HINT
1339 if (fwin->language_button && !fwin->flags.hide_language_button
1340 && !fwin->flags.languagebutton_dont_fit)
1341 width -= fwin->language_button->width + 3;
1342 #endif
1344 if (fwin->right_button && !fwin->flags.hide_right_button
1345 && !fwin->flags.rbutton_dont_fit)
1346 width -= fwin->right_button->width + 3;
1348 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1349 fwin->flags.incomplete_title = 1;
1350 } else {
1351 fwin->flags.incomplete_title = 0;
1356 static void
1357 paintButton(WCoreWindow *button, WTexture *texture, unsigned long color,
1358 WPixmap *image, int pushed)
1360 WScreen *scr = button->screen_ptr;
1361 GC copy_gc = scr->copy_gc;
1362 int x=0, y=0, d=0;
1363 int left=0, width=0;
1365 /* setup stuff according to the state */
1366 if (pushed) {
1367 if (image) {
1368 if (image->width>=image->height*2) {
1369 /* the image contains 2 pictures: the second is for the
1370 * pushed state */
1371 width = image->width/2;
1372 left = image->width/2;
1373 } else {
1374 width = image->width;
1377 XSetClipMask(dpy, copy_gc, None);
1378 XSetForeground(dpy, copy_gc, scr->white_pixel);
1379 d=1;
1380 if (wPreferences.new_style) {
1381 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1382 button->width-1, button->height-1);
1383 XSetForeground(dpy, copy_gc, scr->black_pixel);
1384 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1385 button->width-1, button->height-1);
1386 } else {
1387 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1388 button->width, button->height);
1389 XSetForeground(dpy, copy_gc, scr->black_pixel);
1390 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1391 button->width, button->height);
1393 } else {
1394 XClearWindow(dpy, button->window);
1396 if (image) {
1397 if (image->width>=image->height*2)
1398 width = image->width/2;
1399 else
1400 width = image->width;
1402 d=0;
1404 if (wPreferences.new_style) {
1405 if (texture->any.type==WTEX_SOLID || pushed) {
1406 wDrawBevel(button->window, button->width, button->height,
1407 (WTexSolid*)texture, WREL_RAISED);
1409 } else {
1410 wDrawBevel(button->window, button->width, button->height,
1411 scr->widget_texture, WREL_RAISED);
1415 if (image) {
1416 /* display image */
1417 XSetClipMask(dpy, copy_gc, image->mask);
1418 x = (button->width - width)/2 + d;
1419 y = (button->height - image->height)/2 + d;
1420 XSetClipOrigin(dpy, copy_gc, x-left, y);
1421 if (!wPreferences.new_style) {
1422 XSetForeground(dpy, copy_gc, scr->black_pixel);
1423 if (!pushed) {
1424 if (image->depth==1)
1425 XCopyPlane(dpy, image->image, button->window, copy_gc,
1426 left, 0, width, image->height, x, y, 1);
1427 else
1428 XCopyArea(dpy, image->image, button->window, copy_gc,
1429 left, 0, width, image->height, x, y);
1430 } else {
1431 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1432 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1433 button->width, button->height);
1435 } else {
1436 if (pushed) {
1437 XSetForeground(dpy, copy_gc, scr->black_pixel);
1438 } else {
1439 XSetForeground(dpy, copy_gc, color);
1440 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1442 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1443 button->width, button->height);
1449 static void
1450 handleButtonExpose(WObjDescriptor *desc, XEvent *event)
1452 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1453 WCoreWindow *button = (WCoreWindow*)desc->self;
1455 #ifdef XKB_BUTTON_HINT
1456 if (button == fwin->language_button) {
1457 if (wPreferences.modelock){
1458 paintButton(button, fwin->title_texture[fwin->flags.state],
1459 fwin->title_pixel[fwin->flags.state],
1460 fwin->languagebutton_image, False);
1462 } else
1463 #endif
1464 if (button == fwin->left_button) {
1465 paintButton(button, fwin->title_texture[fwin->flags.state],
1466 fwin->title_pixel[fwin->flags.state],
1467 fwin->lbutton_image, False);
1468 } else {
1469 Bool pushed = False;
1471 #ifdef OLWM_HINTS
1472 if (fwin->flags.right_button_pushed_in)
1473 pushed = True;
1474 #endif
1475 /* emulate the olwm pushpin in the "out" state */
1476 paintButton(button, fwin->title_texture[fwin->flags.state],
1477 fwin->title_pixel[fwin->flags.state],
1478 fwin->rbutton_image, pushed);
1483 static void
1484 titlebarMouseDown(WObjDescriptor *desc, XEvent *event)
1486 WFrameWindow *fwin = desc->parent;
1487 WCoreWindow *titlebar = desc->self;
1489 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1490 if (fwin->on_dblclick_titlebar)
1491 (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event);
1492 } else {
1493 if (fwin->on_mousedown_titlebar)
1494 (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event);
1499 static void
1500 resizebarMouseDown(WObjDescriptor *desc, XEvent *event)
1502 WFrameWindow *fwin = desc->parent;
1503 WCoreWindow *resizebar = desc->self;
1505 if (fwin->on_mousedown_resizebar)
1506 (*fwin->on_mousedown_resizebar)(resizebar, fwin->child, event);
1510 static void
1511 buttonMouseDown(WObjDescriptor *desc, XEvent *event)
1513 WFrameWindow *fwin = desc->parent;
1514 WCoreWindow *button = desc->self;
1515 WPixmap *image;
1516 XEvent ev;
1517 int done=0, execute=1;
1518 WTexture *texture;
1519 unsigned long pixel;
1520 int clickButton = event->xbutton.button;
1522 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1523 if (button == fwin->right_button && fwin->on_dblclick_right) {
1524 (*fwin->on_dblclick_right)(button, fwin->child, event);
1526 return;
1529 if (button == fwin->left_button) {
1530 image = fwin->lbutton_image;
1531 } else {
1532 image = fwin->rbutton_image;
1534 #ifdef XKB_BUTTON_HINT
1535 if (button == fwin->language_button) {
1536 if (!wPreferences.modelock) return;
1537 image = fwin->languagebutton_image;
1539 #endif
1541 pixel = fwin->title_pixel[fwin->flags.state];
1542 texture = fwin->title_texture[fwin->flags.state];
1543 paintButton(button, texture, pixel, image, True);
1545 while (!done) {
1546 WMMaskEvent(dpy, LeaveWindowMask|EnterWindowMask|ButtonReleaseMask
1547 |ButtonPressMask|ExposureMask, &ev);
1548 switch (ev.type) {
1549 case LeaveNotify:
1550 execute = 0;
1551 paintButton(button, texture, pixel, image, False);
1552 break;
1554 case EnterNotify:
1555 execute = 1;
1556 paintButton(button, texture, pixel, image, True);
1557 break;
1559 case ButtonPress:
1560 break;
1562 case ButtonRelease:
1563 if (ev.xbutton.button == clickButton)
1564 done = 1;
1565 break;
1567 default:
1568 WMHandleEvent(&ev);
1571 paintButton(button, texture, pixel, image, False);
1573 if (execute) {
1574 if (button == fwin->left_button) {
1575 if (fwin->on_click_left)
1576 (*fwin->on_click_left)(button, fwin->child, &ev);
1577 } else if (button == fwin->right_button) {
1578 if (fwin->on_click_right)
1579 (*fwin->on_click_right)(button, fwin->child, &ev);
1581 #ifdef XKB_BUTTON_HINT
1582 else if (button == fwin->language_button) {
1583 if (fwin->on_click_language)
1584 (*fwin->on_click_language)(button, fwin->child, &ev);
1586 #endif