- Fixed focus handling for windows that set WM_HINTS.take_focus = False.
[wmaker-crm.git] / src / framewin.c
blobb9b2d8cc14114700e8920481d0242923923caab6
1 /*
2 * Window Maker window manager
3 *
4 * Copyright (c) 1997-2002 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 WMColor **color, WMFont **font)
70 WFrameWindow *fwin;
72 fwin = wmalloc(sizeof(WFrameWindow));
73 memset(fwin, 0, sizeof(WFrameWindow));
75 fwin->screen_ptr = scr;
77 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
79 fwin->title_texture = title_texture;
80 fwin->resizebar_texture = resize_texture;
81 fwin->title_color = color;
82 fwin->title_clearance = clearance;
83 fwin->font = font;
84 #ifdef KEEP_XKB_LOCK_STATUS
85 fwin->languagemode = XkbGroup1Index;
86 fwin->last_languagemode = XkbGroup2Index;
87 #endif
89 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height,
90 (flags & WFF_BORDER)
91 ? FRAME_BORDER_WIDTH : 0);
92 if (wPreferences.use_saveunders) {
93 unsigned long vmask;
94 XSetWindowAttributes attribs;
96 vmask = CWSaveUnder;
97 attribs.save_under = True;
98 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
101 /* setup stacking information */
102 fwin->core->stacking = wmalloc(sizeof(WStacking));
103 fwin->core->stacking->above = NULL;
104 fwin->core->stacking->under = NULL;
105 fwin->core->stacking->child_of = NULL;
106 fwin->core->stacking->window_level = wlevel;
108 AddToStackList(fwin->core);
110 wFrameWindowUpdateBorders(fwin, flags);
112 return fwin;
117 void
118 wFrameWindowUpdateBorders(WFrameWindow *fwin, int flags)
120 int theight;
121 int bsize;
122 int width, height;
123 int i;
124 WScreen *scr = fwin->screen_ptr;
126 width = fwin->core->width;
127 if (flags & WFF_IS_SHADED)
128 height = -1;
129 else
130 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
132 if (flags & WFF_TITLEBAR)
133 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
134 else
135 theight = 0;
137 if (wPreferences.new_style) {
138 bsize = theight;
139 } else {
140 bsize = theight - 7;
143 if (fwin->titlebar) {
144 /* if we had a titlebar and is requesting for one,
145 * check if the size has changed and resize it */
146 if (flags & WFF_TITLEBAR) {
147 fwin->top_width = theight;
149 fwin->flags.need_texture_remake = 1;
151 if (wPreferences.new_style) {
152 if (fwin->left_button) {
153 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
155 #ifdef XKB_BUTTON_HINT
156 if (fwin->language_button)
157 if (fwin->flags.hide_left_button || !fwin->left_button
158 || fwin->flags.lbutton_dont_fit) {
159 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
160 } else {
161 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
163 #endif
166 if (fwin->right_button) {
167 wCoreConfigure(fwin->right_button, width-bsize+1,
168 0, bsize, bsize);
170 } else { /* !new_style */
171 if (fwin->left_button) {
172 wCoreConfigure(fwin->left_button, 3, (theight-bsize)/2,
173 bsize, bsize);
176 #ifdef XKB_BUTTON_HINT
177 if (fwin->language_button) {
178 wCoreConfigure(fwin->language_button, 6 + bsize, (theight-bsize)/2,
179 bsize, bsize);
181 #endif
183 if (fwin->right_button) {
184 wCoreConfigure(fwin->right_button, width-bsize-3,
185 (theight-bsize)/2, bsize, bsize);
188 updateTitlebar(fwin);
189 } else {
190 /* we had a titlebar, but now we don't need it anymore */
191 for (i=0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
192 FREE_PIXMAP(fwin->title_back[i]);
193 if (wPreferences.new_style) {
194 FREE_PIXMAP(fwin->lbutton_back[i]);
195 FREE_PIXMAP(fwin->rbutton_back[i]);
196 #ifdef XKB_BUTTON_HINT
197 FREE_PIXMAP(fwin->languagebutton_back[i]);
198 #endif
201 if (fwin->left_button)
202 wCoreDestroy(fwin->left_button);
203 fwin->left_button = NULL;
205 #ifdef XKB_BUTTON_HINT
206 if (fwin->language_button)
207 wCoreDestroy(fwin->language_button);
208 fwin->language_button = NULL;
209 #endif
211 if (fwin->right_button)
212 wCoreDestroy(fwin->right_button);
213 fwin->right_button = NULL;
215 wCoreDestroy(fwin->titlebar);
216 fwin->titlebar = NULL;
218 fwin->top_width = 0;
220 } else {
221 /* if we didn't have a titlebar and are being requested for
222 * one, create it */
223 if (flags & WFF_TITLEBAR) {
224 fwin->top_width = theight;
226 fwin->flags.titlebar = 1;
227 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width+1, theight);
229 if (flags & WFF_LEFT_BUTTON) {
230 fwin->flags.left_button = 1;
231 if (wPreferences.new_style) {
232 fwin->left_button = wCoreCreate(fwin->core, 0, 0,
233 bsize, bsize);
234 if (width < theight*4) {
235 fwin->flags.lbutton_dont_fit = 1;
236 } else {
237 XMapRaised(dpy, fwin->left_button->window);
239 } else {
240 fwin->left_button =
241 wCoreCreate(fwin->titlebar, 3, (theight-bsize)/2,
242 bsize, bsize);
244 XSetWindowBackground(dpy, fwin->left_button->window,
245 scr->widget_texture->normal.pixel);
247 if (width < theight*3) {
248 fwin->flags.lbutton_dont_fit = 1;
249 } else {
250 XMapRaised(dpy, fwin->left_button->window);
255 #ifdef XKB_BUTTON_HINT
256 if (flags & WFF_LANGUAGE_BUTTON) {
257 fwin->flags.language_button = 1;
258 if (wPreferences.new_style) {
259 fwin->language_button = wCoreCreate(fwin->core,
260 bsize, 0, bsize, bsize);
262 if (width < theight*4) {
263 fwin->flags.languagebutton_dont_fit = 1;
264 } else {
265 XMapRaised(dpy, fwin->language_button->window);
267 } else {
268 fwin->language_button =
269 wCoreCreate(fwin->titlebar, bsize + 6, (theight-bsize)/2,
270 bsize, bsize);
272 XSetWindowBackground(dpy, fwin->language_button->window,
273 scr->widget_texture->normal.pixel);
275 if (width < theight*3) {
276 fwin->flags.languagebutton_dont_fit = 1;
277 } else {
278 XMapRaised(dpy, fwin->language_button->window);
282 #endif
284 if (flags & WFF_RIGHT_BUTTON) {
285 fwin->flags.right_button = 1;
286 if (wPreferences.new_style) {
287 fwin->right_button =
288 wCoreCreate(fwin->core, width-bsize+1, 0,
289 bsize, bsize);
290 } else {
291 fwin->right_button =
292 wCoreCreate(fwin->titlebar, width-bsize-3,
293 (theight-bsize)/2, bsize, bsize);
294 XSetWindowBackground(dpy, fwin->right_button->window,
295 scr->widget_texture->normal.pixel);
298 if (width < theight*2) {
299 fwin->flags.rbutton_dont_fit = 1;
300 } else {
301 XMapRaised(dpy, fwin->right_button->window);
305 if (wPreferences.new_style)
306 updateTitlebar(fwin);
308 XMapRaised(dpy, fwin->titlebar->window);
310 fwin->flags.need_texture_remake = 1;
313 checkTitleSize(fwin);
315 if (flags & WFF_RESIZEBAR) {
316 fwin->bottom_width = RESIZEBAR_HEIGHT;
318 if (!fwin->resizebar) {
319 fwin->flags.resizebar = 1;
320 fwin->resizebar = wCoreCreate(fwin->core, 0,
321 height + fwin->top_width,
322 width, RESIZEBAR_HEIGHT);
323 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
324 if (width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
325 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH)/2;
326 if (fwin->resizebar_corner_width < 0)
327 fwin->resizebar_corner_width = 0;
330 XMapWindow(dpy, fwin->resizebar->window);
331 XLowerWindow(dpy, fwin->resizebar->window);
333 fwin->flags.need_texture_remake = 1;
334 } else {
335 if (height+fwin->top_width+fwin->bottom_width != fwin->core->height) {
336 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
337 width, RESIZEBAR_HEIGHT);
340 } else {
341 fwin->bottom_width = 0;
343 if (fwin->resizebar) {
344 fwin->bottom_width = 0;
345 wCoreDestroy(fwin->resizebar);
346 fwin->resizebar = NULL;
350 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height
351 && !(flags & WFF_IS_SHADED)) {
352 wFrameWindowResize(fwin, width,
353 height + fwin->top_width + fwin->bottom_width);
357 if (flags & WFF_BORDER) {
358 XSetWindowBorderWidth(dpy, fwin->core->window, FRAME_BORDER_WIDTH);
359 } else {
360 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
363 /* setup object descriptors */
365 if (fwin->titlebar) {
366 fwin->titlebar->descriptor.handle_expose = handleExpose;
367 fwin->titlebar->descriptor.parent = fwin;
368 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
369 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
372 if (fwin->resizebar) {
373 fwin->resizebar->descriptor.handle_expose = handleExpose;
374 fwin->resizebar->descriptor.parent = fwin;
375 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
376 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
379 if (fwin->left_button) {
380 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
381 fwin->left_button->descriptor.parent = fwin;
382 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
383 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
386 #ifdef XKB_BUTTON_HINT
387 if (fwin->language_button) {
388 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
389 fwin->language_button->descriptor.parent = fwin;
390 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
391 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
393 #endif
396 if (fwin->right_button) {
397 fwin->right_button->descriptor.parent = fwin;
398 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
399 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
400 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
403 checkTitleSize(fwin);
408 void
409 wFrameWindowDestroy(WFrameWindow *fwin)
411 int i;
413 if (fwin->left_button)
414 wCoreDestroy(fwin->left_button);
416 #ifdef XKB_BUTTON_HINT
417 if (fwin->language_button)
418 wCoreDestroy(fwin->language_button);
419 #endif
421 if (fwin->right_button)
422 wCoreDestroy(fwin->right_button);
424 if (fwin->resizebar)
425 wCoreDestroy(fwin->resizebar);
427 if (fwin->titlebar)
428 wCoreDestroy(fwin->titlebar);
430 RemoveFromStackList(fwin->core);
432 wCoreDestroy(fwin->core);
434 if (fwin->title)
435 wfree(fwin->title);
437 for (i=0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
438 FREE_PIXMAP(fwin->title_back[i]);
439 if (wPreferences.new_style) {
440 FREE_PIXMAP(fwin->lbutton_back[i]);
441 #ifdef XKB_BUTTON_HINT
442 FREE_PIXMAP(fwin->languagebutton_back[i]);
443 #endif
444 FREE_PIXMAP(fwin->rbutton_back[i]);
448 wfree(fwin);
452 void
453 wFrameWindowChangeState(WFrameWindow *fwin, int state)
455 if (fwin->flags.state==state)
456 return;
458 fwin->flags.state = state;
459 fwin->flags.need_texture_change = 1;
461 wFrameWindowPaint(fwin);
465 static void
466 updateTitlebar(WFrameWindow *fwin)
468 int x, w;
469 int theight;
471 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
473 x = 0;
474 w = fwin->core->width + 1;
476 if (wPreferences.new_style) {
477 if (fwin->flags.hide_left_button || !fwin->left_button
478 || fwin->flags.lbutton_dont_fit) {
479 x = 0;
480 #ifdef XKB_BUTTON_HINT
481 if(fwin->language_button)
482 wCoreConfigure(fwin->language_button, 0, 0,
483 fwin->language_button->width,
484 fwin->language_button->width);
485 #endif
486 } else {
487 #ifdef XKB_BUTTON_HINT
488 if(fwin->language_button)
489 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
490 fwin->language_button->width,
491 fwin->language_button->width);
492 #endif
493 x = fwin->left_button->width;
494 w -= fwin->left_button->width;
496 #ifdef XKB_BUTTON_HINT
497 if (fwin->flags.hide_language_button || !fwin->language_button
498 || fwin->flags.languagebutton_dont_fit) {
499 } else {
500 x += fwin->language_button->width;
501 w -= fwin->language_button->width;
503 #endif
505 #ifdef XKB_BUTTON_HINT
506 else {
507 int bsize = theight - 7;
508 if (fwin->flags.hide_left_button || !fwin->left_button
509 || fwin->flags.lbutton_dont_fit) {
510 if(fwin->language_button)
511 wCoreConfigure(fwin->language_button, 3, (theight-bsize)/2,
512 fwin->language_button->width,
513 fwin->language_button->width);
515 else {
516 if(fwin->language_button)
517 wCoreConfigure(fwin->language_button,
518 6 + fwin->left_button->width, (theight-bsize)/2,
519 fwin->language_button->width,
520 fwin->language_button->width);
523 #endif
525 if (wPreferences.new_style) {
526 if (!fwin->flags.hide_right_button && fwin->right_button
527 && !fwin->flags.rbutton_dont_fit) {
528 w -= fwin->right_button->width;
532 if (wPreferences.new_style || fwin->titlebar->width!=w)
533 fwin->flags.need_texture_remake = 1;
535 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
539 void
540 wFrameWindowHideButton(WFrameWindow *fwin, int flags)
542 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
543 XUnmapWindow(dpy, fwin->right_button->window);
544 fwin->flags.hide_right_button = 1;
547 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
548 XUnmapWindow(dpy, fwin->left_button->window);
549 fwin->flags.hide_left_button = 1;
552 #ifdef XKB_BUTTON_HINT
553 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
554 XUnmapWindow(dpy, fwin->language_button->window);
555 fwin->flags.hide_language_button = 1;
557 #endif
559 if (fwin->titlebar) {
560 if (wPreferences.new_style) {
561 updateTitlebar(fwin);
562 } else {
563 #ifdef XKB_BUTTON_HINT
564 updateTitlebar(fwin);
565 #else
566 XClearWindow(dpy, fwin->titlebar->window);
567 wFrameWindowPaint(fwin);
568 #endif
570 checkTitleSize(fwin);
575 void
576 wFrameWindowShowButton(WFrameWindow *fwin, int flags)
578 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button
579 && fwin->flags.hide_right_button) {
581 if (!fwin->flags.rbutton_dont_fit)
582 XMapWindow(dpy, fwin->right_button->window);
584 fwin->flags.hide_right_button = 0;
587 #ifdef XKB_BUTTON_HINT
588 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button
589 && fwin->flags.hide_language_button) {
591 if (!fwin->flags.languagebutton_dont_fit)
592 XMapWindow(dpy, fwin->language_button->window);
594 fwin->flags.hide_language_button = 0;
596 #endif
598 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button
599 && fwin->flags.hide_left_button) {
601 if (!fwin->flags.lbutton_dont_fit)
602 XMapWindow(dpy, fwin->left_button->window);
604 fwin->flags.hide_left_button = 0;
608 if (fwin->titlebar) {
609 if (wPreferences.new_style) {
610 updateTitlebar(fwin);
611 } else {
612 XClearWindow(dpy, fwin->titlebar->window);
613 wFrameWindowPaint(fwin);
615 checkTitleSize(fwin);
620 static void
621 #ifdef XKB_BUTTON_HINT
622 renderTexture(WScreen *scr, WTexture *texture, int width, int height,
623 int bwidth, int bheight, int left, int language, int right,
624 Pixmap *title, Pixmap *lbutton, Pixmap *languagebutton, Pixmap *rbutton)
625 #else
626 renderTexture(WScreen *scr, WTexture *texture, int width, int height,
627 int bwidth, int bheight, int left, int right,
628 Pixmap *title, Pixmap *lbutton, Pixmap *rbutton)
629 #endif
631 RImage *img;
632 RImage *limg, *rimg, *mimg;
633 #ifdef XKB_BUTTON_HINT
634 RImage *timg;
635 #endif
636 int x, w;
638 *title = None;
639 *lbutton = None;
640 *rbutton = None;
641 #ifdef XKB_BUTTON_HINT
642 *languagebutton = None;
643 #endif
645 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
646 if (!img) {
647 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
648 return;
651 if (wPreferences.new_style) {
652 if (left) {
653 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
654 } else
655 limg = NULL;
657 x = 0;
658 w = img->width;
660 #ifdef XKB_BUTTON_HINT
661 if (language) {
662 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
663 } else
664 timg = NULL;
665 #endif
667 if (limg) {
668 RBevelImage(limg, RBEV_RAISED2);
669 if (!RConvertImage(scr->rcontext, limg, lbutton)) {
670 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
672 x += limg->width;
673 w -= limg->width;
674 RReleaseImage(limg);
677 #ifdef XKB_BUTTON_HINT
678 if (timg) {
679 RBevelImage(timg, RBEV_RAISED2);
680 if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
681 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
683 x += timg->width;
684 w -= timg->width;
685 RReleaseImage(timg);
687 #endif
689 if (right) {
690 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
691 } else
692 rimg = NULL;
694 if (rimg) {
695 RBevelImage(rimg, RBEV_RAISED2);
696 if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
697 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
699 w -= rimg->width;
700 RReleaseImage(rimg);
703 if (w!=width) {
704 mimg = RGetSubImage(img, x, 0, w, img->height);
705 RBevelImage(mimg, RBEV_RAISED2);
707 if (!RConvertImage(scr->rcontext, mimg, title)) {
708 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
710 RReleaseImage(mimg);
711 } else {
712 RBevelImage(img, RBEV_RAISED2);
714 if (!RConvertImage(scr->rcontext, img, title)) {
715 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
718 } else {
719 RBevelImage(img, RBEV_RAISED2);
721 if (!RConvertImage(scr->rcontext, img, title)) {
722 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
726 RReleaseImage(img);
730 static void
731 renderResizebarTexture(WScreen *scr, WTexture *texture, int width, int height,
732 int cwidth, Pixmap *pmap)
734 RImage *img;
735 RColor light;
736 RColor dark;
738 *pmap = None;
740 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
741 if (!img) {
742 wwarning(_("could not render texture: %s"),
743 RMessageForError(RErrorCode));
744 return;
747 light.alpha = 0;
748 light.red = light.green = light.blue = 80;
750 dark.alpha = 0;
751 dark.red = dark.green = dark.blue = 40;
753 ROperateLine(img, RSubtractOperation, 0, 0, width-1, 0, &dark);
754 ROperateLine(img, RAddOperation, 0, 1, width-1, 1, &light);
756 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height-1, &dark);
757 ROperateLine(img, RAddOperation, cwidth+1, 2, cwidth+1, height-1, &light);
759 if (width > 1)
760 ROperateLine(img, RSubtractOperation, width-cwidth-2, 2,
761 width-cwidth-2, height-1, &dark);
762 ROperateLine(img, RAddOperation, width-cwidth-1, 2, width-cwidth-1,
763 height-1, &light);
765 #ifdef SHADOW_RESIZEBAR
766 ROperateLine(img, RAddOperation, 0, 1, 0, height-1, &light);
767 ROperateLine(img, RSubtractOperation, width-1, 1, width-1, height-1,
768 &dark);
769 ROperateLine(img, RSubtractOperation, 0, height-1, width-1, height-1,
770 &dark);
771 #endif /* SHADOW_RESIZEBAR */
774 if (!RConvertImage(scr->rcontext, img, pmap)) {
775 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
778 RReleaseImage(img);
783 static void
784 updateTexture(WFrameWindow *fwin)
786 int i;
787 unsigned long pixel;
789 i = fwin->flags.state;
790 if (fwin->titlebar) {
791 if (fwin->title_texture[i]->any.type!=WTEX_SOLID) {
792 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window,
793 fwin->title_back[i]);
794 if (wPreferences.new_style) {
795 if (fwin->left_button && fwin->lbutton_back[i])
796 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
797 fwin->lbutton_back[i]);
799 #ifdef XKB_BUTTON_HINT
800 if (fwin->language_button && fwin->languagebutton_back[i]) {
801 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
802 fwin->languagebutton_back[i]);
804 #endif
806 if (fwin->right_button && fwin->rbutton_back[i])
807 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
808 fwin->rbutton_back[i]);
810 } else {
811 pixel = fwin->title_texture[i]->solid.normal.pixel;
812 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
813 if (wPreferences.new_style) {
814 if (fwin->left_button)
815 XSetWindowBackground(dpy, fwin->left_button->window,
816 pixel);
817 #ifdef XKB_BUTTON_HINT
818 if (fwin->language_button)
819 XSetWindowBackground(dpy, fwin->language_button->window,
820 pixel);
821 #endif
822 if (fwin->right_button)
823 XSetWindowBackground(dpy, fwin->right_button->window,
824 pixel);
827 XClearWindow(dpy, fwin->titlebar->window);
829 if (fwin->left_button) {
830 XClearWindow(dpy, fwin->left_button->window);
831 handleButtonExpose(&fwin->left_button->descriptor, NULL);
833 #ifdef XKB_BUTTON_HINT
834 if (fwin->language_button) {
835 XClearWindow(dpy, fwin->language_button->window);
836 handleButtonExpose(&fwin->language_button->descriptor, NULL);
838 #endif
839 if (fwin->right_button) {
840 XClearWindow(dpy, fwin->right_button->window);
841 handleButtonExpose(&fwin->right_button->descriptor, NULL);
848 static void
849 remakeTexture(WFrameWindow *fwin, int state)
851 Pixmap pmap, lpmap, rpmap;
852 #ifdef XKB_BUTTON_HINT
853 Pixmap tpmap;
854 #endif
856 if (fwin->title_texture[state] && fwin->titlebar) {
857 FREE_PIXMAP(fwin->title_back[state]);
858 if (wPreferences.new_style) {
859 FREE_PIXMAP(fwin->lbutton_back[state]);
860 FREE_PIXMAP(fwin->rbutton_back[state]);
861 #ifdef XKB_BUTTON_HINT
862 FREE_PIXMAP(fwin->languagebutton_back[state]);
863 #endif
866 if (fwin->title_texture[state]->any.type!=WTEX_SOLID) {
867 int left, right;
868 int width;
869 #ifdef XKB_BUTTON_HINT
870 int language;
871 #endif
873 /* eventually surrounded by if new_style */
874 left = fwin->left_button && !fwin->flags.hide_left_button
875 && !fwin->flags.lbutton_dont_fit;
876 #ifdef XKB_BUTTON_HINT
877 language = fwin->language_button && !fwin->flags.hide_language_button
878 && !fwin->flags.languagebutton_dont_fit;
879 #endif
880 right = fwin->right_button && !fwin->flags.hide_right_button
881 && !fwin->flags.rbutton_dont_fit;
883 width = fwin->core->width+1;
885 #ifdef XKB_BUTTON_HINT
886 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
887 width, fwin->titlebar->height,
888 fwin->titlebar->height, fwin->titlebar->height,
889 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
890 #else
891 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
892 width, fwin->titlebar->height,
893 fwin->titlebar->height, fwin->titlebar->height,
894 left, right, &pmap, &lpmap, &rpmap);
895 #endif
897 fwin->title_back[state] = pmap;
898 if (wPreferences.new_style) {
899 fwin->lbutton_back[state] = lpmap;
900 fwin->rbutton_back[state] = rpmap;
901 #ifdef XKB_BUTTON_HINT
902 fwin->languagebutton_back[state] = tpmap;
903 #endif
907 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
908 && fwin->resizebar && state == 0) {
910 FREE_PIXMAP(fwin->resizebar_back[0]);
912 if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
914 renderResizebarTexture(fwin->screen_ptr,
915 fwin->resizebar_texture[0],
916 fwin->resizebar->width,
917 fwin->resizebar->height,
918 fwin->resizebar_corner_width,
919 &pmap);
921 fwin->resizebar_back[0] = pmap;
924 /* this part should be in updateTexture() */
925 if (fwin->resizebar_texture[0]->any.type!=WTEX_SOLID) {
926 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window,
927 fwin->resizebar_back[0]);
928 } else {
929 XSetWindowBackground(dpy, fwin->resizebar->window,
930 fwin->resizebar_texture[0]->solid.normal.pixel);
932 XClearWindow(dpy, fwin->resizebar->window);
937 void
938 wFrameWindowPaint(WFrameWindow *fwin)
940 WScreen *scr = fwin->screen_ptr;
941 int state;
943 state = fwin->flags.state;
945 if (fwin->flags.is_client_window_frame)
946 fwin->flags.justification = wPreferences.title_justification;
948 if (fwin->flags.need_texture_remake) {
949 int i;
951 fwin->flags.need_texture_remake = 0;
952 fwin->flags.need_texture_change = 0;
954 if (fwin->flags.single_texture) {
955 remakeTexture(fwin, 0);
956 updateTexture(fwin);
957 } else {
958 /* first render the texture for the current state... */
959 remakeTexture(fwin, state);
960 /* ... and paint it */
961 updateTexture(fwin);
963 for (i=0; i < 3; i++) {
964 if (i != state) {
965 remakeTexture(fwin, i);
971 if (fwin->flags.need_texture_change) {
972 fwin->flags.need_texture_change = 0;
974 updateTexture(fwin);
977 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
978 && fwin->title_texture[state]->any.type==WTEX_SOLID) {
979 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
980 fwin->titlebar->height,
981 (WTexSolid*)fwin->title_texture[state],
982 WREL_RAISED);
985 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
986 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
987 Window win;
988 int w, h;
989 int cw;
990 GC light_gc, dim_gc;
991 WTexSolid *texture = (WTexSolid*)fwin->resizebar_texture[0];
993 w = fwin->resizebar->width;
994 h = fwin->resizebar->height;
995 cw = fwin->resizebar_corner_width;
996 light_gc = texture->light_gc;
997 dim_gc = texture->dim_gc;
998 win = fwin->resizebar->window;
1000 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
1001 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
1003 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
1004 XDrawLine(dpy, win, light_gc, cw+1, 2, cw+1, h);
1006 XDrawLine(dpy, win, dim_gc, w-cw-2, 2, w-cw-2, h);
1007 XDrawLine(dpy, win, light_gc, w-cw-1, 2, w-cw-1, h);
1009 #ifdef SHADOW_RESIZEBAR
1010 XDrawLine(dpy, win, light_gc, 0, 1, 0, h-1);
1011 XDrawLine(dpy, win, dim_gc, w-1, 2, w-1, h-1);
1012 XDrawLine(dpy, win, dim_gc, 1, h-1, cw, h-1);
1013 XDrawLine(dpy, win, dim_gc, cw+2, h-1, w-cw-2, h-1);
1014 XDrawLine(dpy, win, dim_gc, w-cw, h-1, w-1, h-1);
1015 #endif /* SHADOW_RESIZEBAR */
1019 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
1020 int x, y, w, h;
1021 int lofs = 6, rofs = 6;
1022 int titlelen;
1023 int allButtons = 1;
1026 if (!wPreferences.new_style) {
1027 if (fwin->left_button && !fwin->flags.hide_left_button
1028 && !fwin->flags.lbutton_dont_fit)
1029 lofs += fwin->left_button->width + 3;
1030 else
1031 allButtons = 0;
1033 #ifdef XKB_BUTTON_HINT
1034 if (fwin->language_button && !fwin->flags.hide_language_button
1035 && !fwin->flags.languagebutton_dont_fit)
1036 lofs += fwin->language_button->width;
1037 else
1038 allButtons = 0;
1039 #endif
1041 if (fwin->right_button && !fwin->flags.hide_right_button
1042 && !fwin->flags.rbutton_dont_fit)
1043 rofs += fwin->right_button->width + 3;
1044 else
1045 allButtons = 0;
1048 #ifdef XKB_BUTTON_HINT
1049 fwin->languagebutton_image =
1050 scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
1051 #endif
1053 if (fwin->title) {
1054 Drawable buf;
1055 char *title;
1057 title = ShrinkString(*fwin->font, fwin->title,
1058 fwin->titlebar->width - lofs - rofs);
1059 titlelen = strlen(title);
1060 w = WMWidthOfString(*fwin->font, title, titlelen);
1062 switch (fwin->flags.justification) {
1063 case WTJ_LEFT:
1064 x = lofs;
1065 break;
1067 case WTJ_RIGHT:
1068 x = fwin->titlebar->width - w - rofs;
1069 break;
1071 default:
1072 if (!allButtons)
1073 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
1074 else
1075 x = (fwin->titlebar->width - w) / 2;
1076 break;
1079 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
1080 h = WMFontHeight(*fwin->font);
1082 /* We use a w+2 buffer to have an extra pixel on the left and
1083 * another one on the right. This is because for some odd reason,
1084 * sometimes when using AA fonts (when libfreetype2 is compiled
1085 * with bytecode interpreter turned off), some fonts are drawn
1086 * starting from x = -1 not from 0 as requested. Observed with
1087 * capital A letter on the bold 'trebuchet ms' font. -Dan
1089 buf = XCreatePixmap(dpy, fwin->titlebar->window, w+2, h,
1090 scr->w_depth);
1092 XSetClipMask(dpy, scr->copy_gc, None);
1094 if (fwin->title_texture[state]->any.type!=WTEX_SOLID) {
1095 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1096 x-1, y, w+2, h, 0, 0);
1097 } else {
1098 XSetForeground(dpy, scr->copy_gc,
1099 fwin->title_texture[state]->solid.normal.pixel);
1100 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w+2, h);
1103 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1);*/
1104 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1105 *fwin->font, 1, 0, title, titlelen);
1107 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc,
1108 0, 0, w+2, h, x-1, y);
1110 XFreePixmap(dpy, buf);
1112 wfree(title);
1115 if (fwin->left_button)
1116 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1117 if (fwin->right_button)
1118 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1119 #ifdef XKB_BUTTON_HINT
1120 if (fwin->language_button)
1121 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1122 #endif
1127 static void
1128 reconfigure(WFrameWindow *fwin, int x, int y, int width, int height,
1129 Bool dontMove)
1131 int k = (wPreferences.new_style ? 4 : 3);
1132 int resizedHorizontally = 0;
1134 if (dontMove)
1135 XResizeWindow(dpy, fwin->core->window, width, height);
1136 else
1137 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1140 if (fwin->core->height != height && fwin->resizebar)
1141 XMoveWindow(dpy, fwin->resizebar->window, 0,
1142 height - fwin->resizebar->height);
1144 if (fwin->core->width != width) {
1145 fwin->flags.need_texture_remake = 1;
1146 resizedHorizontally = 1;
1149 fwin->core->width = width;
1150 fwin->core->height = height;
1152 if (fwin->titlebar && resizedHorizontally) {
1153 /* Check if the titlebar is wide enough to hold the buttons.
1154 * Temporarily remove them if can't
1156 if (fwin->left_button) {
1157 if (width < fwin->top_width*k && !fwin->flags.lbutton_dont_fit) {
1159 if (!fwin->flags.hide_left_button) {
1160 XUnmapWindow(dpy, fwin->left_button->window);
1162 fwin->flags.lbutton_dont_fit = 1;
1163 } else if (width >= fwin->top_width*k && fwin->flags.lbutton_dont_fit) {
1165 if (!fwin->flags.hide_left_button) {
1166 XMapWindow(dpy, fwin->left_button->window);
1168 fwin->flags.lbutton_dont_fit = 0;
1172 #ifdef XKB_BUTTON_HINT
1173 if (fwin->language_button) {
1174 if (width < fwin->top_width*k && !fwin->flags.languagebutton_dont_fit) {
1176 if (!fwin->flags.hide_language_button) {
1177 XUnmapWindow(dpy, fwin->language_button->window);
1179 fwin->flags.languagebutton_dont_fit = 1;
1180 } else if (width >= fwin->top_width*k && fwin->flags.languagebutton_dont_fit) {
1182 if (!fwin->flags.hide_language_button) {
1183 XMapWindow(dpy, fwin->language_button->window);
1185 fwin->flags.languagebutton_dont_fit = 0;
1188 #endif
1190 if (fwin->right_button) {
1191 if (width < fwin->top_width*2 && !fwin->flags.rbutton_dont_fit) {
1193 if (!fwin->flags.hide_right_button) {
1194 XUnmapWindow(dpy, fwin->right_button->window);
1196 fwin->flags.rbutton_dont_fit = 1;
1197 } else if (width >= fwin->top_width*2 && fwin->flags.rbutton_dont_fit) {
1199 if (!fwin->flags.hide_right_button) {
1200 XMapWindow(dpy, fwin->right_button->window);
1202 fwin->flags.rbutton_dont_fit = 0;
1206 if (wPreferences.new_style) {
1207 if (fwin->right_button)
1208 XMoveWindow(dpy, fwin->right_button->window,
1209 width - fwin->right_button->width + 1, 0);
1210 } else {
1211 if (fwin->right_button)
1212 XMoveWindow(dpy, fwin->right_button->window,
1213 width - fwin->right_button->width - 3,
1214 (fwin->titlebar->height - fwin->right_button->height)/2);
1216 updateTitlebar(fwin);
1217 checkTitleSize(fwin);
1220 if (fwin->resizebar) {
1221 wCoreConfigure(fwin->resizebar, 0,
1222 fwin->core->height - fwin->resizebar->height,
1223 fwin->core->width, fwin->resizebar->height);
1225 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1226 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH*2 + RESIZEBAR_MIN_WIDTH) {
1227 fwin->resizebar_corner_width = fwin->core->width/2;
1232 void
1233 wFrameWindowConfigure(WFrameWindow *fwin, int x, int y, int width, int height)
1235 reconfigure(fwin, x, y, width, height, False);
1238 void
1239 wFrameWindowResize(WFrameWindow *fwin, int width, int height)
1241 reconfigure(fwin, 0, 0, width, height, True);
1246 int
1247 wFrameWindowChangeTitle(WFrameWindow *fwin, char *new_title)
1249 /* check if the title is the same as before */
1250 if (fwin->title) {
1251 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1252 return 0;
1254 } else {
1255 if (!new_title)
1256 return 0;
1259 if (fwin->title)
1260 wfree(fwin->title);
1262 fwin->title = wstrdup(new_title);
1264 if (fwin->titlebar) {
1265 XClearWindow(dpy, fwin->titlebar->window);
1267 wFrameWindowPaint(fwin);
1269 checkTitleSize(fwin);
1271 return 1;
1275 #ifdef OLWM_HINTS
1276 void
1277 wFrameWindowUpdatePushButton(WFrameWindow *fwin, Bool pushed)
1279 fwin->flags.right_button_pushed_in = pushed;
1281 paintButton(fwin->right_button, fwin->title_texture[fwin->flags.state],
1282 WMColorPixel(fwin->title_color[fwin->flags.state]),
1283 fwin->rbutton_image, pushed);
1285 #endif /* OLWM_HINTS */
1288 #ifdef XKB_BUTTON_HINT
1289 void
1290 wFrameWindowUpdateLanguageButton(WFrameWindow *fwin)
1292 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1293 WMColorPixel(fwin->title_color[fwin->flags.state]),
1294 fwin->languagebutton_image, True);
1296 #endif /* XKB_BUTTON_HINT */
1299 /*********************************************************************/
1301 static void
1302 handleExpose(WObjDescriptor *desc, XEvent *event)
1304 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1307 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1308 fwin->flags.repaint_only_titlebar = 1;
1309 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1310 fwin->flags.repaint_only_resizebar = 1;
1311 wFrameWindowPaint(fwin);
1312 fwin->flags.repaint_only_titlebar = 0;
1313 fwin->flags.repaint_only_resizebar = 0;
1317 static void
1318 checkTitleSize(WFrameWindow *fwin)
1320 int width;
1322 if (!fwin->title) {
1323 fwin->flags.incomplete_title = 0;
1324 return;
1327 if (!fwin->titlebar) {
1328 fwin->flags.incomplete_title = 1;
1329 return;
1330 } else {
1331 width = fwin->titlebar->width - 6 - 6;
1334 if (!wPreferences.new_style) {
1335 if (fwin->left_button && !fwin->flags.hide_left_button
1336 && !fwin->flags.lbutton_dont_fit)
1337 width -= fwin->left_button->width + 3;
1339 #ifdef XKB_BUTTON_HINT
1340 if (fwin->language_button && !fwin->flags.hide_language_button
1341 && !fwin->flags.languagebutton_dont_fit)
1342 width -= fwin->language_button->width + 3;
1343 #endif
1345 if (fwin->right_button && !fwin->flags.hide_right_button
1346 && !fwin->flags.rbutton_dont_fit)
1347 width -= fwin->right_button->width + 3;
1349 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1350 fwin->flags.incomplete_title = 1;
1351 } else {
1352 fwin->flags.incomplete_title = 0;
1357 static void
1358 paintButton(WCoreWindow *button, WTexture *texture, unsigned long color,
1359 WPixmap *image, int pushed)
1361 WScreen *scr = button->screen_ptr;
1362 GC copy_gc = scr->copy_gc;
1363 int x=0, y=0, d=0;
1364 int left=0, width=0;
1366 /* setup stuff according to the state */
1367 if (pushed) {
1368 if (image) {
1369 if (image->width>=image->height*2) {
1370 /* the image contains 2 pictures: the second is for the
1371 * pushed state */
1372 width = image->width/2;
1373 left = image->width/2;
1374 } else {
1375 width = image->width;
1378 XSetClipMask(dpy, copy_gc, None);
1379 XSetForeground(dpy, copy_gc, scr->white_pixel);
1380 d=1;
1381 if (wPreferences.new_style) {
1382 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1383 button->width-1, button->height-1);
1384 XSetForeground(dpy, copy_gc, scr->black_pixel);
1385 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1386 button->width-1, button->height-1);
1387 } else {
1388 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1389 button->width, button->height);
1390 XSetForeground(dpy, copy_gc, scr->black_pixel);
1391 XDrawRectangle(dpy, button->window, copy_gc, 0, 0,
1392 button->width, button->height);
1394 } else {
1395 XClearWindow(dpy, button->window);
1397 if (image) {
1398 if (image->width>=image->height*2)
1399 width = image->width/2;
1400 else
1401 width = image->width;
1403 d=0;
1405 if (wPreferences.new_style) {
1406 if (texture->any.type==WTEX_SOLID || pushed) {
1407 wDrawBevel(button->window, button->width, button->height,
1408 (WTexSolid*)texture, WREL_RAISED);
1410 } else {
1411 wDrawBevel(button->window, button->width, button->height,
1412 scr->widget_texture, WREL_RAISED);
1416 if (image) {
1417 /* display image */
1418 XSetClipMask(dpy, copy_gc, image->mask);
1419 x = (button->width - width)/2 + d;
1420 y = (button->height - image->height)/2 + d;
1421 XSetClipOrigin(dpy, copy_gc, x-left, y);
1422 if (!wPreferences.new_style) {
1423 XSetForeground(dpy, copy_gc, scr->black_pixel);
1424 if (!pushed) {
1425 if (image->depth==1)
1426 XCopyPlane(dpy, image->image, button->window, copy_gc,
1427 left, 0, width, image->height, x, y, 1);
1428 else
1429 XCopyArea(dpy, image->image, button->window, copy_gc,
1430 left, 0, width, image->height, x, y);
1431 } else {
1432 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1433 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1434 button->width, button->height);
1436 } else {
1437 if (pushed) {
1438 XSetForeground(dpy, copy_gc, scr->black_pixel);
1439 } else {
1440 XSetForeground(dpy, copy_gc, color);
1441 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1443 XFillRectangle(dpy, button->window, copy_gc, 0, 0,
1444 button->width, button->height);
1450 static void
1451 handleButtonExpose(WObjDescriptor *desc, XEvent *event)
1453 WFrameWindow *fwin = (WFrameWindow*)desc->parent;
1454 WCoreWindow *button = (WCoreWindow*)desc->self;
1456 #ifdef XKB_BUTTON_HINT
1457 if (button == fwin->language_button) {
1458 if (wPreferences.modelock){
1459 paintButton(button, fwin->title_texture[fwin->flags.state],
1460 WMColorPixel(fwin->title_color[fwin->flags.state]),
1461 fwin->languagebutton_image, False);
1463 } else
1464 #endif
1465 if (button == fwin->left_button) {
1466 paintButton(button, fwin->title_texture[fwin->flags.state],
1467 WMColorPixel(fwin->title_color[fwin->flags.state]),
1468 fwin->lbutton_image, False);
1469 } else {
1470 Bool pushed = False;
1472 #ifdef OLWM_HINTS
1473 if (fwin->flags.right_button_pushed_in)
1474 pushed = True;
1475 #endif
1476 /* emulate the olwm pushpin in the "out" state */
1477 paintButton(button, fwin->title_texture[fwin->flags.state],
1478 WMColorPixel(fwin->title_color[fwin->flags.state]),
1479 fwin->rbutton_image, pushed);
1484 static void
1485 titlebarMouseDown(WObjDescriptor *desc, XEvent *event)
1487 WFrameWindow *fwin = desc->parent;
1488 WCoreWindow *titlebar = desc->self;
1490 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1491 if (fwin->on_dblclick_titlebar)
1492 (*fwin->on_dblclick_titlebar)(titlebar, fwin->child, event);
1493 } else {
1494 if (fwin->on_mousedown_titlebar)
1495 (*fwin->on_mousedown_titlebar)(titlebar, fwin->child, event);
1500 static void
1501 resizebarMouseDown(WObjDescriptor *desc, XEvent *event)
1503 WFrameWindow *fwin = desc->parent;
1504 WCoreWindow *resizebar = desc->self;
1506 if (fwin->on_mousedown_resizebar)
1507 (*fwin->on_mousedown_resizebar)(resizebar, fwin->child, event);
1511 static void
1512 buttonMouseDown(WObjDescriptor *desc, XEvent *event)
1514 WFrameWindow *fwin = desc->parent;
1515 WCoreWindow *button = desc->self;
1516 WPixmap *image;
1517 XEvent ev;
1518 int done=0, execute=1;
1519 WTexture *texture;
1520 unsigned long pixel;
1521 int clickButton = event->xbutton.button;
1523 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1524 if (button == fwin->right_button && fwin->on_dblclick_right) {
1525 (*fwin->on_dblclick_right)(button, fwin->child, event);
1527 return;
1530 if (button == fwin->left_button) {
1531 image = fwin->lbutton_image;
1532 } else {
1533 image = fwin->rbutton_image;
1535 #ifdef XKB_BUTTON_HINT
1536 if (button == fwin->language_button) {
1537 if (!wPreferences.modelock) return;
1538 image = fwin->languagebutton_image;
1540 #endif
1542 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1543 texture = fwin->title_texture[fwin->flags.state];
1544 paintButton(button, texture, pixel, image, True);
1546 while (!done) {
1547 WMMaskEvent(dpy, LeaveWindowMask|EnterWindowMask|ButtonReleaseMask
1548 |ButtonPressMask|ExposureMask, &ev);
1549 switch (ev.type) {
1550 case LeaveNotify:
1551 execute = 0;
1552 paintButton(button, texture, pixel, image, False);
1553 break;
1555 case EnterNotify:
1556 execute = 1;
1557 paintButton(button, texture, pixel, image, True);
1558 break;
1560 case ButtonPress:
1561 break;
1563 case ButtonRelease:
1564 if (ev.xbutton.button == clickButton)
1565 done = 1;
1566 break;
1568 default:
1569 WMHandleEvent(&ev);
1572 paintButton(button, texture, pixel, image, False);
1574 if (execute) {
1575 if (button == fwin->left_button) {
1576 if (fwin->on_click_left)
1577 (*fwin->on_click_left)(button, fwin->child, &ev);
1578 } else if (button == fwin->right_button) {
1579 if (fwin->on_click_right)
1580 (*fwin->on_click_right)(button, fwin->child, &ev);
1582 #ifdef XKB_BUTTON_HINT
1583 else if (button == fwin->language_button) {
1584 if (fwin->on_click_language)
1585 (*fwin->on_click_language)(button, fwin->child, &ev);
1587 #endif