2 * Window Maker window manager
4 * Copyright (c) 1997, 1998 Alfredo K. Kojima
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 #include <X11/Xutil.h>
32 #include "WindowMaker.h"
41 #define DBLCLICK_TIME wPreferences.dblclick_time
43 extern WPreferences wPreferences
;
45 static void handleExpose(WObjDescriptor
*desc
, XEvent
*event
);
46 static void handleButtonExpose(WObjDescriptor
*desc
, XEvent
*event
);
48 static void buttonMouseDown(WObjDescriptor
*desc
, XEvent
*event
);
49 static void titlebarMouseDown(WObjDescriptor
*desc
, XEvent
*event
);
50 static void resizebarMouseDown(WObjDescriptor
*desc
, XEvent
*event
);
52 static void checkTitleSize(WFrameWindow
*fwin
);
55 static void paintButton(WCoreWindow
*button
, WTexture
*texture
,
56 unsigned long color
, WPixmap
*image
, int pushed
);
58 static void updateTitlebar(WFrameWindow
*fwin
);
62 wFrameWindowCreate(WScreen
*scr
, int wlevel
, int x
, int y
,
63 int width
, int height
, int flags
,
64 WTexture
**title_texture
, WTexture
**resize_texture
,
65 unsigned long *color
, GC
*gc
, WFont
**font
)
69 fwin
= wmalloc(sizeof(WFrameWindow
));
70 memset(fwin
, 0, sizeof(WFrameWindow
));
72 fwin
->screen_ptr
= scr
;
73 fwin
->window_level
= wlevel
;
75 fwin
->flags
.single_texture
= (flags
& WFF_SINGLE_STATE
) ? 1 : 0;
77 fwin
->title_texture
= title_texture
;
78 fwin
->resizebar_texture
= resize_texture
;
79 fwin
->title_pixel
= color
;
83 fwin
->core
= wCoreCreateTopLevel(scr
, x
, y
, width
, height
,
85 if (wPreferences
.use_saveunders
) {
87 XSetWindowAttributes attribs
;
90 attribs
.save_under
= True
;
91 XChangeWindowAttributes(dpy
, fwin
->core
->window
, vmask
, &attribs
);
94 /* setup stacking information */
95 fwin
->core
->stacking
= wmalloc(sizeof(WStacking
));
96 fwin
->core
->stacking
->above
= NULL
;
97 fwin
->core
->stacking
->under
= NULL
;
98 fwin
->core
->stacking
->child_of
= NULL
;
99 fwin
->core
->stacking
->window_level
= wlevel
;
101 AddToStackList(fwin
->core
);
103 wFrameWindowUpdateBorders(fwin
, flags
);
111 wFrameWindowUpdateBorders(WFrameWindow
*fwin
, int flags
)
117 WScreen
*scr
= fwin
->screen_ptr
;
119 width
= fwin
->core
->width
;
120 height
= fwin
->core
->height
- fwin
->top_width
- fwin
->bottom_width
;
122 if (flags
& WFF_TITLEBAR
)
123 theight
= (*fwin
->font
)->height
+ TITLEBAR_EXTRA_HEIGHT
;
127 if (wPreferences
.new_style
) {
133 if (fwin
->titlebar
) {
134 /* if we had a titlebar and is requesting for one,
135 * check if the size has changed and resize it */
136 if (flags
& WFF_TITLEBAR
) {
137 fwin
->top_width
= theight
;
139 fwin
->flags
.need_texture_remake
= 1;
141 if (wPreferences
.new_style
) {
142 if (fwin
->left_button
) {
143 wCoreConfigure(fwin
->left_button
, 0, 0, bsize
, bsize
);
146 if (fwin
->right_button
) {
147 wCoreConfigure(fwin
->right_button
, width
-bsize
+1,
150 } else { /* !new_style */
151 if (fwin
->left_button
) {
152 wCoreConfigure(fwin
->left_button
, 3, (theight
-bsize
)/2,
156 if (fwin
->right_button
) {
157 wCoreConfigure(fwin
->right_button
, width
-bsize
-3,
158 (theight
-bsize
)/2, bsize
, bsize
);
161 updateTitlebar(fwin
);
163 /* we had a titlebar, but now we don't need it anymore */
164 for (i
=0; i
< (fwin
->flags
.single_texture
? 1 : 3); i
++) {
165 FREE_PIXMAP(fwin
->title_back
[i
]);
166 if (wPreferences
.new_style
) {
167 FREE_PIXMAP(fwin
->lbutton_back
[i
]);
168 FREE_PIXMAP(fwin
->rbutton_back
[i
]);
171 if (fwin
->left_button
)
172 wCoreDestroy(fwin
->left_button
);
173 fwin
->left_button
= NULL
;
175 if (fwin
->right_button
)
176 wCoreDestroy(fwin
->right_button
);
177 fwin
->right_button
= NULL
;
179 wCoreDestroy(fwin
->titlebar
);
180 fwin
->titlebar
= NULL
;
185 /* if we didn't have a titlebar and are being requested for
187 if (flags
& WFF_TITLEBAR
) {
188 fwin
->top_width
= theight
;
190 fwin
->flags
.titlebar
= 1;
191 fwin
->titlebar
= wCoreCreate(fwin
->core
, 0, 0, width
+1, theight
);
193 if (flags
& WFF_LEFT_BUTTON
) {
194 fwin
->flags
.left_button
= 1;
195 if (wPreferences
.new_style
) {
196 fwin
->left_button
= wCoreCreate(fwin
->core
, 0, 0,
198 if (width
< theight
*4) {
199 fwin
->flags
.lbutton_dont_fit
= 1;
201 XMapRaised(dpy
, fwin
->left_button
->window
);
205 wCoreCreate(fwin
->titlebar
, 3, (theight
-bsize
)/2,
208 XSetWindowBackground(dpy
, fwin
->left_button
->window
,
209 scr
->widget_texture
->normal
.pixel
);
211 if (width
< theight
*3) {
212 fwin
->flags
.lbutton_dont_fit
= 1;
214 XMapRaised(dpy
, fwin
->left_button
->window
);
220 if (flags
& WFF_RIGHT_BUTTON
) {
221 fwin
->flags
.right_button
= 1;
222 if (wPreferences
.new_style
) {
224 wCoreCreate(fwin
->core
, width
-bsize
+1, 0,
228 wCoreCreate(fwin
->titlebar
, width
-bsize
-3,
229 (theight
-bsize
)/2, bsize
, bsize
);
230 XSetWindowBackground(dpy
, fwin
->right_button
->window
,
231 scr
->widget_texture
->normal
.pixel
);
234 if (width
< theight
*2) {
235 fwin
->flags
.rbutton_dont_fit
= 1;
237 XMapRaised(dpy
, fwin
->right_button
->window
);
241 if (wPreferences
.new_style
)
242 updateTitlebar(fwin
);
244 XMapRaised(dpy
, fwin
->titlebar
->window
);
246 fwin
->flags
.need_texture_remake
= 1;
249 checkTitleSize(fwin
);
251 if (flags
& WFF_RESIZEBAR
) {
252 fwin
->bottom_width
= RESIZEBAR_HEIGHT
;
254 fwin
->bottom_width
= 0;
257 if (flags
& WFF_RESIZEBAR
) {
258 if (!fwin
->resizebar
) {
259 fwin
->flags
.resizebar
= 1;
260 fwin
->resizebar
= wCoreCreate(fwin
->core
, 0,
261 height
+ fwin
->top_width
,
262 width
, RESIZEBAR_HEIGHT
);
263 fwin
->resizebar_corner_width
= RESIZEBAR_CORNER_WIDTH
;
264 if (width
< RESIZEBAR_CORNER_WIDTH
*2 + RESIZEBAR_MIN_WIDTH
) {
265 fwin
->resizebar_corner_width
= (width
- RESIZEBAR_MIN_WIDTH
)/2;
266 if (fwin
->resizebar_corner_width
< 0)
267 fwin
->resizebar_corner_width
= 0;
270 XMapWindow(dpy
, fwin
->resizebar
->window
);
271 XLowerWindow(dpy
, fwin
->resizebar
->window
);
273 fwin
->flags
.need_texture_remake
= 1;
275 if (height
+fwin
->top_width
+fwin
->bottom_width
!= fwin
->core
->height
) {
276 wCoreConfigure(fwin
->resizebar
, 0, height
+ fwin
->top_width
,
277 width
, RESIZEBAR_HEIGHT
);
281 if (fwin
->resizebar
) {
282 fwin
->bottom_width
= 0;
283 wCoreDestroy(fwin
->resizebar
);
284 fwin
->resizebar
= NULL
;
288 if (height
+ fwin
->top_width
+ fwin
->bottom_width
!= fwin
->core
->height
) {
289 wFrameWindowResize(fwin
, width
,
290 height
+ fwin
->top_width
+ fwin
->bottom_width
);
293 /* setup object descriptors */
295 if (fwin
->titlebar
) {
296 fwin
->titlebar
->descriptor
.handle_expose
= handleExpose
;
297 fwin
->titlebar
->descriptor
.parent
= fwin
;
298 fwin
->titlebar
->descriptor
.parent_type
= WCLASS_FRAME
;
299 fwin
->titlebar
->descriptor
.handle_mousedown
= titlebarMouseDown
;
302 if (fwin
->resizebar
) {
303 fwin
->resizebar
->descriptor
.handle_expose
= handleExpose
;
304 fwin
->resizebar
->descriptor
.parent
= fwin
;
305 fwin
->resizebar
->descriptor
.parent_type
= WCLASS_FRAME
;
306 fwin
->resizebar
->descriptor
.handle_mousedown
= resizebarMouseDown
;
309 if (fwin
->left_button
) {
310 fwin
->left_button
->descriptor
.handle_expose
= handleButtonExpose
;
311 fwin
->left_button
->descriptor
.parent
= fwin
;
312 fwin
->left_button
->descriptor
.parent_type
= WCLASS_FRAME
;
313 fwin
->left_button
->descriptor
.handle_mousedown
= buttonMouseDown
;
316 if (fwin
->right_button
) {
317 fwin
->right_button
->descriptor
.parent
= fwin
;
318 fwin
->right_button
->descriptor
.parent_type
= WCLASS_FRAME
;
319 fwin
->right_button
->descriptor
.handle_expose
= handleButtonExpose
;
320 fwin
->right_button
->descriptor
.handle_mousedown
= buttonMouseDown
;
323 checkTitleSize(fwin
);
329 wFrameWindowDestroy(WFrameWindow
*fwin
)
333 if (fwin
->left_button
)
334 wCoreDestroy(fwin
->left_button
);
336 if (fwin
->right_button
)
337 wCoreDestroy(fwin
->right_button
);
340 wCoreDestroy(fwin
->resizebar
);
343 wCoreDestroy(fwin
->titlebar
);
345 RemoveFromStackList(fwin
->core
);
347 wCoreDestroy(fwin
->core
);
352 for (i
=0; i
< (fwin
->flags
.single_texture
? 1 : 3); i
++) {
353 FREE_PIXMAP(fwin
->title_back
[i
]);
354 if (wPreferences
.new_style
) {
355 FREE_PIXMAP(fwin
->lbutton_back
[i
]);
356 FREE_PIXMAP(fwin
->rbutton_back
[i
]);
365 wFrameWindowChangeState(WFrameWindow
*fwin
, int state
)
367 if (fwin
->flags
.state
==state
)
370 fwin
->flags
.state
= state
;
371 fwin
->flags
.need_texture_change
= 1;
373 wFrameWindowPaint(fwin
);
378 updateTitlebar(WFrameWindow
*fwin
)
383 theight
= (*fwin
->font
)->height
+ TITLEBAR_EXTRA_HEIGHT
;
386 w
= fwin
->core
->width
+ 1;
388 if (wPreferences
.new_style
) {
389 if (fwin
->flags
.hide_left_button
|| !fwin
->left_button
390 || fwin
->flags
.lbutton_dont_fit
) {
393 x
= fwin
->left_button
->width
;
394 w
-= fwin
->left_button
->width
;
398 if (wPreferences
.new_style
) {
399 if (!fwin
->flags
.hide_right_button
&& fwin
->right_button
400 && !fwin
->flags
.rbutton_dont_fit
) {
401 w
-= fwin
->right_button
->width
;
405 if (wPreferences
.new_style
|| fwin
->titlebar
->width
!=w
)
406 fwin
->flags
.need_texture_remake
= 1;
408 wCoreConfigure(fwin
->titlebar
, x
, 0, w
, theight
);
413 wFrameWindowHideButton(WFrameWindow
*fwin
, int flags
)
415 if ((flags
& WFF_RIGHT_BUTTON
) && fwin
->right_button
) {
416 XUnmapWindow(dpy
, fwin
->right_button
->window
);
417 fwin
->flags
.hide_right_button
= 1;
420 if ((flags
& WFF_LEFT_BUTTON
) && fwin
->left_button
) {
421 XUnmapWindow(dpy
, fwin
->left_button
->window
);
422 fwin
->flags
.hide_left_button
= 1;
425 if (fwin
->titlebar
) {
426 if (wPreferences
.new_style
) {
427 updateTitlebar(fwin
);
429 XClearWindow(dpy
, fwin
->titlebar
->window
);
430 wFrameWindowPaint(fwin
);
432 checkTitleSize(fwin
);
438 wFrameWindowShowButton(WFrameWindow
*fwin
, int flags
)
440 if ((flags
& WFF_RIGHT_BUTTON
) && fwin
->right_button
441 && fwin
->flags
.hide_right_button
) {
443 if (!fwin
->flags
.rbutton_dont_fit
)
444 XMapWindow(dpy
, fwin
->right_button
->window
);
446 fwin
->flags
.hide_right_button
= 0;
449 if ((flags
& WFF_LEFT_BUTTON
) && fwin
->left_button
450 && fwin
->flags
.hide_left_button
) {
452 if (!fwin
->flags
.lbutton_dont_fit
)
453 XMapWindow(dpy
, fwin
->left_button
->window
);
455 fwin
->flags
.hide_left_button
= 0;
459 if (fwin
->titlebar
) {
460 if (wPreferences
.new_style
) {
461 updateTitlebar(fwin
);
463 XClearWindow(dpy
, fwin
->titlebar
->window
);
464 wFrameWindowPaint(fwin
);
466 checkTitleSize(fwin
);
472 renderTexture(WScreen
*scr
, WTexture
*texture
, int width
, int height
,
473 int bwidth
, int bheight
, int left
, int right
,
474 Pixmap
*title
, Pixmap
*lbutton
, Pixmap
*rbutton
)
477 RImage
*limg
, *rimg
, *mimg
;
478 RColor color1
, color2
;
485 switch (texture
->any
.type
) {
489 case WTEX_MHGRADIENT
:
490 case WTEX_MVGRADIENT
:
491 case WTEX_MDGRADIENT
:
492 if (texture
->any
.type
==WTEX_DGRADIENT
493 || texture
->any
.type
==WTEX_MDGRADIENT
)
495 else if (texture
->any
.type
==WTEX_HGRADIENT
496 || texture
->any
.type
==WTEX_MHGRADIENT
)
501 if (texture
->any
.type
==WTEX_MHGRADIENT
502 || texture
->any
.type
==WTEX_MDGRADIENT
503 || texture
->any
.type
==WTEX_MVGRADIENT
)
504 img
= RRenderMultiGradient(width
, height
,
505 &(texture
->mgradient
.colors
[1]), i
);
507 color1
.red
= texture
->gradient
.color1
.red
>> 8;
508 color1
.green
= texture
->gradient
.color1
.green
>> 8;
509 color1
.blue
= texture
->gradient
.color1
.blue
>> 8;
510 color2
.red
= texture
->gradient
.color2
.red
>> 8;
511 color2
.green
= texture
->gradient
.color2
.green
>> 8;
512 color2
.blue
= texture
->gradient
.color2
.blue
>> 8;
513 img
= RRenderGradient(width
, height
, &color1
, &color2
, i
);
518 img
= wTextureRenderImage(texture
, width
, height
, WREL_FLAT
);
526 wwarning(_("could not render gradient: %s"), RMessageForError(RErrorCode
));
530 if (wPreferences
.new_style
) {
532 limg
= RGetSubImage(img
, 0, 0, bwidth
, bheight
);
540 RBevelImage(limg
, RBEV_RAISED2
);
541 if (!RConvertImage(scr
->rcontext
, limg
, lbutton
)) {
542 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
550 rimg
= RGetSubImage(img
, width
- bwidth
, 0, bwidth
, bheight
);
555 RBevelImage(rimg
, RBEV_RAISED2
);
556 if (!RConvertImage(scr
->rcontext
, rimg
, rbutton
)) {
557 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
564 mimg
= RGetSubImage(img
, x
, 0, w
, img
->height
);
565 RBevelImage(mimg
, RBEV_RAISED2
);
567 if (!RConvertImage(scr
->rcontext
, mimg
, title
)) {
568 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
572 RBevelImage(img
, RBEV_RAISED2
);
574 if (!RConvertImage(scr
->rcontext
, img
, title
)) {
575 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
579 RBevelImage(img
, RBEV_RAISED2
);
581 if (!RConvertImage(scr
->rcontext
, img
, title
)) {
582 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
591 updateTexture(WFrameWindow
*fwin
)
596 i
= fwin
->flags
.state
;
597 if (fwin
->titlebar
) {
598 if (fwin
->title_texture
[i
]->any
.type
!=WTEX_SOLID
) {
599 XSetWindowBackgroundPixmap(dpy
, fwin
->titlebar
->window
,
600 fwin
->title_back
[i
]);
601 if (wPreferences
.new_style
) {
602 if (fwin
->left_button
&& fwin
->lbutton_back
[i
])
603 XSetWindowBackgroundPixmap(dpy
, fwin
->left_button
->window
,
604 fwin
->lbutton_back
[i
]);
606 if (fwin
->right_button
&& fwin
->rbutton_back
[i
])
607 XSetWindowBackgroundPixmap(dpy
, fwin
->right_button
->window
,
608 fwin
->rbutton_back
[i
]);
611 pixel
= fwin
->title_texture
[i
]->solid
.normal
.pixel
;
612 XSetWindowBackground(dpy
, fwin
->titlebar
->window
, pixel
);
613 if (wPreferences
.new_style
) {
614 if (fwin
->left_button
)
615 XSetWindowBackground(dpy
, fwin
->left_button
->window
,
617 if (fwin
->right_button
)
618 XSetWindowBackground(dpy
, fwin
->right_button
->window
,
622 XClearWindow(dpy
, fwin
->titlebar
->window
);
624 if (fwin
->left_button
) {
625 XClearWindow(dpy
, fwin
->left_button
->window
);
626 handleButtonExpose(&fwin
->left_button
->descriptor
, NULL
);
628 if (fwin
->right_button
) {
629 XClearWindow(dpy
, fwin
->right_button
->window
);
630 handleButtonExpose(&fwin
->right_button
->descriptor
, NULL
);
634 if (fwin
->resizebar
) {
635 XSetWindowBackground(dpy
, fwin
->resizebar
->window
,
636 fwin
->resizebar_texture
[0]->solid
.normal
.pixel
);
637 XClearWindow(dpy
, fwin
->resizebar
->window
);
644 remakeTexture(WFrameWindow
*fwin
, int state
)
646 Pixmap pmap
, lpmap
, rpmap
;
648 if (fwin
->title_texture
[state
] && fwin
->titlebar
) {
649 FREE_PIXMAP(fwin
->title_back
[state
]);
650 if (wPreferences
.new_style
) {
651 FREE_PIXMAP(fwin
->lbutton_back
[state
]);
652 FREE_PIXMAP(fwin
->rbutton_back
[state
]);
655 if (fwin
->title_texture
[state
]->any
.type
!=WTEX_SOLID
) {
659 /* eventually surrounded by if new_style */
660 left
= fwin
->left_button
&& !fwin
->flags
.hide_left_button
661 && !fwin
->flags
.lbutton_dont_fit
;
662 right
= fwin
->right_button
&& !fwin
->flags
.hide_right_button
663 && !fwin
->flags
.rbutton_dont_fit
;
665 width
= fwin
->core
->width
+1;
667 renderTexture(fwin
->screen_ptr
, fwin
->title_texture
[state
],
668 width
, fwin
->titlebar
->height
,
669 fwin
->titlebar
->height
, fwin
->titlebar
->height
,
670 left
, right
, &pmap
, &lpmap
, &rpmap
);
672 fwin
->title_back
[state
] = pmap
;
673 if (wPreferences
.new_style
) {
674 fwin
->lbutton_back
[state
] = lpmap
;
675 fwin
->rbutton_back
[state
] = rpmap
;
683 wFrameWindowPaint(WFrameWindow
*fwin
)
686 if (fwin
->flags
.is_client_window_frame
)
687 fwin
->flags
.justification
= wPreferences
.title_justification
;
689 if (fwin
->flags
.need_texture_remake
) {
692 fwin
->flags
.need_texture_remake
= 0;
693 fwin
->flags
.need_texture_change
= 0;
695 if (fwin
->flags
.single_texture
) {
696 remakeTexture(fwin
, 0);
699 /* first render the texture for the current state... */
700 remakeTexture(fwin
, fwin
->flags
.state
);
701 /* ... and paint it */
704 for (i
=0; i
< 3; i
++) {
705 if (i
!=fwin
->flags
.state
)
706 remakeTexture(fwin
, i
);
711 if (fwin
->flags
.need_texture_change
) {
712 fwin
->flags
.need_texture_change
= 0;
717 if (fwin
->titlebar
&& !fwin
->flags
.repaint_only_resizebar
718 && fwin
->title_texture
[fwin
->flags
.state
]->any
.type
==WTEX_SOLID
) {
719 wDrawBevel(fwin
->titlebar
->window
, fwin
->titlebar
->width
,
720 fwin
->titlebar
->height
,
721 (WTexSolid
*)fwin
->title_texture
[fwin
->flags
.state
],
726 && !fwin
->flags
.repaint_only_titlebar
) {
731 WTexSolid
*texture
= (WTexSolid
*)fwin
->resizebar_texture
[0];
733 w
= fwin
->resizebar
->width
;
734 h
= fwin
->resizebar
->height
;
735 cw
= fwin
->resizebar_corner_width
;
736 light_gc
= texture
->light_gc
;
737 dim_gc
= texture
->dim_gc
;
738 win
= fwin
->resizebar
->window
;
740 XDrawLine(dpy
, win
, dim_gc
, 0, 0, w
, 0);
741 XDrawLine(dpy
, win
, light_gc
, 0, 1, w
, 1);
743 XDrawLine(dpy
, win
, dim_gc
, cw
, 2, cw
, h
);
744 XDrawLine(dpy
, win
, light_gc
, cw
+1, 2, cw
+1, h
);
746 XDrawLine(dpy
, win
, dim_gc
, w
-cw
-2, 2, w
-cw
-2, h
);
747 XDrawLine(dpy
, win
, light_gc
, w
-cw
-1, 2, w
-cw
-1, h
);
749 #ifdef SHADOW_RESIZEBAR
750 XDrawLine(dpy
, win
, light_gc
, 0, 1, 0, h
-1);
751 XDrawLine(dpy
, win
, dim_gc
, w
-1, 2, w
-1, h
-1);
752 XDrawLine(dpy
, win
, dim_gc
, 1, h
-1, cw
, h
-1);
753 XDrawLine(dpy
, win
, dim_gc
, cw
+2, h
-1, w
-cw
-2, h
-1);
754 XDrawLine(dpy
, win
, dim_gc
, w
-cw
, h
-1, w
-1, h
-1);
755 #endif /* SHADOW_RESIZEBAR */
759 if (fwin
->title
&& fwin
->titlebar
760 && !fwin
->flags
.repaint_only_resizebar
) {
762 int lofs
= 6, rofs
= 6;
768 if (!wPreferences
.new_style
) {
769 if (fwin
->left_button
&& !fwin
->flags
.hide_left_button
770 && !fwin
->flags
.lbutton_dont_fit
)
771 lofs
+= fwin
->left_button
->width
+ 3;
775 if (fwin
->right_button
&& !fwin
->flags
.hide_right_button
776 && !fwin
->flags
.rbutton_dont_fit
)
777 rofs
+= fwin
->right_button
->width
+ 3;
781 title
= ShrinkString(*fwin
->font
, fwin
->title
,
782 fwin
->titlebar
->width
- lofs
- rofs
);
783 titlelen
= strlen(title
);
784 w
= wTextWidth((*fwin
->font
)->font
, title
, titlelen
);
786 switch (fwin
->flags
.justification
) {
792 x
= fwin
->titlebar
->width
- w
- rofs
;
797 x
= lofs
+ (fwin
->titlebar
->width
- w
- lofs
- rofs
) / 2;
799 x
= (fwin
->titlebar
->width
- w
) / 2;
803 XSetForeground(dpy
, *fwin
->title_gc
,
804 fwin
->title_pixel
[fwin
->flags
.state
]);
806 wDrawString(fwin
->titlebar
->window
, *fwin
->font
,
808 (*fwin
->font
)->y
+ TITLEBAR_EXTRA_HEIGHT
/2, title
,
817 wFrameWindowResize(WFrameWindow
*fwin
, int width
, int height
)
819 int k
= (wPreferences
.new_style
? 4 : 3);
820 int resizedHorizontally
= 0;
822 XResizeWindow(dpy
, fwin
->core
->window
, width
, height
);
824 if (fwin->core->height != height && fwin->resizebar)
825 XMoveWindow(dpy, fwin->resizebar->window, 0,
826 height - fwin->resizebar->height);
828 if (fwin
->core
->width
!= width
) {
829 fwin
->flags
.need_texture_remake
= 1;
830 resizedHorizontally
= 1;
833 fwin
->core
->width
= width
;
834 fwin
->core
->height
= height
;
836 if (fwin
->titlebar
&& resizedHorizontally
) {
837 /* Check if the titlebar is wide enough to hold the buttons.
838 * Temporarily remove them if can't
840 if (fwin
->left_button
) {
841 if (width
< fwin
->top_width
*k
&& !fwin
->flags
.lbutton_dont_fit
) {
843 if (!fwin
->flags
.hide_left_button
) {
844 XUnmapWindow(dpy
, fwin
->left_button
->window
);
846 fwin
->flags
.lbutton_dont_fit
= 1;
847 } else if (width
>= fwin
->top_width
*k
&& fwin
->flags
.lbutton_dont_fit
) {
849 if (!fwin
->flags
.hide_left_button
) {
850 XMapWindow(dpy
, fwin
->left_button
->window
);
852 fwin
->flags
.lbutton_dont_fit
= 0;
856 if (fwin
->right_button
) {
857 if (width
< fwin
->top_width
*2 && !fwin
->flags
.rbutton_dont_fit
) {
859 if (!fwin
->flags
.hide_right_button
) {
860 XUnmapWindow(dpy
, fwin
->right_button
->window
);
862 fwin
->flags
.rbutton_dont_fit
= 1;
863 } else if (width
>= fwin
->top_width
*2 && fwin
->flags
.rbutton_dont_fit
) {
865 if (!fwin
->flags
.hide_right_button
) {
866 XMapWindow(dpy
, fwin
->right_button
->window
);
868 fwin
->flags
.rbutton_dont_fit
= 0;
872 if (wPreferences
.new_style
) {
873 if (fwin
->right_button
)
874 XMoveWindow(dpy
, fwin
->right_button
->window
,
875 width
- fwin
->right_button
->width
+ 1, 0);
877 if (fwin
->right_button
)
878 XMoveWindow(dpy
, fwin
->right_button
->window
,
879 width
- fwin
->right_button
->width
- 3,
880 (fwin
->titlebar
->height
- fwin
->right_button
->height
)/2);
882 updateTitlebar(fwin
);
883 checkTitleSize(fwin
);
886 if (fwin
->resizebar
) {
887 wCoreConfigure(fwin
->resizebar
, 0,
888 fwin
->core
->height
- fwin
->resizebar
->height
,
889 fwin
->core
->width
, fwin
->resizebar
->height
);
891 fwin
->resizebar_corner_width
= RESIZEBAR_CORNER_WIDTH
;
892 if (fwin
->core
->width
< RESIZEBAR_CORNER_WIDTH
*2 + RESIZEBAR_MIN_WIDTH
) {
893 fwin
->resizebar_corner_width
= fwin
->core
->width
/2;
900 wFrameWindowResizeInternal(WFrameWindow
*fwin
, int iwidth
, int iheight
)
902 wFrameWindowResize(fwin
, iwidth
,
903 iheight
+ fwin
->top_width
+ fwin
->bottom_width
);
909 wFrameWindowChangeTitle(WFrameWindow
*fwin
, char *new_title
)
911 /* check if the title is the same as before */
913 if (new_title
&& (strcmp(fwin
->title
, new_title
) == 0)) {
924 fwin
->title
= wstrdup(new_title
);
926 if (fwin
->titlebar
) {
927 XClearWindow(dpy
, fwin
->titlebar
->window
);
929 wFrameWindowPaint(fwin
);
931 checkTitleSize(fwin
);
937 /*********************************************************************/
940 handleExpose(WObjDescriptor
*desc
, XEvent
*event
)
942 WFrameWindow
*fwin
= (WFrameWindow
*)desc
->parent
;
945 if (fwin
->titlebar
&& fwin
->titlebar
->window
== event
->xexpose
.window
)
946 fwin
->flags
.repaint_only_titlebar
= 1;
947 if (fwin
->resizebar
&& fwin
->resizebar
->window
== event
->xexpose
.window
)
948 fwin
->flags
.repaint_only_resizebar
= 1;
949 wFrameWindowPaint(fwin
);
950 fwin
->flags
.repaint_only_titlebar
= 0;
951 fwin
->flags
.repaint_only_resizebar
= 0;
956 checkTitleSize(WFrameWindow
*fwin
)
961 fwin
->flags
.incomplete_title
= 0;
965 if (!fwin
->titlebar
) {
966 fwin
->flags
.incomplete_title
= 1;
969 width
= fwin
->titlebar
->width
- 6 - 6;
972 if (!wPreferences
.new_style
) {
973 if (fwin
->left_button
&& !fwin
->flags
.hide_left_button
974 && !fwin
->flags
.lbutton_dont_fit
)
975 width
-= fwin
->left_button
->width
+ 3;
977 if (fwin
->right_button
&& !fwin
->flags
.hide_right_button
978 && !fwin
->flags
.rbutton_dont_fit
)
979 width
-= fwin
->right_button
->width
+ 3;
981 if (wTextWidth((*fwin
->font
)->font
, fwin
->title
,
982 strlen(fwin
->title
)) > width
) {
983 fwin
->flags
.incomplete_title
= 1;
985 fwin
->flags
.incomplete_title
= 0;
990 paintButton(WCoreWindow
*button
, WTexture
*texture
, unsigned long color
,
991 WPixmap
*image
, int pushed
)
993 WScreen
*scr
= button
->screen_ptr
;
994 GC copy_gc
= scr
->copy_gc
;
998 /* setup stuff according to the state */
1001 if (image
->width
>=image
->height
*2) {
1002 /* the image contains 2 pictures: the second is for the
1004 width
= image
->width
/2;
1005 left
= image
->width
/2;
1007 width
= image
->width
;
1010 XSetClipMask(dpy
, copy_gc
, None
);
1011 XSetForeground(dpy
, copy_gc
, scr
->white_pixel
);
1013 if (wPreferences
.new_style
) {
1014 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1015 button
->width
-1, button
->height
-1);
1016 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1017 XDrawRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1018 button
->width
-1, button
->height
-1);
1020 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1021 button
->width
, button
->height
);
1022 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1023 XDrawRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1024 button
->width
, button
->height
);
1027 XClearWindow(dpy
, button
->window
);
1030 if (image
->width
>=image
->height
*2)
1031 width
= image
->width
/2;
1033 width
= image
->width
;
1037 if (wPreferences
.new_style
) {
1038 if (texture
->any
.type
==WTEX_SOLID
|| pushed
) {
1039 wDrawBevel(button
->window
, button
->width
, button
->height
,
1040 (WTexSolid
*)texture
, WREL_RAISED
);
1043 wDrawBevel(button
->window
, button
->width
, button
->height
,
1044 scr
->widget_texture
, WREL_RAISED
);
1050 XSetClipMask(dpy
, copy_gc
, image
->mask
);
1051 x
= (button
->width
- width
)/2 + d
;
1052 y
= (button
->height
- image
->height
)/2 + d
;
1053 XSetClipOrigin(dpy
, copy_gc
, x
-left
, y
);
1054 if (!wPreferences
.new_style
) {
1055 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1057 if (image
->depth
==1)
1058 XCopyPlane(dpy
, image
->image
, button
->window
, copy_gc
,
1059 left
, 0, width
, image
->height
, x
, y
, 1);
1061 XCopyArea(dpy
, image
->image
, button
->window
, copy_gc
,
1062 left
, 0, width
, image
->height
, x
, y
);
1064 XSetForeground(dpy
, copy_gc
, scr
->dark_pixel
);
1065 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1066 button
->width
, button
->height
);
1070 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1072 XSetForeground(dpy
, copy_gc
, color
);
1073 XSetBackground(dpy
, copy_gc
, texture
->any
.color
.pixel
);
1075 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1076 button
->width
, button
->height
);
1083 handleButtonExpose(WObjDescriptor
*desc
, XEvent
*event
)
1085 WFrameWindow
*fwin
= (WFrameWindow
*)desc
->parent
;
1086 WCoreWindow
*button
= (WCoreWindow
*)desc
->self
;
1088 if (button
== fwin
->left_button
) {
1089 paintButton(button
, fwin
->title_texture
[fwin
->flags
.state
],
1090 fwin
->title_pixel
[fwin
->flags
.state
],
1091 fwin
->lbutton_image
, False
);
1093 paintButton(button
, fwin
->title_texture
[fwin
->flags
.state
],
1094 fwin
->title_pixel
[fwin
->flags
.state
],
1095 fwin
->rbutton_image
, False
);
1101 titlebarMouseDown(WObjDescriptor
*desc
, XEvent
*event
)
1103 WFrameWindow
*fwin
= desc
->parent
;
1104 WCoreWindow
*titlebar
= desc
->self
;
1106 if (IsDoubleClick(fwin
->core
->screen_ptr
, event
)) {
1107 if (fwin
->on_dblclick_titlebar
)
1108 (*fwin
->on_dblclick_titlebar
)(titlebar
, fwin
->child
, event
);
1110 if (fwin
->on_mousedown_titlebar
)
1111 (*fwin
->on_mousedown_titlebar
)(titlebar
, fwin
->child
, event
);
1117 resizebarMouseDown(WObjDescriptor
*desc
, XEvent
*event
)
1119 WFrameWindow
*fwin
= desc
->parent
;
1120 WCoreWindow
*resizebar
= desc
->self
;
1122 if (fwin
->on_mousedown_resizebar
)
1123 (*fwin
->on_mousedown_resizebar
)(resizebar
, fwin
->child
, event
);
1128 buttonMouseDown(WObjDescriptor
*desc
, XEvent
*event
)
1130 WFrameWindow
*fwin
= desc
->parent
;
1131 WCoreWindow
*button
= desc
->self
;
1134 int done
=0, execute
=1;
1136 unsigned long pixel
;
1137 int clickButton
= event
->xbutton
.button
;
1139 if (IsDoubleClick(fwin
->core
->screen_ptr
, event
)) {
1140 if (button
== fwin
->right_button
&& fwin
->on_dblclick_right
) {
1141 (*fwin
->on_dblclick_right
)(button
, fwin
->child
, event
);
1146 if (button
== fwin
->left_button
) {
1147 image
= fwin
->lbutton_image
;
1149 image
= fwin
->rbutton_image
;
1152 pixel
= fwin
->title_pixel
[fwin
->flags
.state
];
1153 texture
= fwin
->title_texture
[fwin
->flags
.state
];
1154 paintButton(button
, texture
, pixel
, image
, True
);
1157 WMMaskEvent(dpy
, LeaveWindowMask
|EnterWindowMask
|ButtonReleaseMask
1158 |ButtonPressMask
|ExposureMask
, &ev
);
1162 paintButton(button
, texture
, pixel
, image
, False
);
1167 paintButton(button
, texture
, pixel
, image
, True
);
1174 if (ev
.xbutton
.button
== clickButton
)
1182 paintButton(button
, texture
, pixel
, image
, False
);
1185 if (button
== fwin
->left_button
) {
1186 if (fwin
->on_click_left
)
1187 (*fwin
->on_click_left
)(button
, fwin
->child
, &ev
);
1188 } else if (button
== fwin
->right_button
) {
1189 if (fwin
->on_click_right
)
1190 (*fwin
->on_click_right
)(button
, fwin
->child
, &ev
);