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
);
60 static void remakeTexture(WFrameWindow
*fwin
, int state
, int newWidth
);
62 static void updateTexture(WFrameWindow
*fwin
);
66 wFrameWindowCreate(WScreen
*scr
, int wlevel
, int x
, int y
,
67 int width
, int height
, int flags
,
68 WTexture
**title_texture
, WTexture
**resize_texture
,
69 unsigned long *color
, GC
*gc
, WFont
**font
)
73 fwin
= wmalloc(sizeof(WFrameWindow
));
74 memset(fwin
, 0, sizeof(WFrameWindow
));
76 fwin
->screen_ptr
= scr
;
78 fwin
->flags
.single_texture
= (flags
& WFF_SINGLE_STATE
) ? 1 : 0;
80 fwin
->title_texture
= title_texture
;
81 fwin
->resizebar_texture
= resize_texture
;
82 fwin
->title_pixel
= color
;
86 fwin
->core
= wCoreCreateTopLevel(scr
, x
, y
, width
, height
,
88 if (wPreferences
.use_saveunders
) {
90 XSetWindowAttributes attribs
;
93 attribs
.save_under
= True
;
94 XChangeWindowAttributes(dpy
, fwin
->core
->window
, vmask
, &attribs
);
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
;
104 AddToStackList(fwin
->core
);
106 wFrameWindowUpdateBorders(fwin
, flags
);
114 wFrameWindowUpdateBorders(WFrameWindow
*fwin
, int flags
)
120 WScreen
*scr
= fwin
->screen_ptr
;
122 width
= fwin
->core
->width
;
123 if (flags
& WFF_IS_SHADED
)
126 height
= fwin
->core
->height
- fwin
->top_width
- fwin
->bottom_width
;
128 if (flags
& WFF_TITLEBAR
)
129 theight
= (*fwin
->font
)->height
+ TITLEBAR_EXTRA_HEIGHT
;
133 if (wPreferences
.new_style
) {
139 if (fwin
->titlebar
) {
140 /* if we had a titlebar and is requesting for one,
141 * check if the size has changed and resize it */
142 if (flags
& WFF_TITLEBAR
) {
143 fwin
->top_width
= theight
;
145 fwin
->flags
.need_texture1_remake
= 1;
146 fwin
->flags
.need_texture2_remake
= 1;
147 fwin
->flags
.need_texture3_remake
= 1;
149 if (wPreferences
.new_style
) {
150 if (fwin
->left_button
) {
151 wCoreConfigure(fwin
->left_button
, 0, 0, bsize
, bsize
);
154 if (fwin
->right_button
) {
155 wCoreConfigure(fwin
->right_button
, width
-bsize
+1,
158 } else { /* !new_style */
159 if (fwin
->left_button
) {
160 wCoreConfigure(fwin
->left_button
, 3, (theight
-bsize
)/2,
164 if (fwin
->right_button
) {
165 wCoreConfigure(fwin
->right_button
, width
-bsize
-3,
166 (theight
-bsize
)/2, bsize
, bsize
);
169 updateTitlebar(fwin
);
171 /* we had a titlebar, but now we don't need it anymore */
172 for (i
=0; i
< (fwin
->flags
.single_texture
? 1 : 3); i
++) {
173 FREE_PIXMAP(fwin
->title_back
[i
]);
174 if (wPreferences
.new_style
) {
175 FREE_PIXMAP(fwin
->lbutton_back
[i
]);
176 FREE_PIXMAP(fwin
->rbutton_back
[i
]);
179 if (fwin
->left_button
)
180 wCoreDestroy(fwin
->left_button
);
181 fwin
->left_button
= NULL
;
183 if (fwin
->right_button
)
184 wCoreDestroy(fwin
->right_button
);
185 fwin
->right_button
= NULL
;
187 wCoreDestroy(fwin
->titlebar
);
188 fwin
->titlebar
= NULL
;
193 /* if we didn't have a titlebar and are being requested for
195 if (flags
& WFF_TITLEBAR
) {
196 fwin
->top_width
= theight
;
198 fwin
->flags
.titlebar
= 1;
199 fwin
->titlebar
= wCoreCreate(fwin
->core
, 0, 0, width
+1, theight
);
201 if (flags
& WFF_LEFT_BUTTON
) {
202 fwin
->flags
.left_button
= 1;
203 if (wPreferences
.new_style
) {
204 fwin
->left_button
= wCoreCreate(fwin
->core
, 0, 0,
206 if (width
< theight
*4) {
207 fwin
->flags
.lbutton_dont_fit
= 1;
209 XMapRaised(dpy
, fwin
->left_button
->window
);
213 wCoreCreate(fwin
->titlebar
, 3, (theight
-bsize
)/2,
216 XSetWindowBackground(dpy
, fwin
->left_button
->window
,
217 scr
->widget_texture
->normal
.pixel
);
219 if (width
< theight
*3) {
220 fwin
->flags
.lbutton_dont_fit
= 1;
222 XMapRaised(dpy
, fwin
->left_button
->window
);
228 if (flags
& WFF_RIGHT_BUTTON
) {
229 fwin
->flags
.right_button
= 1;
230 if (wPreferences
.new_style
) {
232 wCoreCreate(fwin
->core
, width
-bsize
+1, 0,
236 wCoreCreate(fwin
->titlebar
, width
-bsize
-3,
237 (theight
-bsize
)/2, bsize
, bsize
);
238 XSetWindowBackground(dpy
, fwin
->right_button
->window
,
239 scr
->widget_texture
->normal
.pixel
);
242 if (width
< theight
*2) {
243 fwin
->flags
.rbutton_dont_fit
= 1;
245 XMapRaised(dpy
, fwin
->right_button
->window
);
249 if (wPreferences
.new_style
)
250 updateTitlebar(fwin
);
252 XMapRaised(dpy
, fwin
->titlebar
->window
);
254 fwin
->flags
.need_texture1_remake
= 1;
255 fwin
->flags
.need_texture2_remake
= 1;
256 fwin
->flags
.need_texture3_remake
= 1;
259 checkTitleSize(fwin
);
261 if (flags
& WFF_RESIZEBAR
) {
262 fwin
->bottom_width
= RESIZEBAR_HEIGHT
;
264 fwin
->bottom_width
= 0;
267 if (flags
& WFF_RESIZEBAR
) {
268 if (!fwin
->resizebar
) {
269 fwin
->flags
.resizebar
= 1;
270 fwin
->resizebar
= wCoreCreate(fwin
->core
, 0,
271 height
+ fwin
->top_width
,
272 width
, RESIZEBAR_HEIGHT
);
273 fwin
->resizebar_corner_width
= RESIZEBAR_CORNER_WIDTH
;
274 if (width
< RESIZEBAR_CORNER_WIDTH
*2 + RESIZEBAR_MIN_WIDTH
) {
275 fwin
->resizebar_corner_width
= (width
- RESIZEBAR_MIN_WIDTH
)/2;
276 if (fwin
->resizebar_corner_width
< 0)
277 fwin
->resizebar_corner_width
= 0;
280 XMapWindow(dpy
, fwin
->resizebar
->window
);
281 XLowerWindow(dpy
, fwin
->resizebar
->window
);
283 fwin
->flags
.need_texture1_remake
= 1;
284 fwin
->flags
.need_texture2_remake
= 1;
285 fwin
->flags
.need_texture3_remake
= 1;
287 if (height
+fwin
->top_width
+fwin
->bottom_width
!= fwin
->core
->height
) {
288 wCoreConfigure(fwin
->resizebar
, 0, height
+ fwin
->top_width
,
289 width
, RESIZEBAR_HEIGHT
);
293 if (fwin
->resizebar
) {
294 fwin
->bottom_width
= 0;
295 wCoreDestroy(fwin
->resizebar
);
296 fwin
->resizebar
= NULL
;
300 if (height
+ fwin
->top_width
+ fwin
->bottom_width
!= fwin
->core
->height
301 && !(flags
& WFF_IS_SHADED
)) {
302 wFrameWindowResize(fwin
, width
,
303 height
+ fwin
->top_width
+ fwin
->bottom_width
);
306 /* setup object descriptors */
308 if (fwin
->titlebar
) {
309 fwin
->titlebar
->descriptor
.handle_expose
= handleExpose
;
310 fwin
->titlebar
->descriptor
.parent
= fwin
;
311 fwin
->titlebar
->descriptor
.parent_type
= WCLASS_FRAME
;
312 fwin
->titlebar
->descriptor
.handle_mousedown
= titlebarMouseDown
;
315 if (fwin
->resizebar
) {
316 fwin
->resizebar
->descriptor
.handle_expose
= handleExpose
;
317 fwin
->resizebar
->descriptor
.parent
= fwin
;
318 fwin
->resizebar
->descriptor
.parent_type
= WCLASS_FRAME
;
319 fwin
->resizebar
->descriptor
.handle_mousedown
= resizebarMouseDown
;
322 if (fwin
->left_button
) {
323 fwin
->left_button
->descriptor
.handle_expose
= handleButtonExpose
;
324 fwin
->left_button
->descriptor
.parent
= fwin
;
325 fwin
->left_button
->descriptor
.parent_type
= WCLASS_FRAME
;
326 fwin
->left_button
->descriptor
.handle_mousedown
= buttonMouseDown
;
329 if (fwin
->right_button
) {
330 fwin
->right_button
->descriptor
.parent
= fwin
;
331 fwin
->right_button
->descriptor
.parent_type
= WCLASS_FRAME
;
332 fwin
->right_button
->descriptor
.handle_expose
= handleButtonExpose
;
333 fwin
->right_button
->descriptor
.handle_mousedown
= buttonMouseDown
;
336 checkTitleSize(fwin
);
342 wFrameWindowDestroy(WFrameWindow
*fwin
)
346 if (fwin
->left_button
)
347 wCoreDestroy(fwin
->left_button
);
349 if (fwin
->right_button
)
350 wCoreDestroy(fwin
->right_button
);
353 wCoreDestroy(fwin
->resizebar
);
356 wCoreDestroy(fwin
->titlebar
);
358 RemoveFromStackList(fwin
->core
);
360 wCoreDestroy(fwin
->core
);
365 for (i
=0; i
< (fwin
->flags
.single_texture
? 1 : 3); i
++) {
366 FREE_PIXMAP(fwin
->title_back
[i
]);
367 if (wPreferences
.new_style
) {
368 FREE_PIXMAP(fwin
->lbutton_back
[i
]);
369 FREE_PIXMAP(fwin
->rbutton_back
[i
]);
378 wFrameWindowChangeState(WFrameWindow
*fwin
, int state
)
380 if (fwin
->flags
.state
==state
)
383 fwin
->flags
.state
= state
;
384 fwin
->flags
.need_texture_change
= 1;
386 wFrameWindowPaint(fwin
);
391 updateTitlebar(WFrameWindow
*fwin
)
396 theight
= (*fwin
->font
)->height
+ TITLEBAR_EXTRA_HEIGHT
;
399 w
= fwin
->core
->width
+ 1;
401 if (wPreferences
.new_style
) {
402 if (fwin
->flags
.hide_left_button
|| !fwin
->left_button
403 || fwin
->flags
.lbutton_dont_fit
) {
406 x
= fwin
->left_button
->width
;
407 w
-= fwin
->left_button
->width
;
411 if (wPreferences
.new_style
) {
412 if (!fwin
->flags
.hide_right_button
&& fwin
->right_button
413 && !fwin
->flags
.rbutton_dont_fit
) {
414 w
-= fwin
->right_button
->width
;
418 if (wPreferences
.new_style
|| fwin
->titlebar
->width
!=w
) {
419 fwin
->flags
.need_texture1_remake
= 1;
420 fwin
->flags
.need_texture2_remake
= 1;
421 fwin
->flags
.need_texture3_remake
= 1;
424 wCoreConfigure(fwin
->titlebar
, x
, 0, w
, theight
);
429 wFrameWindowHideButton(WFrameWindow
*fwin
, int flags
)
431 if ((flags
& WFF_RIGHT_BUTTON
) && fwin
->right_button
) {
432 XUnmapWindow(dpy
, fwin
->right_button
->window
);
433 fwin
->flags
.hide_right_button
= 1;
436 if ((flags
& WFF_LEFT_BUTTON
) && fwin
->left_button
) {
437 XUnmapWindow(dpy
, fwin
->left_button
->window
);
438 fwin
->flags
.hide_left_button
= 1;
441 if (fwin
->titlebar
) {
442 if (wPreferences
.new_style
) {
443 updateTitlebar(fwin
);
445 XClearWindow(dpy
, fwin
->titlebar
->window
);
446 wFrameWindowPaint(fwin
);
448 checkTitleSize(fwin
);
454 wFrameWindowShowButton(WFrameWindow
*fwin
, int flags
)
456 if ((flags
& WFF_RIGHT_BUTTON
) && fwin
->right_button
457 && fwin
->flags
.hide_right_button
) {
459 if (!fwin
->flags
.rbutton_dont_fit
)
460 XMapWindow(dpy
, fwin
->right_button
->window
);
462 fwin
->flags
.hide_right_button
= 0;
465 if ((flags
& WFF_LEFT_BUTTON
) && fwin
->left_button
466 && fwin
->flags
.hide_left_button
) {
468 if (!fwin
->flags
.lbutton_dont_fit
)
469 XMapWindow(dpy
, fwin
->left_button
->window
);
471 fwin
->flags
.hide_left_button
= 0;
475 if (fwin
->titlebar
) {
476 if (wPreferences
.new_style
) {
477 updateTitlebar(fwin
);
479 XClearWindow(dpy
, fwin
->titlebar
->window
);
480 wFrameWindowPaint(fwin
);
482 checkTitleSize(fwin
);
488 renderTexture(WScreen
*scr
, WTexture
*texture
, int width
, int height
,
489 int bwidth
, int bheight
, int left
, int right
,
490 Pixmap
*title
, Pixmap
*lbutton
, Pixmap
*rbutton
)
493 RImage
*limg
, *rimg
, *mimg
;
500 img
= wTextureRenderImage(texture
, width
, height
, WREL_FLAT
);
502 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode
));
506 if (wPreferences
.new_style
) {
508 limg
= RGetSubImage(img
, 0, 0, bwidth
, bheight
);
516 RBevelImage(limg
, RBEV_RAISED2
);
517 if (!RConvertImage(scr
->rcontext
, limg
, lbutton
)) {
518 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
526 rimg
= RGetSubImage(img
, width
- bwidth
, 0, bwidth
, bheight
);
531 RBevelImage(rimg
, RBEV_RAISED2
);
532 if (!RConvertImage(scr
->rcontext
, rimg
, rbutton
)) {
533 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
540 mimg
= RGetSubImage(img
, x
, 0, w
, img
->height
);
541 RBevelImage(mimg
, RBEV_RAISED2
);
543 if (!RConvertImage(scr
->rcontext
, mimg
, title
)) {
544 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
548 RBevelImage(img
, RBEV_RAISED2
);
550 if (!RConvertImage(scr
->rcontext
, img
, title
)) {
551 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
555 RBevelImage(img
, RBEV_RAISED2
);
557 if (!RConvertImage(scr
->rcontext
, img
, title
)) {
558 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
567 renderResizebarTexture(WScreen
*scr
, WTexture
*texture
, int width
, int height
,
568 int cwidth
, Pixmap
*pmap
)
576 img
= wTextureRenderImage(texture
, width
, height
, WREL_FLAT
);
578 wwarning(_("could not render texture: %s"),
579 RMessageForError(RErrorCode
));
584 light
.red
= light
.green
= light
.blue
= 80;
587 dark
.red
= dark
.green
= dark
.blue
= 40;
589 ROperateLine(img
, RSubtractOperation
, 0, 0, width
-1, 0, &dark
);
590 ROperateLine(img
, RAddOperation
, 0, 1, width
-1, 1, &light
);
592 ROperateLine(img
, RSubtractOperation
, cwidth
, 2, cwidth
, height
-1, &dark
);
593 ROperateLine(img
, RAddOperation
, cwidth
+1, 2, cwidth
+1, height
-1, &light
);
596 ROperateLine(img
, RSubtractOperation
, width
-cwidth
-2, 2,
597 width
-cwidth
-2, height
-1, &dark
);
598 ROperateLine(img
, RAddOperation
, width
-cwidth
-1, 2, width
-cwidth
-1,
601 #ifdef SHADOW_RESIZEBAR
602 ROperateLine(img
, RAddOperation
, 0, 1, 0, height
-1, &light
);
603 ROperateLine(img
, RSubtractOperation
, width
-1, 1, width
-1, height
-1,
605 ROperateLine(img
, RSubtractOperation
, 0, height
-1, width
-1, height
-1,
607 #endif /* SHADOW_RESIZEBAR */
610 if (!RConvertImage(scr
->rcontext
, img
, pmap
)) {
611 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode
));
620 updateTexture(WFrameWindow
*fwin
)
625 i
= fwin
->flags
.state
;
626 if (fwin
->titlebar
) {
627 if (fwin
->title_texture
[i
]->any
.type
!=WTEX_SOLID
) {
628 XSetWindowBackgroundPixmap(dpy
, fwin
->titlebar
->window
,
629 fwin
->title_back
[i
]);
630 if (wPreferences
.new_style
) {
631 if (fwin
->left_button
&& fwin
->lbutton_back
[i
])
632 XSetWindowBackgroundPixmap(dpy
, fwin
->left_button
->window
,
633 fwin
->lbutton_back
[i
]);
635 if (fwin
->right_button
&& fwin
->rbutton_back
[i
])
636 XSetWindowBackgroundPixmap(dpy
, fwin
->right_button
->window
,
637 fwin
->rbutton_back
[i
]);
640 pixel
= fwin
->title_texture
[i
]->solid
.normal
.pixel
;
641 XSetWindowBackground(dpy
, fwin
->titlebar
->window
, pixel
);
642 if (wPreferences
.new_style
) {
643 if (fwin
->left_button
)
644 XSetWindowBackground(dpy
, fwin
->left_button
->window
,
646 if (fwin
->right_button
)
647 XSetWindowBackground(dpy
, fwin
->right_button
->window
,
651 XClearWindow(dpy
, fwin
->titlebar
->window
);
653 if (fwin
->left_button
) {
654 XClearWindow(dpy
, fwin
->left_button
->window
);
655 handleButtonExpose(&fwin
->left_button
->descriptor
, NULL
);
657 if (fwin
->right_button
) {
658 XClearWindow(dpy
, fwin
->right_button
->window
);
659 handleButtonExpose(&fwin
->right_button
->descriptor
, NULL
);
668 remakeTexture(WFrameWindow
*fwin
, int state
, int newWidth
)
670 Pixmap pmap
, lpmap
, rpmap
;
672 if (fwin
->title_texture
[state
] && fwin
->titlebar
) {
673 FREE_PIXMAP(fwin
->title_back
[state
]);
674 if (wPreferences
.new_style
) {
675 FREE_PIXMAP(fwin
->lbutton_back
[state
]);
676 FREE_PIXMAP(fwin
->rbutton_back
[state
]);
679 if (fwin
->title_texture
[state
]->any
.type
!=WTEX_SOLID
) {
683 /* eventually surrounded by if new_style */
684 left
= fwin
->left_button
&& !fwin
->flags
.hide_left_button
685 && !fwin
->flags
.lbutton_dont_fit
;
686 right
= fwin
->right_button
&& !fwin
->flags
.hide_right_button
687 && !fwin
->flags
.rbutton_dont_fit
;
691 renderTexture(fwin
->screen_ptr
, fwin
->title_texture
[state
],
692 width
, fwin
->titlebar
->height
,
693 fwin
->titlebar
->height
, fwin
->titlebar
->height
,
694 left
, right
, &pmap
, &lpmap
, &rpmap
);
696 fwin
->title_back
[state
] = pmap
;
697 if (wPreferences
.new_style
) {
698 fwin
->lbutton_back
[state
] = lpmap
;
699 fwin
->rbutton_back
[state
] = rpmap
;
703 if (fwin
->resizebar_texture
&& fwin
->resizebar_texture
[0]
704 && fwin
->resizebar
&& state
== fwin
->flags
.state
) {
706 FREE_PIXMAP(fwin
->resizebar_back
[0]);
708 if (fwin
->resizebar_texture
[0]->any
.type
!=WTEX_SOLID
) {
710 renderResizebarTexture(fwin
->screen_ptr
,
711 fwin
->resizebar_texture
[0],
712 newWidth
, fwin
->resizebar
->height
,
713 fwin
->resizebar_corner_width
,
716 fwin
->resizebar_back
[0] = pmap
;
719 /* this part should be in updateTexture() */
720 if (fwin
->resizebar_texture
[0]->any
.type
!=WTEX_SOLID
) {
721 XSetWindowBackgroundPixmap(dpy
, fwin
->resizebar
->window
,
722 fwin
->resizebar_back
[0]);
724 XSetWindowBackground(dpy
, fwin
->resizebar
->window
,
725 fwin
->resizebar_texture
[0]->solid
.normal
.pixel
);
727 XClearWindow(dpy
, fwin
->resizebar
->window
);
733 wFrameWindowPaint(WFrameWindow
*fwin
)
735 if (fwin
->flags
.is_client_window_frame
)
736 fwin
->flags
.justification
= wPreferences
.title_justification
;
738 if (fwin
->flags
.need_texture1_remake
|| fwin
->flags
.need_texture2_remake
739 || fwin
->flags
.need_texture3_remake
) {
741 if (fwin
->flags
.single_texture
) {
743 fwin
->flags
.need_texture_change
= 1;
745 fwin
->flags
.need_texture1_remake
= 0;
746 fwin
->flags
.need_texture2_remake
= 0;
747 fwin
->flags
.need_texture3_remake
= 0;
749 remakeTexture(fwin
, 0, fwin
->core
->width
);
751 } else if (fwin
->flags
.state
==0 && fwin
->flags
.need_texture1_remake
) {
753 fwin
->flags
.need_texture_change
= 1;
754 fwin
->flags
.need_texture1_remake
= 0;
755 remakeTexture(fwin
, fwin
->flags
.state
, fwin
->core
->width
);
757 } else if (fwin
->flags
.state
==1 && fwin
->flags
.need_texture2_remake
) {
759 fwin
->flags
.need_texture_change
= 1;
760 fwin
->flags
.need_texture2_remake
= 0;
761 remakeTexture(fwin
, fwin
->flags
.state
, fwin
->core
->width
);
763 } else if (fwin
->flags
.state
==2 && fwin
->flags
.need_texture3_remake
) {
765 fwin
->flags
.need_texture_change
= 1;
766 fwin
->flags
.need_texture3_remake
= 0;
767 remakeTexture(fwin
, fwin
->flags
.state
, fwin
->core
->width
);
771 if (fwin
->flags
.need_texture_change
) {
772 fwin
->flags
.need_texture_change
= 0;
777 if (fwin
->titlebar
&& !fwin
->flags
.repaint_only_resizebar
778 && fwin
->title_texture
[fwin
->flags
.state
]->any
.type
==WTEX_SOLID
) {
779 wDrawBevel(fwin
->titlebar
->window
, fwin
->titlebar
->width
,
780 fwin
->titlebar
->height
,
781 (WTexSolid
*)fwin
->title_texture
[fwin
->flags
.state
],
785 if (fwin
->resizebar
&& !fwin
->flags
.repaint_only_titlebar
786 && fwin
->resizebar_texture
[0]->any
.type
== WTEX_SOLID
) {
791 WTexSolid
*texture
= (WTexSolid
*)fwin
->resizebar_texture
[0];
793 w
= fwin
->resizebar
->width
;
794 h
= fwin
->resizebar
->height
;
795 cw
= fwin
->resizebar_corner_width
;
796 light_gc
= texture
->light_gc
;
797 dim_gc
= texture
->dim_gc
;
798 win
= fwin
->resizebar
->window
;
800 XDrawLine(dpy
, win
, dim_gc
, 0, 0, w
, 0);
801 XDrawLine(dpy
, win
, light_gc
, 0, 1, w
, 1);
803 XDrawLine(dpy
, win
, dim_gc
, cw
, 2, cw
, h
);
804 XDrawLine(dpy
, win
, light_gc
, cw
+1, 2, cw
+1, h
);
806 XDrawLine(dpy
, win
, dim_gc
, w
-cw
-2, 2, w
-cw
-2, h
);
807 XDrawLine(dpy
, win
, light_gc
, w
-cw
-1, 2, w
-cw
-1, h
);
809 #ifdef SHADOW_RESIZEBAR
810 XDrawLine(dpy
, win
, light_gc
, 0, 1, 0, h
-1);
811 XDrawLine(dpy
, win
, dim_gc
, w
-1, 2, w
-1, h
-1);
812 XDrawLine(dpy
, win
, dim_gc
, 1, h
-1, cw
, h
-1);
813 XDrawLine(dpy
, win
, dim_gc
, cw
+2, h
-1, w
-cw
-2, h
-1);
814 XDrawLine(dpy
, win
, dim_gc
, w
-cw
, h
-1, w
-1, h
-1);
815 #endif /* SHADOW_RESIZEBAR */
819 if (fwin
->title
&& fwin
->titlebar
&& !fwin
->flags
.repaint_only_resizebar
) {
821 int lofs
= 6, rofs
= 6;
827 if (!wPreferences
.new_style
) {
828 if (fwin
->left_button
&& !fwin
->flags
.hide_left_button
829 && !fwin
->flags
.lbutton_dont_fit
)
830 lofs
+= fwin
->left_button
->width
+ 3;
834 if (fwin
->right_button
&& !fwin
->flags
.hide_right_button
835 && !fwin
->flags
.rbutton_dont_fit
)
836 rofs
+= fwin
->right_button
->width
+ 3;
841 #ifdef XKB_TITLE_HINT
842 if(fwin
->flags
.is_client_window_frame
) {
844 freebuff
= (char *)wmalloc((strlen(fwin
->title
)+6)*sizeof(char));
845 if (fwin
->flags
.justification
== WTJ_RIGHT
)
846 sprintf(freebuff
,"%s %s",fwin
->title
,fwin
->languagemode
?XKB_ON
:XKB_OFF
);
848 sprintf(freebuff
,"%s %s",fwin
->languagemode
?XKB_ON
:XKB_OFF
,fwin
->title
);
849 title
= ShrinkString(*fwin
->font
, freebuff
,
850 fwin
->titlebar
->width
- lofs
- rofs
);
853 else title
= ShrinkString(*fwin
->font
, fwin
->title
,
854 fwin
->titlebar
->width
- lofs
- rofs
);
856 title
= ShrinkString(*fwin
->font
, fwin
->title
,
857 fwin
->titlebar
->width
- lofs
- rofs
);
858 #endif /* XKB_TITLE_HINT */
859 titlelen
= strlen(title
);
860 w
= wTextWidth((*fwin
->font
)->font
, title
, titlelen
);
862 switch (fwin
->flags
.justification
) {
868 x
= fwin
->titlebar
->width
- w
- rofs
;
873 x
= lofs
+ (fwin
->titlebar
->width
- w
- lofs
- rofs
) / 2;
875 x
= (fwin
->titlebar
->width
- w
) / 2;
879 #ifdef TITLE_TEXT_SHADOW
880 if(wPreferences
.title_shadow
) {
882 XSetForeground(dpy
, *fwin
->title_gc
,
883 fwin
->title_pixel
[fwin
->flags
.state
+3]);
884 for(shadowx
=0;shadowx
<TITLE_TEXT_SHADOW_WIDTH
;shadowx
++)
885 for(shadowy
=0;shadowy
<TITLE_TEXT_SHADOW_HEIGHT
;shadowy
++)
886 wDrawString(fwin
->titlebar
->window
, *fwin
->font
,
888 x
+ shadowx
+ TITLE_TEXT_SHADOW_X_OFFSET
,
889 (*fwin
->font
)->y
+ TITLEBAR_EXTRA_HEIGHT
/2
890 + shadowy
+ TITLE_TEXT_SHADOW_Y_OFFSET
, title
,
893 #endif /* TITLE_TEXT_SHADOW */
895 XSetForeground(dpy
, *fwin
->title_gc
,
896 fwin
->title_pixel
[fwin
->flags
.state
]);
898 wDrawString(fwin
->titlebar
->window
, *fwin
->font
,
900 (*fwin
->font
)->y
+ TITLEBAR_EXTRA_HEIGHT
/2, title
,
905 if (fwin
->left_button
)
906 handleButtonExpose(&fwin
->left_button
->descriptor
, NULL
);
907 if (fwin
->right_button
)
908 handleButtonExpose(&fwin
->right_button
->descriptor
, NULL
);
914 reconfigure(WFrameWindow
*fwin
, int x
, int y
, int width
, int height
,
917 int k
= (wPreferences
.new_style
? 4 : 3);
918 int resizedHorizontally
= 0;
921 XResizeWindow(dpy
, fwin
->core
->window
, width
, height
);
923 XMoveResizeWindow(dpy
, fwin
->core
->window
, x
, y
, width
, height
);
926 if (fwin->core->height != height && fwin->resizebar)
927 XMoveWindow(dpy, fwin->resizebar->window, 0,
928 height - fwin->resizebar->height);
930 if (fwin
->core
->width
!= width
) {
931 resizedHorizontally
= 1;
934 fwin
->core
->width
= width
;
935 fwin
->core
->height
= height
;
937 if (fwin
->titlebar
&& resizedHorizontally
) {
938 /* Check if the titlebar is wide enough to hold the buttons.
939 * Temporarily remove them if can't
941 if (fwin
->left_button
) {
942 if (width
< fwin
->top_width
*k
&& !fwin
->flags
.lbutton_dont_fit
) {
944 if (!fwin
->flags
.hide_left_button
) {
945 XUnmapWindow(dpy
, fwin
->left_button
->window
);
947 fwin
->flags
.lbutton_dont_fit
= 1;
948 } else if (width
>= fwin
->top_width
*k
&& fwin
->flags
.lbutton_dont_fit
) {
950 if (!fwin
->flags
.hide_left_button
) {
951 XMapWindow(dpy
, fwin
->left_button
->window
);
953 fwin
->flags
.lbutton_dont_fit
= 0;
957 if (fwin
->right_button
) {
958 if (width
< fwin
->top_width
*2 && !fwin
->flags
.rbutton_dont_fit
) {
960 if (!fwin
->flags
.hide_right_button
) {
961 XUnmapWindow(dpy
, fwin
->right_button
->window
);
963 fwin
->flags
.rbutton_dont_fit
= 1;
964 } else if (width
>= fwin
->top_width
*2 && fwin
->flags
.rbutton_dont_fit
) {
966 if (!fwin
->flags
.hide_right_button
) {
967 XMapWindow(dpy
, fwin
->right_button
->window
);
969 fwin
->flags
.rbutton_dont_fit
= 0;
973 if (wPreferences
.new_style
) {
974 if (fwin
->right_button
)
975 XMoveWindow(dpy
, fwin
->right_button
->window
,
976 width
- fwin
->right_button
->width
+ 1, 0);
978 if (fwin
->right_button
)
979 XMoveWindow(dpy
, fwin
->right_button
->window
,
980 width
- fwin
->right_button
->width
- 3,
981 (fwin
->titlebar
->height
- fwin
->right_button
->height
)/2);
983 updateTitlebar(fwin
);
984 checkTitleSize(fwin
);
987 if (fwin
->resizebar
) {
988 wCoreConfigure(fwin
->resizebar
, 0,
989 fwin
->core
->height
- fwin
->resizebar
->height
,
990 fwin
->core
->width
, fwin
->resizebar
->height
);
992 fwin
->resizebar_corner_width
= RESIZEBAR_CORNER_WIDTH
;
993 if (fwin
->core
->width
< RESIZEBAR_CORNER_WIDTH
*2 + RESIZEBAR_MIN_WIDTH
) {
994 fwin
->resizebar_corner_width
= fwin
->core
->width
/2;
1001 wFrameWindowConfigure(WFrameWindow
*fwin
, int x
, int y
, int width
, int height
)
1003 reconfigure(fwin
, x
, y
, width
, height
, False
);
1008 wFrameWindowResize(WFrameWindow
*fwin
, int width
, int height
)
1010 reconfigure(fwin
, 0, 0, width
, height
, True
);
1016 wFrameWindowChangeTitle(WFrameWindow
*fwin
, char *new_title
)
1018 /* check if the title is the same as before */
1020 if (new_title
&& (strcmp(fwin
->title
, new_title
) == 0)) {
1031 fwin
->title
= wstrdup(new_title
);
1033 if (fwin
->titlebar
) {
1034 XClearWindow(dpy
, fwin
->titlebar
->window
);
1036 wFrameWindowPaint(fwin
);
1038 checkTitleSize(fwin
);
1046 wFrameWindowUpdatePushButton(WFrameWindow
*fwin
, Bool pushed
)
1048 fwin
->flags
.right_button_pushed_in
= pushed
;
1050 paintButton(fwin
->right_button
, fwin
->title_texture
[fwin
->flags
.state
],
1051 fwin
->title_pixel
[fwin
->flags
.state
],
1052 fwin
->rbutton_image
, pushed
);
1054 #endif /* OLWM_HINTS */
1058 /*********************************************************************/
1061 handleExpose(WObjDescriptor
*desc
, XEvent
*event
)
1063 WFrameWindow
*fwin
= (WFrameWindow
*)desc
->parent
;
1066 if (fwin
->titlebar
&& fwin
->titlebar
->window
== event
->xexpose
.window
)
1067 fwin
->flags
.repaint_only_titlebar
= 1;
1068 if (fwin
->resizebar
&& fwin
->resizebar
->window
== event
->xexpose
.window
)
1069 fwin
->flags
.repaint_only_resizebar
= 1;
1070 wFrameWindowPaint(fwin
);
1071 fwin
->flags
.repaint_only_titlebar
= 0;
1072 fwin
->flags
.repaint_only_resizebar
= 0;
1077 checkTitleSize(WFrameWindow
*fwin
)
1082 fwin
->flags
.incomplete_title
= 0;
1086 if (!fwin
->titlebar
) {
1087 fwin
->flags
.incomplete_title
= 1;
1090 width
= fwin
->titlebar
->width
- 6 - 6;
1093 if (!wPreferences
.new_style
) {
1094 if (fwin
->left_button
&& !fwin
->flags
.hide_left_button
1095 && !fwin
->flags
.lbutton_dont_fit
)
1096 width
-= fwin
->left_button
->width
+ 3;
1098 if (fwin
->right_button
&& !fwin
->flags
.hide_right_button
1099 && !fwin
->flags
.rbutton_dont_fit
)
1100 width
-= fwin
->right_button
->width
+ 3;
1102 if (wTextWidth((*fwin
->font
)->font
, fwin
->title
,
1103 strlen(fwin
->title
)) > width
) {
1104 fwin
->flags
.incomplete_title
= 1;
1106 fwin
->flags
.incomplete_title
= 0;
1112 paintButton(WCoreWindow
*button
, WTexture
*texture
, unsigned long color
,
1113 WPixmap
*image
, int pushed
)
1115 WScreen
*scr
= button
->screen_ptr
;
1116 GC copy_gc
= scr
->copy_gc
;
1118 int left
=0, width
=0;
1120 /* setup stuff according to the state */
1123 if (image
->width
>=image
->height
*2) {
1124 /* the image contains 2 pictures: the second is for the
1126 width
= image
->width
/2;
1127 left
= image
->width
/2;
1129 width
= image
->width
;
1132 XSetClipMask(dpy
, copy_gc
, None
);
1133 XSetForeground(dpy
, copy_gc
, scr
->white_pixel
);
1135 if (wPreferences
.new_style
) {
1136 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1137 button
->width
-1, button
->height
-1);
1138 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1139 XDrawRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1140 button
->width
-1, button
->height
-1);
1142 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1143 button
->width
, button
->height
);
1144 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1145 XDrawRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1146 button
->width
, button
->height
);
1149 XClearWindow(dpy
, button
->window
);
1152 if (image
->width
>=image
->height
*2)
1153 width
= image
->width
/2;
1155 width
= image
->width
;
1159 if (wPreferences
.new_style
) {
1160 if (texture
->any
.type
==WTEX_SOLID
|| pushed
) {
1161 wDrawBevel(button
->window
, button
->width
, button
->height
,
1162 (WTexSolid
*)texture
, WREL_RAISED
);
1165 wDrawBevel(button
->window
, button
->width
, button
->height
,
1166 scr
->widget_texture
, WREL_RAISED
);
1172 XSetClipMask(dpy
, copy_gc
, image
->mask
);
1173 x
= (button
->width
- width
)/2 + d
;
1174 y
= (button
->height
- image
->height
)/2 + d
;
1175 XSetClipOrigin(dpy
, copy_gc
, x
-left
, y
);
1176 if (!wPreferences
.new_style
) {
1177 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1179 if (image
->depth
==1)
1180 XCopyPlane(dpy
, image
->image
, button
->window
, copy_gc
,
1181 left
, 0, width
, image
->height
, x
, y
, 1);
1183 XCopyArea(dpy
, image
->image
, button
->window
, copy_gc
,
1184 left
, 0, width
, image
->height
, x
, y
);
1186 XSetForeground(dpy
, copy_gc
, scr
->dark_pixel
);
1187 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1188 button
->width
, button
->height
);
1192 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1194 XSetForeground(dpy
, copy_gc
, color
);
1195 XSetBackground(dpy
, copy_gc
, texture
->any
.color
.pixel
);
1197 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1198 button
->width
, button
->height
);
1205 handleButtonExpose(WObjDescriptor
*desc
, XEvent
*event
)
1207 WFrameWindow
*fwin
= (WFrameWindow
*)desc
->parent
;
1208 WCoreWindow
*button
= (WCoreWindow
*)desc
->self
;
1210 if (button
== fwin
->left_button
) {
1211 paintButton(button
, fwin
->title_texture
[fwin
->flags
.state
],
1212 fwin
->title_pixel
[fwin
->flags
.state
],
1213 fwin
->lbutton_image
, False
);
1215 Bool pushed
= False
;
1218 if (fwin
->flags
.right_button_pushed_in
)
1221 /* emulate the olwm pushpin in the "out" state */
1222 paintButton(button
, fwin
->title_texture
[fwin
->flags
.state
],
1223 fwin
->title_pixel
[fwin
->flags
.state
],
1224 fwin
->rbutton_image
, pushed
);
1230 titlebarMouseDown(WObjDescriptor
*desc
, XEvent
*event
)
1232 WFrameWindow
*fwin
= desc
->parent
;
1233 WCoreWindow
*titlebar
= desc
->self
;
1235 if (IsDoubleClick(fwin
->core
->screen_ptr
, event
)) {
1236 if (fwin
->on_dblclick_titlebar
)
1237 (*fwin
->on_dblclick_titlebar
)(titlebar
, fwin
->child
, event
);
1239 if (fwin
->on_mousedown_titlebar
)
1240 (*fwin
->on_mousedown_titlebar
)(titlebar
, fwin
->child
, event
);
1246 resizebarMouseDown(WObjDescriptor
*desc
, XEvent
*event
)
1248 WFrameWindow
*fwin
= desc
->parent
;
1249 WCoreWindow
*resizebar
= desc
->self
;
1251 if (fwin
->on_mousedown_resizebar
)
1252 (*fwin
->on_mousedown_resizebar
)(resizebar
, fwin
->child
, event
);
1257 buttonMouseDown(WObjDescriptor
*desc
, XEvent
*event
)
1259 WFrameWindow
*fwin
= desc
->parent
;
1260 WCoreWindow
*button
= desc
->self
;
1263 int done
=0, execute
=1;
1265 unsigned long pixel
;
1266 int clickButton
= event
->xbutton
.button
;
1268 if (IsDoubleClick(fwin
->core
->screen_ptr
, event
)) {
1269 if (button
== fwin
->right_button
&& fwin
->on_dblclick_right
) {
1270 (*fwin
->on_dblclick_right
)(button
, fwin
->child
, event
);
1275 if (button
== fwin
->left_button
) {
1276 image
= fwin
->lbutton_image
;
1278 image
= fwin
->rbutton_image
;
1281 pixel
= fwin
->title_pixel
[fwin
->flags
.state
];
1282 texture
= fwin
->title_texture
[fwin
->flags
.state
];
1283 paintButton(button
, texture
, pixel
, image
, True
);
1286 WMMaskEvent(dpy
, LeaveWindowMask
|EnterWindowMask
|ButtonReleaseMask
1287 |ButtonPressMask
|ExposureMask
, &ev
);
1291 paintButton(button
, texture
, pixel
, image
, False
);
1296 paintButton(button
, texture
, pixel
, image
, True
);
1303 if (ev
.xbutton
.button
== clickButton
)
1311 paintButton(button
, texture
, pixel
, image
, False
);
1314 if (button
== fwin
->left_button
) {
1315 if (fwin
->on_click_left
)
1316 (*fwin
->on_click_left
)(button
, fwin
->child
, &ev
);
1317 } else if (button
== fwin
->right_button
) {
1318 if (fwin
->on_click_right
)
1319 (*fwin
->on_click_right
)(button
, fwin
->child
, &ev
);