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