Change to the linux kernel coding style
[wmaker-crm.git] / src / framewin.c
1 /*
2 * Window Maker window manager
3 *
4 * Copyright (c) 1997-2003 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.
10 *
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.
15 *
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.
20 */
21
22 #include "wconfig.h"
23
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 */
29
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <wraster.h>
34
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"
43
44 #define DBLCLICK_TIME wPreferences.dblclick_time
45
46 extern WPreferences wPreferences;
47
48 static void handleExpose(WObjDescriptor * desc, XEvent * event);
49 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event);
50
51 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event);
52 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event);
53 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event);
54
55 static void checkTitleSize(WFrameWindow * fwin);
56
57 static void paintButton(WCoreWindow * button, WTexture * texture,
58 unsigned long color, WPixmap * image, int pushed);
59
60 static void updateTitlebar(WFrameWindow * fwin);
61
62 WFrameWindow *wFrameWindowCreate(WScreen * scr, int wlevel, int x, int y,
63 int width, int height, int *clearance, int flags,
64 WTexture ** title_texture, WTexture ** resize_texture,
65 WMColor ** color, WMFont ** font)
66 {
67 WFrameWindow *fwin;
68
69 fwin = wmalloc(sizeof(WFrameWindow));
70 memset(fwin, 0, sizeof(WFrameWindow));
71
72 fwin->screen_ptr = scr;
73
74 fwin->flags.single_texture = (flags & WFF_SINGLE_STATE) ? 1 : 0;
75
76 fwin->title_texture = title_texture;
77 fwin->resizebar_texture = resize_texture;
78 fwin->title_color = color;
79 fwin->title_clearance = clearance;
80 fwin->font = font;
81 #ifdef KEEP_XKB_LOCK_STATUS
82 fwin->languagemode = XkbGroup1Index;
83 fwin->last_languagemode = XkbGroup2Index;
84 #endif
85
86 fwin->core = wCoreCreateTopLevel(scr, x, y, width, height, (flags & WFF_BORDER)
87 ? FRAME_BORDER_WIDTH : 0);
88 if (wPreferences.use_saveunders) {
89 unsigned long vmask;
90 XSetWindowAttributes attribs;
91
92 vmask = CWSaveUnder;
93 attribs.save_under = True;
94 XChangeWindowAttributes(dpy, fwin->core->window, vmask, &attribs);
95 }
96
97 /* setup stacking information */
98 fwin->core->stacking = wmalloc(sizeof(WStacking));
99 fwin->core->stacking->above = NULL;
100 fwin->core->stacking->under = NULL;
101 fwin->core->stacking->child_of = NULL;
102 fwin->core->stacking->window_level = wlevel;
103
104 AddToStackList(fwin->core);
105
106 wFrameWindowUpdateBorders(fwin, flags);
107
108 return fwin;
109 }
110
111 void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
112 {
113 int theight;
114 int bsize;
115 int width, height;
116 int i;
117 WScreen *scr = fwin->screen_ptr;
118
119 width = fwin->core->width;
120 if (flags & WFF_IS_SHADED)
121 height = -1;
122 else
123 height = fwin->core->height - fwin->top_width - fwin->bottom_width;
124
125 if (flags & WFF_TITLEBAR)
126 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
127 else
128 theight = 0;
129
130 if (wPreferences.new_style) {
131 bsize = theight;
132 } else {
133 bsize = theight - 7;
134 }
135
136 if (fwin->titlebar) {
137 /* if we had a titlebar and is requesting for one,
138 * check if the size has changed and resize it */
139 if (flags & WFF_TITLEBAR) {
140 fwin->top_width = theight;
141
142 fwin->flags.need_texture_remake = 1;
143
144 if (wPreferences.new_style) {
145 if (fwin->left_button) {
146 wCoreConfigure(fwin->left_button, 0, 0, bsize, bsize);
147 }
148 #ifdef XKB_BUTTON_HINT
149 if (fwin->language_button)
150 if (fwin->flags.hide_left_button || !fwin->left_button
151 || fwin->flags.lbutton_dont_fit) {
152 wCoreConfigure(fwin->language_button, 0, 0, bsize, bsize);
153 } else {
154 wCoreConfigure(fwin->language_button, bsize, 0, bsize, bsize);
155 }
156 #endif
157
158 if (fwin->right_button) {
159 wCoreConfigure(fwin->right_button, width - bsize + 1, 0, bsize, bsize);
160 }
161 } else { /* !new_style */
162 if (fwin->left_button) {
163 wCoreConfigure(fwin->left_button, 3, (theight - bsize) / 2, bsize, bsize);
164 }
165 #ifdef XKB_BUTTON_HINT
166 if (fwin->language_button) {
167 wCoreConfigure(fwin->language_button, 6 + bsize, (theight - bsize) / 2,
168 bsize, bsize);
169 }
170 #endif
171
172 if (fwin->right_button) {
173 wCoreConfigure(fwin->right_button, width - bsize - 3,
174 (theight - bsize) / 2, bsize, bsize);
175 }
176 }
177 updateTitlebar(fwin);
178 } else {
179 /* we had a titlebar, but now we don't need it anymore */
180 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
181 FREE_PIXMAP(fwin->title_back[i]);
182 if (wPreferences.new_style) {
183 FREE_PIXMAP(fwin->lbutton_back[i]);
184 FREE_PIXMAP(fwin->rbutton_back[i]);
185 #ifdef XKB_BUTTON_HINT
186 FREE_PIXMAP(fwin->languagebutton_back[i]);
187 #endif
188 }
189 }
190 if (fwin->left_button)
191 wCoreDestroy(fwin->left_button);
192 fwin->left_button = NULL;
193
194 #ifdef XKB_BUTTON_HINT
195 if (fwin->language_button)
196 wCoreDestroy(fwin->language_button);
197 fwin->language_button = NULL;
198 #endif
199
200 if (fwin->right_button)
201 wCoreDestroy(fwin->right_button);
202 fwin->right_button = NULL;
203
204 wCoreDestroy(fwin->titlebar);
205 fwin->titlebar = NULL;
206
207 fwin->top_width = 0;
208 }
209 } else {
210 /* if we didn't have a titlebar and are being requested for
211 * one, create it */
212 if (flags & WFF_TITLEBAR) {
213 fwin->top_width = theight;
214
215 fwin->flags.titlebar = 1;
216 fwin->titlebar = wCoreCreate(fwin->core, 0, 0, width + 1, theight);
217
218 if (flags & WFF_LEFT_BUTTON) {
219 fwin->flags.left_button = 1;
220 if (wPreferences.new_style) {
221 fwin->left_button = wCoreCreate(fwin->core, 0, 0, bsize, bsize);
222 if (width < theight * 4) {
223 fwin->flags.lbutton_dont_fit = 1;
224 } else {
225 XMapRaised(dpy, fwin->left_button->window);
226 }
227 } else {
228 fwin->left_button =
229 wCoreCreate(fwin->titlebar, 3, (theight - bsize) / 2, bsize, bsize);
230
231 XSetWindowBackground(dpy, fwin->left_button->window,
232 scr->widget_texture->normal.pixel);
233
234 if (width < theight * 3) {
235 fwin->flags.lbutton_dont_fit = 1;
236 } else {
237 XMapRaised(dpy, fwin->left_button->window);
238 }
239 }
240 }
241 #ifdef XKB_BUTTON_HINT
242 if (flags & WFF_LANGUAGE_BUTTON) {
243 fwin->flags.language_button = 1;
244 if (wPreferences.new_style) {
245 fwin->language_button = wCoreCreate(fwin->core, bsize, 0, bsize, bsize);
246
247 if (width < theight * 4) {
248 fwin->flags.languagebutton_dont_fit = 1;
249 } else {
250 XMapRaised(dpy, fwin->language_button->window);
251 }
252 } else {
253 fwin->language_button =
254 wCoreCreate(fwin->titlebar, bsize + 6, (theight - bsize) / 2,
255 bsize, bsize);
256
257 XSetWindowBackground(dpy, fwin->language_button->window,
258 scr->widget_texture->normal.pixel);
259
260 if (width < theight * 3) {
261 fwin->flags.languagebutton_dont_fit = 1;
262 } else {
263 XMapRaised(dpy, fwin->language_button->window);
264 }
265 }
266 }
267 #endif
268
269 if (flags & WFF_RIGHT_BUTTON) {
270 fwin->flags.right_button = 1;
271 if (wPreferences.new_style) {
272 fwin->right_button =
273 wCoreCreate(fwin->core, width - bsize + 1, 0, bsize, bsize);
274 } else {
275 fwin->right_button =
276 wCoreCreate(fwin->titlebar, width - bsize - 3,
277 (theight - bsize) / 2, bsize, bsize);
278 XSetWindowBackground(dpy, fwin->right_button->window,
279 scr->widget_texture->normal.pixel);
280 }
281
282 if (width < theight * 2) {
283 fwin->flags.rbutton_dont_fit = 1;
284 } else {
285 XMapRaised(dpy, fwin->right_button->window);
286 }
287 }
288
289 if (wPreferences.new_style)
290 updateTitlebar(fwin);
291
292 XMapRaised(dpy, fwin->titlebar->window);
293
294 fwin->flags.need_texture_remake = 1;
295 }
296 }
297 checkTitleSize(fwin);
298
299 if (flags & WFF_RESIZEBAR) {
300 fwin->bottom_width = RESIZEBAR_HEIGHT;
301
302 if (!fwin->resizebar) {
303 fwin->flags.resizebar = 1;
304 fwin->resizebar = wCoreCreate(fwin->core, 0,
305 height + fwin->top_width, width, RESIZEBAR_HEIGHT);
306 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
307 if (width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
308 fwin->resizebar_corner_width = (width - RESIZEBAR_MIN_WIDTH) / 2;
309 if (fwin->resizebar_corner_width < 0)
310 fwin->resizebar_corner_width = 0;
311 }
312
313 XMapWindow(dpy, fwin->resizebar->window);
314 XLowerWindow(dpy, fwin->resizebar->window);
315
316 fwin->flags.need_texture_remake = 1;
317 } else {
318 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height) {
319 wCoreConfigure(fwin->resizebar, 0, height + fwin->top_width,
320 width, RESIZEBAR_HEIGHT);
321 }
322 }
323 } else {
324 fwin->bottom_width = 0;
325
326 if (fwin->resizebar) {
327 fwin->bottom_width = 0;
328 wCoreDestroy(fwin->resizebar);
329 fwin->resizebar = NULL;
330 }
331 }
332
333 if (height + fwin->top_width + fwin->bottom_width != fwin->core->height && !(flags & WFF_IS_SHADED)) {
334 wFrameWindowResize(fwin, width, height + fwin->top_width + fwin->bottom_width);
335 }
336
337 if (flags & WFF_BORDER) {
338 XSetWindowBorderWidth(dpy, fwin->core->window, FRAME_BORDER_WIDTH);
339 } else {
340 XSetWindowBorderWidth(dpy, fwin->core->window, 0);
341 }
342
343 /* setup object descriptors */
344
345 if (fwin->titlebar) {
346 fwin->titlebar->descriptor.handle_expose = handleExpose;
347 fwin->titlebar->descriptor.parent = fwin;
348 fwin->titlebar->descriptor.parent_type = WCLASS_FRAME;
349 fwin->titlebar->descriptor.handle_mousedown = titlebarMouseDown;
350 }
351
352 if (fwin->resizebar) {
353 fwin->resizebar->descriptor.handle_expose = handleExpose;
354 fwin->resizebar->descriptor.parent = fwin;
355 fwin->resizebar->descriptor.parent_type = WCLASS_FRAME;
356 fwin->resizebar->descriptor.handle_mousedown = resizebarMouseDown;
357 }
358
359 if (fwin->left_button) {
360 fwin->left_button->descriptor.handle_expose = handleButtonExpose;
361 fwin->left_button->descriptor.parent = fwin;
362 fwin->left_button->descriptor.parent_type = WCLASS_FRAME;
363 fwin->left_button->descriptor.handle_mousedown = buttonMouseDown;
364 }
365 #ifdef XKB_BUTTON_HINT
366 if (fwin->language_button) {
367 fwin->language_button->descriptor.handle_expose = handleButtonExpose;
368 fwin->language_button->descriptor.parent = fwin;
369 fwin->language_button->descriptor.parent_type = WCLASS_FRAME;
370 fwin->language_button->descriptor.handle_mousedown = buttonMouseDown;
371 }
372 #endif
373
374 if (fwin->right_button) {
375 fwin->right_button->descriptor.parent = fwin;
376 fwin->right_button->descriptor.parent_type = WCLASS_FRAME;
377 fwin->right_button->descriptor.handle_expose = handleButtonExpose;
378 fwin->right_button->descriptor.handle_mousedown = buttonMouseDown;
379 }
380
381 checkTitleSize(fwin);
382 }
383
384 void wFrameWindowDestroy(WFrameWindow * fwin)
385 {
386 int i;
387
388 if (fwin->left_button)
389 wCoreDestroy(fwin->left_button);
390
391 #ifdef XKB_BUTTON_HINT
392 if (fwin->language_button)
393 wCoreDestroy(fwin->language_button);
394 #endif
395
396 if (fwin->right_button)
397 wCoreDestroy(fwin->right_button);
398
399 if (fwin->resizebar)
400 wCoreDestroy(fwin->resizebar);
401
402 if (fwin->titlebar)
403 wCoreDestroy(fwin->titlebar);
404
405 RemoveFromStackList(fwin->core);
406
407 wCoreDestroy(fwin->core);
408
409 if (fwin->title)
410 wfree(fwin->title);
411
412 for (i = 0; i < (fwin->flags.single_texture ? 1 : 3); i++) {
413 FREE_PIXMAP(fwin->title_back[i]);
414 if (wPreferences.new_style) {
415 FREE_PIXMAP(fwin->lbutton_back[i]);
416 #ifdef XKB_BUTTON_HINT
417 FREE_PIXMAP(fwin->languagebutton_back[i]);
418 #endif
419 FREE_PIXMAP(fwin->rbutton_back[i]);
420 }
421 }
422
423 wfree(fwin);
424 }
425
426 void wFrameWindowChangeState(WFrameWindow * fwin, int state)
427 {
428 if (fwin->flags.state == state)
429 return;
430
431 fwin->flags.state = state;
432 fwin->flags.need_texture_change = 1;
433
434 wFrameWindowPaint(fwin);
435 }
436
437 static void updateTitlebar(WFrameWindow * fwin)
438 {
439 int x, w;
440 int theight;
441
442 theight = WMFontHeight(*fwin->font) + (*fwin->title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
443
444 x = 0;
445 w = fwin->core->width + 1;
446
447 if (wPreferences.new_style) {
448 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
449 x = 0;
450 #ifdef XKB_BUTTON_HINT
451 if (fwin->language_button)
452 wCoreConfigure(fwin->language_button, 0, 0,
453 fwin->language_button->width, fwin->language_button->width);
454 #endif
455 } else {
456 #ifdef XKB_BUTTON_HINT
457 if (fwin->language_button)
458 wCoreConfigure(fwin->language_button, fwin->left_button->width, 0,
459 fwin->language_button->width, fwin->language_button->width);
460 #endif
461 x = fwin->left_button->width;
462 w -= fwin->left_button->width;
463 }
464 #ifdef XKB_BUTTON_HINT
465 if (fwin->flags.hide_language_button || !fwin->language_button
466 || fwin->flags.languagebutton_dont_fit) {
467 } else {
468 x += fwin->language_button->width;
469 w -= fwin->language_button->width;
470 }
471 #endif
472 }
473 #ifdef XKB_BUTTON_HINT
474 else {
475 int bsize = theight - 7;
476 if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
477 if (fwin->language_button)
478 wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
479 fwin->language_button->width, fwin->language_button->width);
480 } else {
481 if (fwin->language_button)
482 wCoreConfigure(fwin->language_button,
483 6 + fwin->left_button->width, (theight - bsize) / 2,
484 fwin->language_button->width, fwin->language_button->width);
485 }
486 }
487 #endif
488
489 if (wPreferences.new_style) {
490 if (!fwin->flags.hide_right_button && fwin->right_button && !fwin->flags.rbutton_dont_fit) {
491 w -= fwin->right_button->width;
492 }
493 }
494
495 if (wPreferences.new_style || fwin->titlebar->width != w)
496 fwin->flags.need_texture_remake = 1;
497
498 wCoreConfigure(fwin->titlebar, x, 0, w, theight);
499 }
500
501 void wFrameWindowHideButton(WFrameWindow * fwin, int flags)
502 {
503 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button) {
504 XUnmapWindow(dpy, fwin->right_button->window);
505 fwin->flags.hide_right_button = 1;
506 }
507
508 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button) {
509 XUnmapWindow(dpy, fwin->left_button->window);
510 fwin->flags.hide_left_button = 1;
511 }
512 #ifdef XKB_BUTTON_HINT
513 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button) {
514 XUnmapWindow(dpy, fwin->language_button->window);
515 fwin->flags.hide_language_button = 1;
516 }
517 #endif
518
519 if (fwin->titlebar) {
520 if (wPreferences.new_style) {
521 updateTitlebar(fwin);
522 } else {
523 #ifdef XKB_BUTTON_HINT
524 updateTitlebar(fwin);
525 #else
526 XClearWindow(dpy, fwin->titlebar->window);
527 wFrameWindowPaint(fwin);
528 #endif
529 }
530 checkTitleSize(fwin);
531 }
532 }
533
534 void wFrameWindowShowButton(WFrameWindow * fwin, int flags)
535 {
536 if ((flags & WFF_RIGHT_BUTTON) && fwin->right_button && fwin->flags.hide_right_button) {
537
538 if (!fwin->flags.rbutton_dont_fit)
539 XMapWindow(dpy, fwin->right_button->window);
540
541 fwin->flags.hide_right_button = 0;
542 }
543 #ifdef XKB_BUTTON_HINT
544 if ((flags & WFF_LANGUAGE_BUTTON) && fwin->language_button && fwin->flags.hide_language_button) {
545
546 if (!fwin->flags.languagebutton_dont_fit)
547 XMapWindow(dpy, fwin->language_button->window);
548
549 fwin->flags.hide_language_button = 0;
550 }
551 #endif
552
553 if ((flags & WFF_LEFT_BUTTON) && fwin->left_button && fwin->flags.hide_left_button) {
554
555 if (!fwin->flags.lbutton_dont_fit)
556 XMapWindow(dpy, fwin->left_button->window);
557
558 fwin->flags.hide_left_button = 0;
559 }
560
561 if (fwin->titlebar) {
562 if (wPreferences.new_style) {
563 updateTitlebar(fwin);
564 } else {
565 XClearWindow(dpy, fwin->titlebar->window);
566 wFrameWindowPaint(fwin);
567 }
568 checkTitleSize(fwin);
569 }
570 }
571
572 static void
573 #ifdef XKB_BUTTON_HINT
574 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
575 int bwidth, int bheight, int left, int language, int right,
576 Pixmap * title, Pixmap * lbutton, Pixmap * languagebutton, Pixmap * rbutton)
577 #else
578 renderTexture(WScreen * scr, WTexture * texture, int width, int height,
579 int bwidth, int bheight, int left, int right, Pixmap * title, Pixmap * lbutton, Pixmap * rbutton)
580 #endif
581 {
582 RImage *img;
583 RImage *limg, *rimg, *mimg;
584 #ifdef XKB_BUTTON_HINT
585 RImage *timg;
586 #endif
587 int x, w;
588
589 *title = None;
590 *lbutton = None;
591 *rbutton = None;
592 #ifdef XKB_BUTTON_HINT
593 *languagebutton = None;
594 #endif
595
596 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
597 if (!img) {
598 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
599 return;
600 }
601
602 if (wPreferences.new_style) {
603 if (left) {
604 limg = RGetSubImage(img, 0, 0, bwidth, bheight);
605 } else
606 limg = NULL;
607
608 x = 0;
609 w = img->width;
610
611 #ifdef XKB_BUTTON_HINT
612 if (language) {
613 timg = RGetSubImage(img, bwidth * left, 0, bwidth, bheight);
614 } else
615 timg = NULL;
616 #endif
617
618 if (limg) {
619 RBevelImage(limg, RBEV_RAISED2);
620 if (!RConvertImage(scr->rcontext, limg, lbutton)) {
621 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
622 }
623 x += limg->width;
624 w -= limg->width;
625 RReleaseImage(limg);
626 }
627 #ifdef XKB_BUTTON_HINT
628 if (timg) {
629 RBevelImage(timg, RBEV_RAISED2);
630 if (!RConvertImage(scr->rcontext, timg, languagebutton)) {
631 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
632 }
633 x += timg->width;
634 w -= timg->width;
635 RReleaseImage(timg);
636 }
637 #endif
638
639 if (right) {
640 rimg = RGetSubImage(img, width - bwidth, 0, bwidth, bheight);
641 } else
642 rimg = NULL;
643
644 if (rimg) {
645 RBevelImage(rimg, RBEV_RAISED2);
646 if (!RConvertImage(scr->rcontext, rimg, rbutton)) {
647 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
648 }
649 w -= rimg->width;
650 RReleaseImage(rimg);
651 }
652
653 if (w != width) {
654 mimg = RGetSubImage(img, x, 0, w, img->height);
655 RBevelImage(mimg, RBEV_RAISED2);
656
657 if (!RConvertImage(scr->rcontext, mimg, title)) {
658 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
659 }
660 RReleaseImage(mimg);
661 } else {
662 RBevelImage(img, RBEV_RAISED2);
663
664 if (!RConvertImage(scr->rcontext, img, title)) {
665 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
666 }
667 }
668 } else {
669 RBevelImage(img, RBEV_RAISED2);
670
671 if (!RConvertImage(scr->rcontext, img, title)) {
672 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode));
673 }
674 }
675
676 RReleaseImage(img);
677 }
678
679 static void
680 renderResizebarTexture(WScreen * scr, WTexture * texture, int width, int height, int cwidth, Pixmap * pmap)
681 {
682 RImage *img;
683 RColor light;
684 RColor dark;
685
686 *pmap = None;
687
688 img = wTextureRenderImage(texture, width, height, WREL_FLAT);
689 if (!img) {
690 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
691 return;
692 }
693
694 light.alpha = 0;
695 light.red = light.green = light.blue = 80;
696
697 dark.alpha = 0;
698 dark.red = dark.green = dark.blue = 40;
699
700 ROperateLine(img, RSubtractOperation, 0, 0, width - 1, 0, &dark);
701 ROperateLine(img, RAddOperation, 0, 1, width - 1, 1, &light);
702
703 ROperateLine(img, RSubtractOperation, cwidth, 2, cwidth, height - 1, &dark);
704 ROperateLine(img, RAddOperation, cwidth + 1, 2, cwidth + 1, height - 1, &light);
705
706 if (width > 1)
707 ROperateLine(img, RSubtractOperation, width - cwidth - 2, 2,
708 width - cwidth - 2, height - 1, &dark);
709 ROperateLine(img, RAddOperation, width - cwidth - 1, 2, width - cwidth - 1, height - 1, &light);
710
711 #ifdef SHADOW_RESIZEBAR
712 ROperateLine(img, RAddOperation, 0, 1, 0, height - 1, &light);
713 ROperateLine(img, RSubtractOperation, width - 1, 1, width - 1, height - 1, &dark);
714 ROperateLine(img, RSubtractOperation, 0, height - 1, width - 1, height - 1, &dark);
715 #endif /* SHADOW_RESIZEBAR */
716
717 if (!RConvertImage(scr->rcontext, img, pmap)) {
718 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode));
719 }
720
721 RReleaseImage(img);
722 }
723
724 static void updateTexture(WFrameWindow * fwin)
725 {
726 int i;
727 unsigned long pixel;
728
729 i = fwin->flags.state;
730 if (fwin->titlebar) {
731 if (fwin->title_texture[i]->any.type != WTEX_SOLID) {
732 XSetWindowBackgroundPixmap(dpy, fwin->titlebar->window, fwin->title_back[i]);
733 if (wPreferences.new_style) {
734 if (fwin->left_button && fwin->lbutton_back[i])
735 XSetWindowBackgroundPixmap(dpy, fwin->left_button->window,
736 fwin->lbutton_back[i]);
737
738 #ifdef XKB_BUTTON_HINT
739 if (fwin->language_button && fwin->languagebutton_back[i]) {
740 XSetWindowBackgroundPixmap(dpy, fwin->language_button->window,
741 fwin->languagebutton_back[i]);
742 }
743 #endif
744
745 if (fwin->right_button && fwin->rbutton_back[i])
746 XSetWindowBackgroundPixmap(dpy, fwin->right_button->window,
747 fwin->rbutton_back[i]);
748 }
749 } else {
750 pixel = fwin->title_texture[i]->solid.normal.pixel;
751 XSetWindowBackground(dpy, fwin->titlebar->window, pixel);
752 if (wPreferences.new_style) {
753 if (fwin->left_button)
754 XSetWindowBackground(dpy, fwin->left_button->window, pixel);
755 #ifdef XKB_BUTTON_HINT
756 if (fwin->language_button)
757 XSetWindowBackground(dpy, fwin->language_button->window, pixel);
758 #endif
759 if (fwin->right_button)
760 XSetWindowBackground(dpy, fwin->right_button->window, pixel);
761 }
762 }
763 XClearWindow(dpy, fwin->titlebar->window);
764
765 if (fwin->left_button) {
766 XClearWindow(dpy, fwin->left_button->window);
767 handleButtonExpose(&fwin->left_button->descriptor, NULL);
768 }
769 #ifdef XKB_BUTTON_HINT
770 if (fwin->language_button) {
771 XClearWindow(dpy, fwin->language_button->window);
772 handleButtonExpose(&fwin->language_button->descriptor, NULL);
773 }
774 #endif
775 if (fwin->right_button) {
776 XClearWindow(dpy, fwin->right_button->window);
777 handleButtonExpose(&fwin->right_button->descriptor, NULL);
778 }
779 }
780 }
781
782 static void remakeTexture(WFrameWindow * fwin, int state)
783 {
784 Pixmap pmap, lpmap, rpmap;
785 #ifdef XKB_BUTTON_HINT
786 Pixmap tpmap;
787 #endif
788
789 if (fwin->title_texture[state] && fwin->titlebar) {
790 FREE_PIXMAP(fwin->title_back[state]);
791 if (wPreferences.new_style) {
792 FREE_PIXMAP(fwin->lbutton_back[state]);
793 FREE_PIXMAP(fwin->rbutton_back[state]);
794 #ifdef XKB_BUTTON_HINT
795 FREE_PIXMAP(fwin->languagebutton_back[state]);
796 #endif
797 }
798
799 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
800 int left, right;
801 int width;
802 #ifdef XKB_BUTTON_HINT
803 int language;
804 #endif
805
806 /* eventually surrounded by if new_style */
807 left = fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit;
808 #ifdef XKB_BUTTON_HINT
809 language = fwin->language_button && !fwin->flags.hide_language_button
810 && !fwin->flags.languagebutton_dont_fit;
811 #endif
812 right = fwin->right_button && !fwin->flags.hide_right_button
813 && !fwin->flags.rbutton_dont_fit;
814
815 width = fwin->core->width + 1;
816
817 #ifdef XKB_BUTTON_HINT
818 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
819 width, fwin->titlebar->height,
820 fwin->titlebar->height, fwin->titlebar->height,
821 left, language, right, &pmap, &lpmap, &tpmap, &rpmap);
822 #else
823 renderTexture(fwin->screen_ptr, fwin->title_texture[state],
824 width, fwin->titlebar->height,
825 fwin->titlebar->height, fwin->titlebar->height,
826 left, right, &pmap, &lpmap, &rpmap);
827 #endif
828
829 fwin->title_back[state] = pmap;
830 if (wPreferences.new_style) {
831 fwin->lbutton_back[state] = lpmap;
832 fwin->rbutton_back[state] = rpmap;
833 #ifdef XKB_BUTTON_HINT
834 fwin->languagebutton_back[state] = tpmap;
835 #endif
836 }
837 }
838 }
839 if (fwin->resizebar_texture && fwin->resizebar_texture[0]
840 && fwin->resizebar && state == 0) {
841
842 FREE_PIXMAP(fwin->resizebar_back[0]);
843
844 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
845
846 renderResizebarTexture(fwin->screen_ptr,
847 fwin->resizebar_texture[0],
848 fwin->resizebar->width,
849 fwin->resizebar->height, fwin->resizebar_corner_width, &pmap);
850
851 fwin->resizebar_back[0] = pmap;
852 }
853
854 /* this part should be in updateTexture() */
855 if (fwin->resizebar_texture[0]->any.type != WTEX_SOLID) {
856 XSetWindowBackgroundPixmap(dpy, fwin->resizebar->window, fwin->resizebar_back[0]);
857 } else {
858 XSetWindowBackground(dpy, fwin->resizebar->window,
859 fwin->resizebar_texture[0]->solid.normal.pixel);
860 }
861 XClearWindow(dpy, fwin->resizebar->window);
862 }
863 }
864
865 void wFrameWindowPaint(WFrameWindow * fwin)
866 {
867 WScreen *scr = fwin->screen_ptr;
868 int state;
869
870 state = fwin->flags.state;
871
872 if (fwin->flags.is_client_window_frame)
873 fwin->flags.justification = wPreferences.title_justification;
874
875 if (fwin->flags.need_texture_remake) {
876 int i;
877
878 fwin->flags.need_texture_remake = 0;
879 fwin->flags.need_texture_change = 0;
880
881 if (fwin->flags.single_texture) {
882 remakeTexture(fwin, 0);
883 updateTexture(fwin);
884 } else {
885 /* first render the texture for the current state... */
886 remakeTexture(fwin, state);
887 /* ... and paint it */
888 updateTexture(fwin);
889
890 for (i = 0; i < 3; i++) {
891 if (i != state) {
892 remakeTexture(fwin, i);
893 }
894 }
895 }
896 }
897
898 if (fwin->flags.need_texture_change) {
899 fwin->flags.need_texture_change = 0;
900
901 updateTexture(fwin);
902 }
903
904 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar
905 && fwin->title_texture[state]->any.type == WTEX_SOLID) {
906 wDrawBevel(fwin->titlebar->window, fwin->titlebar->width,
907 fwin->titlebar->height, (WTexSolid *) fwin->title_texture[state], WREL_RAISED);
908 }
909
910 if (fwin->resizebar && !fwin->flags.repaint_only_titlebar
911 && fwin->resizebar_texture[0]->any.type == WTEX_SOLID) {
912 Window win;
913 int w, h;
914 int cw;
915 GC light_gc, dim_gc;
916 WTexSolid *texture = (WTexSolid *) fwin->resizebar_texture[0];
917
918 w = fwin->resizebar->width;
919 h = fwin->resizebar->height;
920 cw = fwin->resizebar_corner_width;
921 light_gc = texture->light_gc;
922 dim_gc = texture->dim_gc;
923 win = fwin->resizebar->window;
924
925 XDrawLine(dpy, win, dim_gc, 0, 0, w, 0);
926 XDrawLine(dpy, win, light_gc, 0, 1, w, 1);
927
928 XDrawLine(dpy, win, dim_gc, cw, 2, cw, h);
929 XDrawLine(dpy, win, light_gc, cw + 1, 2, cw + 1, h);
930
931 XDrawLine(dpy, win, dim_gc, w - cw - 2, 2, w - cw - 2, h);
932 XDrawLine(dpy, win, light_gc, w - cw - 1, 2, w - cw - 1, h);
933
934 #ifdef SHADOW_RESIZEBAR
935 XDrawLine(dpy, win, light_gc, 0, 1, 0, h - 1);
936 XDrawLine(dpy, win, dim_gc, w - 1, 2, w - 1, h - 1);
937 XDrawLine(dpy, win, dim_gc, 1, h - 1, cw, h - 1);
938 XDrawLine(dpy, win, dim_gc, cw + 2, h - 1, w - cw - 2, h - 1);
939 XDrawLine(dpy, win, dim_gc, w - cw, h - 1, w - 1, h - 1);
940 #endif /* SHADOW_RESIZEBAR */
941 }
942
943 if (fwin->titlebar && !fwin->flags.repaint_only_resizebar) {
944 int x, y, w, h;
945 int lofs = 6, rofs = 6;
946 int titlelen;
947 int allButtons = 1;
948
949 if (!wPreferences.new_style) {
950 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
951 lofs += fwin->left_button->width + 3;
952 else
953 allButtons = 0;
954
955 #ifdef XKB_BUTTON_HINT
956 if (fwin->language_button && !fwin->flags.hide_language_button
957 && !fwin->flags.languagebutton_dont_fit)
958 lofs += fwin->language_button->width;
959 else
960 allButtons = 0;
961 #endif
962
963 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
964 rofs += fwin->right_button->width + 3;
965 else
966 allButtons = 0;
967 }
968 #ifdef XKB_BUTTON_HINT
969 fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
970 #endif
971
972 if (fwin->title) {
973 Drawable buf;
974 char *title;
975
976 title = ShrinkString(*fwin->font, fwin->title, fwin->titlebar->width - lofs - rofs);
977 titlelen = strlen(title);
978 w = WMWidthOfString(*fwin->font, title, titlelen);
979
980 switch (fwin->flags.justification) {
981 case WTJ_LEFT:
982 x = lofs;
983 break;
984
985 case WTJ_RIGHT:
986 x = fwin->titlebar->width - w - rofs;
987 break;
988
989 default:
990 if (!allButtons)
991 x = lofs + (fwin->titlebar->width - w - lofs - rofs) / 2;
992 else
993 x = (fwin->titlebar->width - w) / 2;
994 break;
995 }
996
997 y = *fwin->title_clearance + TITLEBAR_EXTEND_SPACE;
998 h = WMFontHeight(*fwin->font);
999
1000 /* We use a w+2 buffer to have an extra pixel on the left and
1001 * another one on the right. This is because for some odd reason,
1002 * sometimes when using AA fonts (when libfreetype2 is compiled
1003 * with bytecode interpreter turned off), some fonts are drawn
1004 * starting from x = -1 not from 0 as requested. Observed with
1005 * capital A letter on the bold 'trebuchet ms' font. -Dan
1006 */
1007 buf = XCreatePixmap(dpy, fwin->titlebar->window, w + 2, h, scr->w_depth);
1008
1009 XSetClipMask(dpy, scr->copy_gc, None);
1010
1011 if (fwin->title_texture[state]->any.type != WTEX_SOLID) {
1012 XCopyArea(dpy, fwin->title_back[state], buf, scr->copy_gc,
1013 x - 1, y, w + 2, h, 0, 0);
1014 } else {
1015 XSetForeground(dpy, scr->copy_gc, fwin->title_texture[state]->solid.normal.pixel);
1016 XFillRectangle(dpy, buf, scr->copy_gc, 0, 0, w + 2, h);
1017 }
1018
1019 /*XDrawRectangle(dpy, buf, WMColorGC(scr->white),1,0,w,h-1); */
1020 WMDrawString(scr->wmscreen, buf, fwin->title_color[state],
1021 *fwin->font, 1, 0, title, titlelen);
1022
1023 XCopyArea(dpy, buf, fwin->titlebar->window, scr->copy_gc, 0, 0, w + 2, h, x - 1, y);
1024
1025 XFreePixmap(dpy, buf);
1026
1027 wfree(title);
1028 }
1029
1030 if (fwin->left_button)
1031 handleButtonExpose(&fwin->left_button->descriptor, NULL);
1032 if (fwin->right_button)
1033 handleButtonExpose(&fwin->right_button->descriptor, NULL);
1034 #ifdef XKB_BUTTON_HINT
1035 if (fwin->language_button)
1036 handleButtonExpose(&fwin->language_button->descriptor, NULL);
1037 #endif
1038 }
1039 }
1040
1041 static void reconfigure(WFrameWindow * fwin, int x, int y, int width, int height, Bool dontMove)
1042 {
1043 int k = (wPreferences.new_style ? 4 : 3);
1044 int resizedHorizontally = 0;
1045
1046 if (dontMove)
1047 XResizeWindow(dpy, fwin->core->window, width, height);
1048 else
1049 XMoveResizeWindow(dpy, fwin->core->window, x, y, width, height);
1050
1051 /*
1052 if (fwin->core->height != height && fwin->resizebar)
1053 XMoveWindow(dpy, fwin->resizebar->window, 0,
1054 height - fwin->resizebar->height);
1055 */
1056 if (fwin->core->width != width) {
1057 fwin->flags.need_texture_remake = 1;
1058 resizedHorizontally = 1;
1059 }
1060
1061 fwin->core->width = width;
1062 fwin->core->height = height;
1063
1064 if (fwin->titlebar && resizedHorizontally) {
1065 /* Check if the titlebar is wide enough to hold the buttons.
1066 * Temporarily remove them if can't
1067 */
1068 if (fwin->left_button) {
1069 if (width < fwin->top_width * k && !fwin->flags.lbutton_dont_fit) {
1070
1071 if (!fwin->flags.hide_left_button) {
1072 XUnmapWindow(dpy, fwin->left_button->window);
1073 }
1074 fwin->flags.lbutton_dont_fit = 1;
1075 } else if (width >= fwin->top_width * k && fwin->flags.lbutton_dont_fit) {
1076
1077 if (!fwin->flags.hide_left_button) {
1078 XMapWindow(dpy, fwin->left_button->window);
1079 }
1080 fwin->flags.lbutton_dont_fit = 0;
1081 }
1082 }
1083 #ifdef XKB_BUTTON_HINT
1084 if (fwin->language_button) {
1085 if (width < fwin->top_width * k && !fwin->flags.languagebutton_dont_fit) {
1086
1087 if (!fwin->flags.hide_language_button) {
1088 XUnmapWindow(dpy, fwin->language_button->window);
1089 }
1090 fwin->flags.languagebutton_dont_fit = 1;
1091 } else if (width >= fwin->top_width * k && fwin->flags.languagebutton_dont_fit) {
1092
1093 if (!fwin->flags.hide_language_button) {
1094 XMapWindow(dpy, fwin->language_button->window);
1095 }
1096 fwin->flags.languagebutton_dont_fit = 0;
1097 }
1098 }
1099 #endif
1100
1101 if (fwin->right_button) {
1102 if (width < fwin->top_width * 2 && !fwin->flags.rbutton_dont_fit) {
1103
1104 if (!fwin->flags.hide_right_button) {
1105 XUnmapWindow(dpy, fwin->right_button->window);
1106 }
1107 fwin->flags.rbutton_dont_fit = 1;
1108 } else if (width >= fwin->top_width * 2 && fwin->flags.rbutton_dont_fit) {
1109
1110 if (!fwin->flags.hide_right_button) {
1111 XMapWindow(dpy, fwin->right_button->window);
1112 }
1113 fwin->flags.rbutton_dont_fit = 0;
1114 }
1115 }
1116
1117 if (wPreferences.new_style) {
1118 if (fwin->right_button)
1119 XMoveWindow(dpy, fwin->right_button->window,
1120 width - fwin->right_button->width + 1, 0);
1121 } else {
1122 if (fwin->right_button)
1123 XMoveWindow(dpy, fwin->right_button->window,
1124 width - fwin->right_button->width - 3,
1125 (fwin->titlebar->height - fwin->right_button->height) / 2);
1126 }
1127 updateTitlebar(fwin);
1128 checkTitleSize(fwin);
1129 }
1130
1131 if (fwin->resizebar) {
1132 wCoreConfigure(fwin->resizebar, 0,
1133 fwin->core->height - fwin->resizebar->height,
1134 fwin->core->width, fwin->resizebar->height);
1135
1136 fwin->resizebar_corner_width = RESIZEBAR_CORNER_WIDTH;
1137 if (fwin->core->width < RESIZEBAR_CORNER_WIDTH * 2 + RESIZEBAR_MIN_WIDTH) {
1138 fwin->resizebar_corner_width = fwin->core->width / 2;
1139 }
1140 }
1141 }
1142
1143 void wFrameWindowConfigure(WFrameWindow * fwin, int x, int y, int width, int height)
1144 {
1145 reconfigure(fwin, x, y, width, height, False);
1146 }
1147
1148 void wFrameWindowResize(WFrameWindow * fwin, int width, int height)
1149 {
1150 reconfigure(fwin, 0, 0, width, height, True);
1151 }
1152
1153 int wFrameWindowChangeTitle(WFrameWindow * fwin, char *new_title)
1154 {
1155 /* check if the title is the same as before */
1156 if (fwin->title) {
1157 if (new_title && (strcmp(fwin->title, new_title) == 0)) {
1158 return 0;
1159 }
1160 } else {
1161 if (!new_title)
1162 return 0;
1163 }
1164
1165 if (fwin->title)
1166 wfree(fwin->title);
1167
1168 fwin->title = wstrdup(new_title);
1169
1170 if (fwin->titlebar) {
1171 XClearWindow(dpy, fwin->titlebar->window);
1172
1173 wFrameWindowPaint(fwin);
1174 }
1175 checkTitleSize(fwin);
1176
1177 return 1;
1178 }
1179
1180 #ifdef XKB_BUTTON_HINT
1181 void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
1182 {
1183 paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
1184 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
1185 }
1186 #endif /* XKB_BUTTON_HINT */
1187
1188 /*********************************************************************/
1189
1190 static void handleExpose(WObjDescriptor * desc, XEvent * event)
1191 {
1192 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1193
1194 if (fwin->titlebar && fwin->titlebar->window == event->xexpose.window)
1195 fwin->flags.repaint_only_titlebar = 1;
1196 if (fwin->resizebar && fwin->resizebar->window == event->xexpose.window)
1197 fwin->flags.repaint_only_resizebar = 1;
1198 wFrameWindowPaint(fwin);
1199 fwin->flags.repaint_only_titlebar = 0;
1200 fwin->flags.repaint_only_resizebar = 0;
1201 }
1202
1203 static void checkTitleSize(WFrameWindow * fwin)
1204 {
1205 int width;
1206
1207 if (!fwin->title) {
1208 fwin->flags.incomplete_title = 0;
1209 return;
1210 }
1211
1212 if (!fwin->titlebar) {
1213 fwin->flags.incomplete_title = 1;
1214 return;
1215 } else {
1216 width = fwin->titlebar->width - 6 - 6;
1217 }
1218
1219 if (!wPreferences.new_style) {
1220 if (fwin->left_button && !fwin->flags.hide_left_button && !fwin->flags.lbutton_dont_fit)
1221 width -= fwin->left_button->width + 3;
1222
1223 #ifdef XKB_BUTTON_HINT
1224 if (fwin->language_button && !fwin->flags.hide_language_button
1225 && !fwin->flags.languagebutton_dont_fit)
1226 width -= fwin->language_button->width + 3;
1227 #endif
1228
1229 if (fwin->right_button && !fwin->flags.hide_right_button && !fwin->flags.rbutton_dont_fit)
1230 width -= fwin->right_button->width + 3;
1231 }
1232 if (WMWidthOfString(*fwin->font, fwin->title, strlen(fwin->title)) > width) {
1233 fwin->flags.incomplete_title = 1;
1234 } else {
1235 fwin->flags.incomplete_title = 0;
1236 }
1237 }
1238
1239 static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
1240 {
1241 WScreen *scr = button->screen_ptr;
1242 GC copy_gc = scr->copy_gc;
1243 int x = 0, y = 0, d = 0;
1244 int left = 0, width = 0;
1245
1246 /* setup stuff according to the state */
1247 if (pushed) {
1248 if (image) {
1249 if (image->width >= image->height * 2) {
1250 /* the image contains 2 pictures: the second is for the
1251 * pushed state */
1252 width = image->width / 2;
1253 left = image->width / 2;
1254 } else {
1255 width = image->width;
1256 }
1257 }
1258 XSetClipMask(dpy, copy_gc, None);
1259 XSetForeground(dpy, copy_gc, scr->white_pixel);
1260 d = 1;
1261 if (wPreferences.new_style) {
1262 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1263 XSetForeground(dpy, copy_gc, scr->black_pixel);
1264 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width - 1, button->height - 1);
1265 } else {
1266 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1267 XSetForeground(dpy, copy_gc, scr->black_pixel);
1268 XDrawRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1269 }
1270 } else {
1271 XClearWindow(dpy, button->window);
1272
1273 if (image) {
1274 if (image->width >= image->height * 2)
1275 width = image->width / 2;
1276 else
1277 width = image->width;
1278 }
1279 d = 0;
1280
1281 if (wPreferences.new_style) {
1282 if (texture->any.type == WTEX_SOLID || pushed) {
1283 wDrawBevel(button->window, button->width, button->height,
1284 (WTexSolid *) texture, WREL_RAISED);
1285 }
1286 } else {
1287 wDrawBevel(button->window, button->width, button->height,
1288 scr->widget_texture, WREL_RAISED);
1289 }
1290 }
1291
1292 if (image) {
1293 /* display image */
1294 XSetClipMask(dpy, copy_gc, image->mask);
1295 x = (button->width - width) / 2 + d;
1296 y = (button->height - image->height) / 2 + d;
1297 XSetClipOrigin(dpy, copy_gc, x - left, y);
1298 if (!wPreferences.new_style) {
1299 XSetForeground(dpy, copy_gc, scr->black_pixel);
1300 if (!pushed) {
1301 if (image->depth == 1)
1302 XCopyPlane(dpy, image->image, button->window, copy_gc,
1303 left, 0, width, image->height, x, y, 1);
1304 else
1305 XCopyArea(dpy, image->image, button->window, copy_gc,
1306 left, 0, width, image->height, x, y);
1307 } else {
1308 XSetForeground(dpy, copy_gc, scr->dark_pixel);
1309 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1310 }
1311 } else {
1312 if (pushed) {
1313 XSetForeground(dpy, copy_gc, scr->black_pixel);
1314 } else {
1315 XSetForeground(dpy, copy_gc, color);
1316 XSetBackground(dpy, copy_gc, texture->any.color.pixel);
1317 }
1318 XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
1319 }
1320 }
1321 }
1322
1323 static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
1324 {
1325 WFrameWindow *fwin = (WFrameWindow *) desc->parent;
1326 WCoreWindow *button = (WCoreWindow *) desc->self;
1327
1328 #ifdef XKB_BUTTON_HINT
1329 if (button == fwin->language_button) {
1330 if (wPreferences.modelock) {
1331 paintButton(button, fwin->title_texture[fwin->flags.state],
1332 WMColorPixel(fwin->title_color[fwin->flags.state]),
1333 fwin->languagebutton_image, False);
1334 }
1335 } else
1336 #endif
1337 if (button == fwin->left_button) {
1338 paintButton(button, fwin->title_texture[fwin->flags.state],
1339 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
1340 } else {
1341 paintButton(button, fwin->title_texture[fwin->flags.state],
1342 WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
1343 }
1344 }
1345
1346 static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
1347 {
1348 WFrameWindow *fwin = desc->parent;
1349 WCoreWindow *titlebar = desc->self;
1350
1351 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1352 if (fwin->on_dblclick_titlebar) {
1353 (*fwin->on_dblclick_titlebar) (titlebar, fwin->child, event);
1354 }
1355 } else {
1356 if (fwin->on_mousedown_titlebar) {
1357 (*fwin->on_mousedown_titlebar) (titlebar, fwin->child, event);
1358 }
1359 }
1360 }
1361
1362 static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event)
1363 {
1364 WFrameWindow *fwin = desc->parent;
1365 WCoreWindow *resizebar = desc->self;
1366
1367 if (fwin->on_mousedown_resizebar)
1368 (*fwin->on_mousedown_resizebar) (resizebar, fwin->child, event);
1369 }
1370
1371 static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
1372 {
1373 WFrameWindow *fwin = desc->parent;
1374 WCoreWindow *button = desc->self;
1375 WPixmap *image;
1376 XEvent ev;
1377 int done = 0, execute = 1;
1378 WTexture *texture;
1379 unsigned long pixel;
1380 int clickButton = event->xbutton.button;
1381
1382 if (IsDoubleClick(fwin->core->screen_ptr, event)) {
1383 if (button == fwin->right_button && fwin->on_dblclick_right) {
1384 (*fwin->on_dblclick_right) (button, fwin->child, event);
1385 }
1386 return;
1387 }
1388
1389 if (button == fwin->left_button) {
1390 image = fwin->lbutton_image;
1391 } else {
1392 image = fwin->rbutton_image;
1393 }
1394 #ifdef XKB_BUTTON_HINT
1395 if (button == fwin->language_button) {
1396 if (!wPreferences.modelock)
1397 return;
1398 image = fwin->languagebutton_image;
1399 }
1400 #endif
1401
1402 pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
1403 texture = fwin->title_texture[fwin->flags.state];
1404 paintButton(button, texture, pixel, image, True);
1405
1406 while (!done) {
1407 WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
1408 | ButtonPressMask | ExposureMask, &ev);
1409 switch (ev.type) {
1410 case LeaveNotify:
1411 execute = 0;
1412 paintButton(button, texture, pixel, image, False);
1413 break;
1414
1415 case EnterNotify:
1416 execute = 1;
1417 paintButton(button, texture, pixel, image, True);
1418 break;
1419
1420 case ButtonPress:
1421 break;
1422
1423 case ButtonRelease:
1424 if (ev.xbutton.button == clickButton)
1425 done = 1;
1426 break;
1427
1428 default:
1429 WMHandleEvent(&ev);
1430 }
1431 }
1432 paintButton(button, texture, pixel, image, False);
1433
1434 if (execute) {
1435 if (button == fwin->left_button) {
1436 if (fwin->on_click_left)
1437 (*fwin->on_click_left) (button, fwin->child, &ev);
1438 } else if (button == fwin->right_button) {
1439 if (fwin->on_click_right)
1440 (*fwin->on_click_right) (button, fwin->child, &ev);
1441 }
1442 #ifdef XKB_BUTTON_HINT
1443 else if (button == fwin->language_button) {
1444 if (fwin->on_click_language)
1445 (*fwin->on_click_language) (button, fwin->child, &ev);
1446 }
1447 #endif
1448
1449 }
1450 }