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
;
74 fwin
->flags
.single_texture
= (flags
& WFF_SINGLE_STATE
) ? 1 : 0;
76 fwin
->title_texture
= title_texture
;
77 fwin
->resizebar_texture
= resize_texture
;
78 fwin
->title_pixel
= color
;
82 fwin
->core
= wCoreCreateTopLevel(scr
, x
, y
, width
, height
,
84 if (wPreferences
.use_saveunders
) {
86 XSetWindowAttributes attribs
;
89 attribs
.save_under
= True
;
90 XChangeWindowAttributes(dpy
, fwin
->core
->window
, vmask
, &attribs
);
93 /* setup stacking information */
94 fwin
->core
->stacking
= wmalloc(sizeof(WStacking
));
95 fwin
->core
->stacking
->above
= NULL
;
96 fwin
->core
->stacking
->under
= NULL
;
97 fwin
->core
->stacking
->child_of
= NULL
;
98 fwin
->core
->stacking
->window_level
= wlevel
;
100 AddToStackList(fwin
->core
);
102 wFrameWindowUpdateBorders(fwin
, flags
);
110 wFrameWindowUpdateBorders(WFrameWindow
*fwin
, int flags
)
116 WScreen
*scr
= fwin
->screen_ptr
;
118 width
= fwin
->core
->width
;
119 if (flags
& WFF_IS_SHADED
)
122 height
= fwin
->core
->height
- fwin
->top_width
- fwin
->bottom_width
;
124 if (flags
& WFF_TITLEBAR
)
125 theight
= (*fwin
->font
)->height
+ TITLEBAR_EXTRA_HEIGHT
;
129 if (wPreferences
.new_style
) {
135 if (fwin
->titlebar
) {
136 /* if we had a titlebar and is requesting for one,
137 * check if the size has changed and resize it */
138 if (flags
& WFF_TITLEBAR
) {
139 fwin
->top_width
= theight
;
141 fwin
->flags
.need_texture_remake
= 1;
143 if (wPreferences
.new_style
) {
144 if (fwin
->left_button
) {
145 wCoreConfigure(fwin
->left_button
, 0, 0, bsize
, bsize
);
148 if (fwin
->right_button
) {
149 wCoreConfigure(fwin
->right_button
, width
-bsize
+1,
152 } else { /* !new_style */
153 if (fwin
->left_button
) {
154 wCoreConfigure(fwin
->left_button
, 3, (theight
-bsize
)/2,
158 if (fwin
->right_button
) {
159 wCoreConfigure(fwin
->right_button
, width
-bsize
-3,
160 (theight
-bsize
)/2, bsize
, bsize
);
163 updateTitlebar(fwin
);
165 /* we had a titlebar, but now we don't need it anymore */
166 for (i
=0; i
< (fwin
->flags
.single_texture
? 1 : 3); i
++) {
167 FREE_PIXMAP(fwin
->title_back
[i
]);
168 if (wPreferences
.new_style
) {
169 FREE_PIXMAP(fwin
->lbutton_back
[i
]);
170 FREE_PIXMAP(fwin
->rbutton_back
[i
]);
173 if (fwin
->left_button
)
174 wCoreDestroy(fwin
->left_button
);
175 fwin
->left_button
= NULL
;
177 if (fwin
->right_button
)
178 wCoreDestroy(fwin
->right_button
);
179 fwin
->right_button
= NULL
;
181 wCoreDestroy(fwin
->titlebar
);
182 fwin
->titlebar
= NULL
;
187 /* if we didn't have a titlebar and are being requested for
189 if (flags
& WFF_TITLEBAR
) {
190 fwin
->top_width
= theight
;
192 fwin
->flags
.titlebar
= 1;
193 fwin
->titlebar
= wCoreCreate(fwin
->core
, 0, 0, width
+1, theight
);
195 if (flags
& WFF_LEFT_BUTTON
) {
196 fwin
->flags
.left_button
= 1;
197 if (wPreferences
.new_style
) {
198 fwin
->left_button
= wCoreCreate(fwin
->core
, 0, 0,
200 if (width
< theight
*4) {
201 fwin
->flags
.lbutton_dont_fit
= 1;
203 XMapRaised(dpy
, fwin
->left_button
->window
);
207 wCoreCreate(fwin
->titlebar
, 3, (theight
-bsize
)/2,
210 XSetWindowBackground(dpy
, fwin
->left_button
->window
,
211 scr
->widget_texture
->normal
.pixel
);
213 if (width
< theight
*3) {
214 fwin
->flags
.lbutton_dont_fit
= 1;
216 XMapRaised(dpy
, fwin
->left_button
->window
);
222 if (flags
& WFF_RIGHT_BUTTON
) {
223 fwin
->flags
.right_button
= 1;
224 if (wPreferences
.new_style
) {
226 wCoreCreate(fwin
->core
, width
-bsize
+1, 0,
230 wCoreCreate(fwin
->titlebar
, width
-bsize
-3,
231 (theight
-bsize
)/2, bsize
, bsize
);
232 XSetWindowBackground(dpy
, fwin
->right_button
->window
,
233 scr
->widget_texture
->normal
.pixel
);
236 if (width
< theight
*2) {
237 fwin
->flags
.rbutton_dont_fit
= 1;
239 XMapRaised(dpy
, fwin
->right_button
->window
);
243 if (wPreferences
.new_style
)
244 updateTitlebar(fwin
);
246 XMapRaised(dpy
, fwin
->titlebar
->window
);
248 fwin
->flags
.need_texture_remake
= 1;
251 checkTitleSize(fwin
);
253 if (flags
& WFF_RESIZEBAR
) {
254 fwin
->bottom_width
= RESIZEBAR_HEIGHT
;
256 fwin
->bottom_width
= 0;
259 if (flags
& WFF_RESIZEBAR
) {
260 if (!fwin
->resizebar
) {
261 fwin
->flags
.resizebar
= 1;
262 fwin
->resizebar
= wCoreCreate(fwin
->core
, 0,
263 height
+ fwin
->top_width
,
264 width
, RESIZEBAR_HEIGHT
);
265 fwin
->resizebar_corner_width
= RESIZEBAR_CORNER_WIDTH
;
266 if (width
< RESIZEBAR_CORNER_WIDTH
*2 + RESIZEBAR_MIN_WIDTH
) {
267 fwin
->resizebar_corner_width
= (width
- RESIZEBAR_MIN_WIDTH
)/2;
268 if (fwin
->resizebar_corner_width
< 0)
269 fwin
->resizebar_corner_width
= 0;
272 XMapWindow(dpy
, fwin
->resizebar
->window
);
273 XLowerWindow(dpy
, fwin
->resizebar
->window
);
275 fwin
->flags
.need_texture_remake
= 1;
277 if (height
+fwin
->top_width
+fwin
->bottom_width
!= fwin
->core
->height
) {
278 wCoreConfigure(fwin
->resizebar
, 0, height
+ fwin
->top_width
,
279 width
, RESIZEBAR_HEIGHT
);
283 if (fwin
->resizebar
) {
284 fwin
->bottom_width
= 0;
285 wCoreDestroy(fwin
->resizebar
);
286 fwin
->resizebar
= NULL
;
290 if (height
+ fwin
->top_width
+ fwin
->bottom_width
!= fwin
->core
->height
291 && !(flags
& WFF_IS_SHADED
)) {
292 wFrameWindowResize(fwin
, width
,
293 height
+ fwin
->top_width
+ fwin
->bottom_width
);
296 /* setup object descriptors */
298 if (fwin
->titlebar
) {
299 fwin
->titlebar
->descriptor
.handle_expose
= handleExpose
;
300 fwin
->titlebar
->descriptor
.parent
= fwin
;
301 fwin
->titlebar
->descriptor
.parent_type
= WCLASS_FRAME
;
302 fwin
->titlebar
->descriptor
.handle_mousedown
= titlebarMouseDown
;
305 if (fwin
->resizebar
) {
306 fwin
->resizebar
->descriptor
.handle_expose
= handleExpose
;
307 fwin
->resizebar
->descriptor
.parent
= fwin
;
308 fwin
->resizebar
->descriptor
.parent_type
= WCLASS_FRAME
;
309 fwin
->resizebar
->descriptor
.handle_mousedown
= resizebarMouseDown
;
312 if (fwin
->left_button
) {
313 fwin
->left_button
->descriptor
.handle_expose
= handleButtonExpose
;
314 fwin
->left_button
->descriptor
.parent
= fwin
;
315 fwin
->left_button
->descriptor
.parent_type
= WCLASS_FRAME
;
316 fwin
->left_button
->descriptor
.handle_mousedown
= buttonMouseDown
;
319 if (fwin
->right_button
) {
320 fwin
->right_button
->descriptor
.parent
= fwin
;
321 fwin
->right_button
->descriptor
.parent_type
= WCLASS_FRAME
;
322 fwin
->right_button
->descriptor
.handle_expose
= handleButtonExpose
;
323 fwin
->right_button
->descriptor
.handle_mousedown
= buttonMouseDown
;
326 checkTitleSize(fwin
);
332 wFrameWindowDestroy(WFrameWindow
*fwin
)
336 if (fwin
->left_button
)
337 wCoreDestroy(fwin
->left_button
);
339 if (fwin
->right_button
)
340 wCoreDestroy(fwin
->right_button
);
343 wCoreDestroy(fwin
->resizebar
);
346 wCoreDestroy(fwin
->titlebar
);
348 RemoveFromStackList(fwin
->core
);
350 wCoreDestroy(fwin
->core
);
355 for (i
=0; i
< (fwin
->flags
.single_texture
? 1 : 3); i
++) {
356 FREE_PIXMAP(fwin
->title_back
[i
]);
357 if (wPreferences
.new_style
) {
358 FREE_PIXMAP(fwin
->lbutton_back
[i
]);
359 FREE_PIXMAP(fwin
->rbutton_back
[i
]);
368 wFrameWindowChangeState(WFrameWindow
*fwin
, int state
)
370 if (fwin
->flags
.state
==state
)
373 fwin
->flags
.state
= state
;
374 fwin
->flags
.need_texture_change
= 1;
376 wFrameWindowPaint(fwin
);
381 updateTitlebar(WFrameWindow
*fwin
)
386 theight
= (*fwin
->font
)->height
+ TITLEBAR_EXTRA_HEIGHT
;
389 w
= fwin
->core
->width
+ 1;
391 if (wPreferences
.new_style
) {
392 if (fwin
->flags
.hide_left_button
|| !fwin
->left_button
393 || fwin
->flags
.lbutton_dont_fit
) {
396 x
= fwin
->left_button
->width
;
397 w
-= fwin
->left_button
->width
;
401 if (wPreferences
.new_style
) {
402 if (!fwin
->flags
.hide_right_button
&& fwin
->right_button
403 && !fwin
->flags
.rbutton_dont_fit
) {
404 w
-= fwin
->right_button
->width
;
408 if (wPreferences
.new_style
|| fwin
->titlebar
->width
!=w
)
409 fwin
->flags
.need_texture_remake
= 1;
411 wCoreConfigure(fwin
->titlebar
, x
, 0, w
, theight
);
416 wFrameWindowHideButton(WFrameWindow
*fwin
, int flags
)
418 if ((flags
& WFF_RIGHT_BUTTON
) && fwin
->right_button
) {
419 XUnmapWindow(dpy
, fwin
->right_button
->window
);
420 fwin
->flags
.hide_right_button
= 1;
423 if ((flags
& WFF_LEFT_BUTTON
) && fwin
->left_button
) {
424 XUnmapWindow(dpy
, fwin
->left_button
->window
);
425 fwin
->flags
.hide_left_button
= 1;
428 if (fwin
->titlebar
) {
429 if (wPreferences
.new_style
) {
430 updateTitlebar(fwin
);
432 XClearWindow(dpy
, fwin
->titlebar
->window
);
433 wFrameWindowPaint(fwin
);
435 checkTitleSize(fwin
);
441 wFrameWindowShowButton(WFrameWindow
*fwin
, int flags
)
443 if ((flags
& WFF_RIGHT_BUTTON
) && fwin
->right_button
444 && fwin
->flags
.hide_right_button
) {
446 if (!fwin
->flags
.rbutton_dont_fit
)
447 XMapWindow(dpy
, fwin
->right_button
->window
);
449 fwin
->flags
.hide_right_button
= 0;
452 if ((flags
& WFF_LEFT_BUTTON
) && fwin
->left_button
453 && fwin
->flags
.hide_left_button
) {
455 if (!fwin
->flags
.lbutton_dont_fit
)
456 XMapWindow(dpy
, fwin
->left_button
->window
);
458 fwin
->flags
.hide_left_button
= 0;
462 if (fwin
->titlebar
) {
463 if (wPreferences
.new_style
) {
464 updateTitlebar(fwin
);
466 XClearWindow(dpy
, fwin
->titlebar
->window
);
467 wFrameWindowPaint(fwin
);
469 checkTitleSize(fwin
);
475 renderTexture(WScreen
*scr
, WTexture
*texture
, int width
, int height
,
476 int bwidth
, int bheight
, int left
, int right
,
477 Pixmap
*title
, Pixmap
*lbutton
, Pixmap
*rbutton
)
480 RImage
*limg
, *rimg
, *mimg
;
487 img
= wTextureRenderImage(texture
, width
, height
, WREL_FLAT
);
489 wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode
));
493 if (wPreferences
.new_style
) {
495 limg
= RGetSubImage(img
, 0, 0, bwidth
, bheight
);
503 RBevelImage(limg
, RBEV_RAISED2
);
504 if (!RConvertImage(scr
->rcontext
, limg
, lbutton
)) {
505 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
513 rimg
= RGetSubImage(img
, width
- bwidth
, 0, bwidth
, bheight
);
518 RBevelImage(rimg
, RBEV_RAISED2
);
519 if (!RConvertImage(scr
->rcontext
, rimg
, rbutton
)) {
520 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
527 mimg
= RGetSubImage(img
, x
, 0, w
, img
->height
);
528 RBevelImage(mimg
, RBEV_RAISED2
);
530 if (!RConvertImage(scr
->rcontext
, mimg
, title
)) {
531 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
535 RBevelImage(img
, RBEV_RAISED2
);
537 if (!RConvertImage(scr
->rcontext
, img
, title
)) {
538 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
542 RBevelImage(img
, RBEV_RAISED2
);
544 if (!RConvertImage(scr
->rcontext
, img
, title
)) {
545 wwarning(_("error rendering image:%s"), RMessageForError(RErrorCode
));
554 renderResizebarTexture(WScreen
*scr
, WTexture
*texture
, int width
, int height
,
555 int cwidth
, Pixmap
*pmap
)
563 img
= wTextureRenderImage(texture
, width
, height
, WREL_FLAT
);
565 wwarning(_("could not render texture: %s"),
566 RMessageForError(RErrorCode
));
571 light
.red
= light
.green
= light
.blue
= 80;
574 dark
.red
= dark
.green
= dark
.blue
= 40;
576 ROperateLine(img
, RSubtractOperation
, 0, 0, width
-1, 0, &dark
);
577 ROperateLine(img
, RAddOperation
, 0, 1, width
-1, 1, &light
);
579 ROperateLine(img
, RSubtractOperation
, cwidth
, 2, cwidth
, height
-1, &dark
);
580 ROperateLine(img
, RAddOperation
, cwidth
+1, 2, cwidth
+1, height
-1, &light
);
583 ROperateLine(img
, RSubtractOperation
, width
-cwidth
-2, 2,
584 width
-cwidth
-2, height
-1, &dark
);
585 ROperateLine(img
, RAddOperation
, width
-cwidth
-1, 2, width
-cwidth
-1,
588 #ifdef SHADOW_RESIZEBAR
589 ROperateLine(img
, RAddOperation
, 0, 1, 0, height
-1, &light
);
590 ROperateLine(img
, RSubtractOperation
, width
-1, 1, width
-1, height
-1,
592 ROperateLine(img
, RSubtractOperation
, 0, height
-1, width
-1, height
-1,
594 #endif /* SHADOW_RESIZEBAR */
597 if (!RConvertImage(scr
->rcontext
, img
, pmap
)) {
598 wwarning(_("error rendering image: %s"), RMessageForError(RErrorCode
));
607 updateTexture(WFrameWindow
*fwin
)
612 i
= fwin
->flags
.state
;
613 if (fwin
->titlebar
) {
614 if (fwin
->title_texture
[i
]->any
.type
!=WTEX_SOLID
) {
615 XSetWindowBackgroundPixmap(dpy
, fwin
->titlebar
->window
,
616 fwin
->title_back
[i
]);
617 if (wPreferences
.new_style
) {
618 if (fwin
->left_button
&& fwin
->lbutton_back
[i
])
619 XSetWindowBackgroundPixmap(dpy
, fwin
->left_button
->window
,
620 fwin
->lbutton_back
[i
]);
622 if (fwin
->right_button
&& fwin
->rbutton_back
[i
])
623 XSetWindowBackgroundPixmap(dpy
, fwin
->right_button
->window
,
624 fwin
->rbutton_back
[i
]);
627 pixel
= fwin
->title_texture
[i
]->solid
.normal
.pixel
;
628 XSetWindowBackground(dpy
, fwin
->titlebar
->window
, pixel
);
629 if (wPreferences
.new_style
) {
630 if (fwin
->left_button
)
631 XSetWindowBackground(dpy
, fwin
->left_button
->window
,
633 if (fwin
->right_button
)
634 XSetWindowBackground(dpy
, fwin
->right_button
->window
,
638 XClearWindow(dpy
, fwin
->titlebar
->window
);
640 if (fwin
->left_button
) {
641 XClearWindow(dpy
, fwin
->left_button
->window
);
642 handleButtonExpose(&fwin
->left_button
->descriptor
, NULL
);
644 if (fwin
->right_button
) {
645 XClearWindow(dpy
, fwin
->right_button
->window
);
646 handleButtonExpose(&fwin
->right_button
->descriptor
, NULL
);
654 remakeTexture(WFrameWindow
*fwin
, int state
)
656 Pixmap pmap
, lpmap
, rpmap
;
658 if (fwin
->title_texture
[state
] && fwin
->titlebar
) {
659 FREE_PIXMAP(fwin
->title_back
[state
]);
660 if (wPreferences
.new_style
) {
661 FREE_PIXMAP(fwin
->lbutton_back
[state
]);
662 FREE_PIXMAP(fwin
->rbutton_back
[state
]);
665 if (fwin
->title_texture
[state
]->any
.type
!=WTEX_SOLID
) {
669 /* eventually surrounded by if new_style */
670 left
= fwin
->left_button
&& !fwin
->flags
.hide_left_button
671 && !fwin
->flags
.lbutton_dont_fit
;
672 right
= fwin
->right_button
&& !fwin
->flags
.hide_right_button
673 && !fwin
->flags
.rbutton_dont_fit
;
675 width
= fwin
->core
->width
+1;
677 renderTexture(fwin
->screen_ptr
, fwin
->title_texture
[state
],
678 width
, fwin
->titlebar
->height
,
679 fwin
->titlebar
->height
, fwin
->titlebar
->height
,
680 left
, right
, &pmap
, &lpmap
, &rpmap
);
682 fwin
->title_back
[state
] = pmap
;
683 if (wPreferences
.new_style
) {
684 fwin
->lbutton_back
[state
] = lpmap
;
685 fwin
->rbutton_back
[state
] = rpmap
;
689 if (fwin
->resizebar_texture
&& fwin
->resizebar_texture
[0]
690 && fwin
->resizebar
&& state
== 0) {
692 FREE_PIXMAP(fwin
->resizebar_back
[0]);
694 if (fwin
->resizebar_texture
[0]->any
.type
!=WTEX_SOLID
) {
696 renderResizebarTexture(fwin
->screen_ptr
,
697 fwin
->resizebar_texture
[0],
698 fwin
->resizebar
->width
,
699 fwin
->resizebar
->height
,
700 fwin
->resizebar_corner_width
,
703 fwin
->resizebar_back
[0] = pmap
;
706 /* this part should be in updateTexture() */
707 if (fwin
->resizebar_texture
[0]->any
.type
!=WTEX_SOLID
) {
708 XSetWindowBackgroundPixmap(dpy
, fwin
->resizebar
->window
,
709 fwin
->resizebar_back
[0]);
711 XSetWindowBackground(dpy
, fwin
->resizebar
->window
,
712 fwin
->resizebar_texture
[0]->solid
.normal
.pixel
);
714 XClearWindow(dpy
, fwin
->resizebar
->window
);
720 wFrameWindowPaint(WFrameWindow
*fwin
)
722 if (fwin
->flags
.is_client_window_frame
)
723 fwin
->flags
.justification
= wPreferences
.title_justification
;
725 if (fwin
->flags
.need_texture_remake
) {
728 fwin
->flags
.need_texture_remake
= 0;
729 fwin
->flags
.need_texture_change
= 0;
731 if (fwin
->flags
.single_texture
) {
732 remakeTexture(fwin
, 0);
735 /* first render the texture for the current state... */
736 remakeTexture(fwin
, fwin
->flags
.state
);
737 /* ... and paint it */
740 for (i
=0; i
< 3; i
++) {
741 if (i
!=fwin
->flags
.state
)
742 remakeTexture(fwin
, i
);
747 if (fwin
->flags
.need_texture_change
) {
748 fwin
->flags
.need_texture_change
= 0;
753 if (fwin
->titlebar
&& !fwin
->flags
.repaint_only_resizebar
754 && fwin
->title_texture
[fwin
->flags
.state
]->any
.type
==WTEX_SOLID
) {
755 wDrawBevel(fwin
->titlebar
->window
, fwin
->titlebar
->width
,
756 fwin
->titlebar
->height
,
757 (WTexSolid
*)fwin
->title_texture
[fwin
->flags
.state
],
761 if (fwin
->resizebar
&& !fwin
->flags
.repaint_only_titlebar
762 && fwin
->resizebar_texture
[0]->any
.type
== WTEX_SOLID
) {
767 WTexSolid
*texture
= (WTexSolid
*)fwin
->resizebar_texture
[0];
769 w
= fwin
->resizebar
->width
;
770 h
= fwin
->resizebar
->height
;
771 cw
= fwin
->resizebar_corner_width
;
772 light_gc
= texture
->light_gc
;
773 dim_gc
= texture
->dim_gc
;
774 win
= fwin
->resizebar
->window
;
776 XDrawLine(dpy
, win
, dim_gc
, 0, 0, w
, 0);
777 XDrawLine(dpy
, win
, light_gc
, 0, 1, w
, 1);
779 XDrawLine(dpy
, win
, dim_gc
, cw
, 2, cw
, h
);
780 XDrawLine(dpy
, win
, light_gc
, cw
+1, 2, cw
+1, h
);
782 XDrawLine(dpy
, win
, dim_gc
, w
-cw
-2, 2, w
-cw
-2, h
);
783 XDrawLine(dpy
, win
, light_gc
, w
-cw
-1, 2, w
-cw
-1, h
);
785 #ifdef SHADOW_RESIZEBAR
786 XDrawLine(dpy
, win
, light_gc
, 0, 1, 0, h
-1);
787 XDrawLine(dpy
, win
, dim_gc
, w
-1, 2, w
-1, h
-1);
788 XDrawLine(dpy
, win
, dim_gc
, 1, h
-1, cw
, h
-1);
789 XDrawLine(dpy
, win
, dim_gc
, cw
+2, h
-1, w
-cw
-2, h
-1);
790 XDrawLine(dpy
, win
, dim_gc
, w
-cw
, h
-1, w
-1, h
-1);
791 #endif /* SHADOW_RESIZEBAR */
795 if (fwin
->title
&& fwin
->titlebar
&& !fwin
->flags
.repaint_only_resizebar
) {
797 int lofs
= 6, rofs
= 6;
803 if (!wPreferences
.new_style
) {
804 if (fwin
->left_button
&& !fwin
->flags
.hide_left_button
805 && !fwin
->flags
.lbutton_dont_fit
)
806 lofs
+= fwin
->left_button
->width
+ 3;
810 if (fwin
->right_button
&& !fwin
->flags
.hide_right_button
811 && !fwin
->flags
.rbutton_dont_fit
)
812 rofs
+= fwin
->right_button
->width
+ 3;
817 #ifdef XKB_TITLE_HINT
818 if(fwin
->flags
.is_client_window_frame
) {
820 freebuff
= (char *)wmalloc((strlen(fwin
->title
)+6)*sizeof(char));
821 if (fwin
->flags
.justification
== WTJ_RIGHT
)
822 sprintf(freebuff
,"%s %s",fwin
->title
,fwin
->languagemode
?XKB_ON
:XKB_OFF
);
824 sprintf(freebuff
,"%s %s",fwin
->languagemode
?XKB_ON
:XKB_OFF
,fwin
->title
);
825 title
= ShrinkString(*fwin
->font
, freebuff
,
826 fwin
->titlebar
->width
- lofs
- rofs
);
829 else title
= ShrinkString(*fwin
->font
, fwin
->title
,
830 fwin
->titlebar
->width
- lofs
- rofs
);
832 title
= ShrinkString(*fwin
->font
, fwin
->title
,
833 fwin
->titlebar
->width
- lofs
- rofs
);
834 #endif /* XKB_TITLE_HINT */
835 titlelen
= strlen(title
);
836 w
= wTextWidth((*fwin
->font
)->font
, title
, titlelen
);
838 switch (fwin
->flags
.justification
) {
844 x
= fwin
->titlebar
->width
- w
- rofs
;
849 x
= lofs
+ (fwin
->titlebar
->width
- w
- lofs
- rofs
) / 2;
851 x
= (fwin
->titlebar
->width
- w
) / 2;
855 #ifdef TITLE_TEXT_SHADOW
856 if(wPreferences
.title_shadow
){
858 XSetForeground(dpy
, *fwin
->title_gc
,
859 fwin
->title_pixel
[fwin
->flags
.state
+3]);
860 for(shadowx
=0;shadowx
<TITLE_TEXT_SHADOW_WIDTH
;shadowx
++)
861 for(shadowy
=0;shadowy
<TITLE_TEXT_SHADOW_HEIGHT
;shadowy
++)
862 wDrawString(fwin
->titlebar
->window
, *fwin
->font
,
864 x
+ shadowx
+ TITLE_TEXT_SHADOW_X_OFFSET
,
865 (*fwin
->font
)->y
+ TITLEBAR_EXTRA_HEIGHT
/2
866 + shadowy
+ TITLE_TEXT_SHADOW_Y_OFFSET
, title
,
869 #endif /* TITLE_TEXT_SHADOW */
871 XSetForeground(dpy
, *fwin
->title_gc
,
872 fwin
->title_pixel
[fwin
->flags
.state
]);
874 wDrawString(fwin
->titlebar
->window
, *fwin
->font
,
876 (*fwin
->font
)->y
+ TITLEBAR_EXTRA_HEIGHT
/2, title
,
881 if (fwin
->left_button
)
882 handleButtonExpose(&fwin
->left_button
->descriptor
, NULL
);
883 if (fwin
->right_button
)
884 handleButtonExpose(&fwin
->right_button
->descriptor
, NULL
);
890 reconfigure(WFrameWindow
*fwin
, int x
, int y
, int width
, int height
,
893 int k
= (wPreferences
.new_style
? 4 : 3);
894 int resizedHorizontally
= 0;
897 XResizeWindow(dpy
, fwin
->core
->window
, width
, height
);
899 XMoveResizeWindow(dpy
, fwin
->core
->window
, x
, y
, width
, height
);
902 if (fwin->core->height != height && fwin->resizebar)
903 XMoveWindow(dpy, fwin->resizebar->window, 0,
904 height - fwin->resizebar->height);
906 if (fwin
->core
->width
!= width
) {
907 fwin
->flags
.need_texture_remake
= 1;
908 resizedHorizontally
= 1;
911 fwin
->core
->width
= width
;
912 fwin
->core
->height
= height
;
914 if (fwin
->titlebar
&& resizedHorizontally
) {
915 /* Check if the titlebar is wide enough to hold the buttons.
916 * Temporarily remove them if can't
918 if (fwin
->left_button
) {
919 if (width
< fwin
->top_width
*k
&& !fwin
->flags
.lbutton_dont_fit
) {
921 if (!fwin
->flags
.hide_left_button
) {
922 XUnmapWindow(dpy
, fwin
->left_button
->window
);
924 fwin
->flags
.lbutton_dont_fit
= 1;
925 } else if (width
>= fwin
->top_width
*k
&& fwin
->flags
.lbutton_dont_fit
) {
927 if (!fwin
->flags
.hide_left_button
) {
928 XMapWindow(dpy
, fwin
->left_button
->window
);
930 fwin
->flags
.lbutton_dont_fit
= 0;
934 if (fwin
->right_button
) {
935 if (width
< fwin
->top_width
*2 && !fwin
->flags
.rbutton_dont_fit
) {
937 if (!fwin
->flags
.hide_right_button
) {
938 XUnmapWindow(dpy
, fwin
->right_button
->window
);
940 fwin
->flags
.rbutton_dont_fit
= 1;
941 } else if (width
>= fwin
->top_width
*2 && fwin
->flags
.rbutton_dont_fit
) {
943 if (!fwin
->flags
.hide_right_button
) {
944 XMapWindow(dpy
, fwin
->right_button
->window
);
946 fwin
->flags
.rbutton_dont_fit
= 0;
950 if (wPreferences
.new_style
) {
951 if (fwin
->right_button
)
952 XMoveWindow(dpy
, fwin
->right_button
->window
,
953 width
- fwin
->right_button
->width
+ 1, 0);
955 if (fwin
->right_button
)
956 XMoveWindow(dpy
, fwin
->right_button
->window
,
957 width
- fwin
->right_button
->width
- 3,
958 (fwin
->titlebar
->height
- fwin
->right_button
->height
)/2);
960 updateTitlebar(fwin
);
961 checkTitleSize(fwin
);
964 if (fwin
->resizebar
) {
965 wCoreConfigure(fwin
->resizebar
, 0,
966 fwin
->core
->height
- fwin
->resizebar
->height
,
967 fwin
->core
->width
, fwin
->resizebar
->height
);
969 fwin
->resizebar_corner_width
= RESIZEBAR_CORNER_WIDTH
;
970 if (fwin
->core
->width
< RESIZEBAR_CORNER_WIDTH
*2 + RESIZEBAR_MIN_WIDTH
) {
971 fwin
->resizebar_corner_width
= fwin
->core
->width
/2;
977 wFrameWindowConfigure(WFrameWindow
*fwin
, int x
, int y
, int width
, int height
)
979 reconfigure(fwin
, x
, y
, width
, height
, False
);
983 wFrameWindowResize(WFrameWindow
*fwin
, int width
, int height
)
985 reconfigure(fwin
, 0, 0, width
, height
, True
);
991 wFrameWindowChangeTitle(WFrameWindow
*fwin
, char *new_title
)
993 /* check if the title is the same as before */
995 if (new_title
&& (strcmp(fwin
->title
, new_title
) == 0)) {
1006 fwin
->title
= wstrdup(new_title
);
1008 if (fwin
->titlebar
) {
1009 XClearWindow(dpy
, fwin
->titlebar
->window
);
1011 wFrameWindowPaint(fwin
);
1013 checkTitleSize(fwin
);
1021 wFrameWindowUpdatePushButton(WFrameWindow
*fwin
, Bool pushed
)
1023 fwin
->flags
.right_button_pushed_in
= pushed
;
1025 paintButton(fwin
->right_button
, fwin
->title_texture
[fwin
->flags
.state
],
1026 fwin
->title_pixel
[fwin
->flags
.state
],
1027 fwin
->rbutton_image
, pushed
);
1029 #endif /* OLWM_HINTS */
1033 /*********************************************************************/
1036 handleExpose(WObjDescriptor
*desc
, XEvent
*event
)
1038 WFrameWindow
*fwin
= (WFrameWindow
*)desc
->parent
;
1041 if (fwin
->titlebar
&& fwin
->titlebar
->window
== event
->xexpose
.window
)
1042 fwin
->flags
.repaint_only_titlebar
= 1;
1043 if (fwin
->resizebar
&& fwin
->resizebar
->window
== event
->xexpose
.window
)
1044 fwin
->flags
.repaint_only_resizebar
= 1;
1045 wFrameWindowPaint(fwin
);
1046 fwin
->flags
.repaint_only_titlebar
= 0;
1047 fwin
->flags
.repaint_only_resizebar
= 0;
1052 checkTitleSize(WFrameWindow
*fwin
)
1057 fwin
->flags
.incomplete_title
= 0;
1061 if (!fwin
->titlebar
) {
1062 fwin
->flags
.incomplete_title
= 1;
1065 width
= fwin
->titlebar
->width
- 6 - 6;
1068 if (!wPreferences
.new_style
) {
1069 if (fwin
->left_button
&& !fwin
->flags
.hide_left_button
1070 && !fwin
->flags
.lbutton_dont_fit
)
1071 width
-= fwin
->left_button
->width
+ 3;
1073 if (fwin
->right_button
&& !fwin
->flags
.hide_right_button
1074 && !fwin
->flags
.rbutton_dont_fit
)
1075 width
-= fwin
->right_button
->width
+ 3;
1077 if (wTextWidth((*fwin
->font
)->font
, fwin
->title
,
1078 strlen(fwin
->title
)) > width
) {
1079 fwin
->flags
.incomplete_title
= 1;
1081 fwin
->flags
.incomplete_title
= 0;
1087 paintButton(WCoreWindow
*button
, WTexture
*texture
, unsigned long color
,
1088 WPixmap
*image
, int pushed
)
1090 WScreen
*scr
= button
->screen_ptr
;
1091 GC copy_gc
= scr
->copy_gc
;
1093 int left
=0, width
=0;
1095 /* setup stuff according to the state */
1098 if (image
->width
>=image
->height
*2) {
1099 /* the image contains 2 pictures: the second is for the
1101 width
= image
->width
/2;
1102 left
= image
->width
/2;
1104 width
= image
->width
;
1107 XSetClipMask(dpy
, copy_gc
, None
);
1108 XSetForeground(dpy
, copy_gc
, scr
->white_pixel
);
1110 if (wPreferences
.new_style
) {
1111 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1112 button
->width
-1, button
->height
-1);
1113 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1114 XDrawRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1115 button
->width
-1, button
->height
-1);
1117 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1118 button
->width
, button
->height
);
1119 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1120 XDrawRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1121 button
->width
, button
->height
);
1124 XClearWindow(dpy
, button
->window
);
1127 if (image
->width
>=image
->height
*2)
1128 width
= image
->width
/2;
1130 width
= image
->width
;
1134 if (wPreferences
.new_style
) {
1135 if (texture
->any
.type
==WTEX_SOLID
|| pushed
) {
1136 wDrawBevel(button
->window
, button
->width
, button
->height
,
1137 (WTexSolid
*)texture
, WREL_RAISED
);
1140 wDrawBevel(button
->window
, button
->width
, button
->height
,
1141 scr
->widget_texture
, WREL_RAISED
);
1147 XSetClipMask(dpy
, copy_gc
, image
->mask
);
1148 x
= (button
->width
- width
)/2 + d
;
1149 y
= (button
->height
- image
->height
)/2 + d
;
1150 XSetClipOrigin(dpy
, copy_gc
, x
-left
, y
);
1151 if (!wPreferences
.new_style
) {
1152 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1154 if (image
->depth
==1)
1155 XCopyPlane(dpy
, image
->image
, button
->window
, copy_gc
,
1156 left
, 0, width
, image
->height
, x
, y
, 1);
1158 XCopyArea(dpy
, image
->image
, button
->window
, copy_gc
,
1159 left
, 0, width
, image
->height
, x
, y
);
1161 XSetForeground(dpy
, copy_gc
, scr
->dark_pixel
);
1162 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1163 button
->width
, button
->height
);
1167 XSetForeground(dpy
, copy_gc
, scr
->black_pixel
);
1169 XSetForeground(dpy
, copy_gc
, color
);
1170 XSetBackground(dpy
, copy_gc
, texture
->any
.color
.pixel
);
1172 XFillRectangle(dpy
, button
->window
, copy_gc
, 0, 0,
1173 button
->width
, button
->height
);
1180 handleButtonExpose(WObjDescriptor
*desc
, XEvent
*event
)
1182 WFrameWindow
*fwin
= (WFrameWindow
*)desc
->parent
;
1183 WCoreWindow
*button
= (WCoreWindow
*)desc
->self
;
1185 if (button
== fwin
->left_button
) {
1186 paintButton(button
, fwin
->title_texture
[fwin
->flags
.state
],
1187 fwin
->title_pixel
[fwin
->flags
.state
],
1188 fwin
->lbutton_image
, False
);
1190 Bool pushed
= False
;
1193 if (fwin
->flags
.right_button_pushed_in
)
1196 /* emulate the olwm pushpin in the "out" state */
1197 paintButton(button
, fwin
->title_texture
[fwin
->flags
.state
],
1198 fwin
->title_pixel
[fwin
->flags
.state
],
1199 fwin
->rbutton_image
, pushed
);
1205 titlebarMouseDown(WObjDescriptor
*desc
, XEvent
*event
)
1207 WFrameWindow
*fwin
= desc
->parent
;
1208 WCoreWindow
*titlebar
= desc
->self
;
1210 if (IsDoubleClick(fwin
->core
->screen_ptr
, event
)) {
1211 if (fwin
->on_dblclick_titlebar
)
1212 (*fwin
->on_dblclick_titlebar
)(titlebar
, fwin
->child
, event
);
1214 if (fwin
->on_mousedown_titlebar
)
1215 (*fwin
->on_mousedown_titlebar
)(titlebar
, fwin
->child
, event
);
1221 resizebarMouseDown(WObjDescriptor
*desc
, XEvent
*event
)
1223 WFrameWindow
*fwin
= desc
->parent
;
1224 WCoreWindow
*resizebar
= desc
->self
;
1226 if (fwin
->on_mousedown_resizebar
)
1227 (*fwin
->on_mousedown_resizebar
)(resizebar
, fwin
->child
, event
);
1232 buttonMouseDown(WObjDescriptor
*desc
, XEvent
*event
)
1234 WFrameWindow
*fwin
= desc
->parent
;
1235 WCoreWindow
*button
= desc
->self
;
1238 int done
=0, execute
=1;
1240 unsigned long pixel
;
1241 int clickButton
= event
->xbutton
.button
;
1243 if (IsDoubleClick(fwin
->core
->screen_ptr
, event
)) {
1244 if (button
== fwin
->right_button
&& fwin
->on_dblclick_right
) {
1245 (*fwin
->on_dblclick_right
)(button
, fwin
->child
, event
);
1250 if (button
== fwin
->left_button
) {
1251 image
= fwin
->lbutton_image
;
1253 image
= fwin
->rbutton_image
;
1256 pixel
= fwin
->title_pixel
[fwin
->flags
.state
];
1257 texture
= fwin
->title_texture
[fwin
->flags
.state
];
1258 paintButton(button
, texture
, pixel
, image
, True
);
1261 WMMaskEvent(dpy
, LeaveWindowMask
|EnterWindowMask
|ButtonReleaseMask
1262 |ButtonPressMask
|ExposureMask
, &ev
);
1266 paintButton(button
, texture
, pixel
, image
, False
);
1271 paintButton(button
, texture
, pixel
, image
, True
);
1278 if (ev
.xbutton
.button
== clickButton
)
1286 paintButton(button
, texture
, pixel
, image
, False
);
1289 if (button
== fwin
->left_button
) {
1290 if (fwin
->on_click_left
)
1291 (*fwin
->on_click_left
)(button
, fwin
->child
, &ev
);
1292 } else if (button
== fwin
->right_button
) {
1293 if (fwin
->on_click_right
)
1294 (*fwin
->on_click_right
)(button
, fwin
->child
, &ev
);