2 * Window Maker window manager
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
5 * Copyright (c) 1998-2003 Dan Pascu
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
26 #include <X11/Xutil.h>
35 #include "WindowMaker.h"
37 #include "superfluous.h"
45 extern WPreferences wPreferences
;
48 static void play(Display
* dpy
, int pitch
, int delay
)
52 kc
.bell_pitch
= pitch
;
54 kc
.bell_duration
= delay
;
55 XChangeKeyboardControl(dpy
, KBBellPitch
| KBBellDuration
| KBBellPercent
, &kc
);
62 #ifdef DEMATERIALIZE_ICON
63 void DoKaboom(WScreen
* scr
, Window win
, int x
, int y
)
77 h
= w
= wPreferences
.icon_size
;
78 if (x
< 0 || x
+ w
> scr
->scr_width
|| y
< 0 || y
+ h
> scr
->scr_height
)
81 icon
= RCreateImageFromDrawable(scr
->rcontext
, win
, None
);
85 gcv
.foreground
= scr
->white_pixel
;
86 gcv
.background
= scr
->black_pixel
;
87 gcv
.graphics_exposures
= False
;
88 gcv
.subwindow_mode
= IncludeInferiors
;
89 gc
= XCreateGC(dpy
, scr
->w_win
, GCForeground
| GCBackground
| GCSubwindowMode
| GCGraphicsExposures
, &gcv
);
92 RConvertImage(scr
->rcontext
, icon
, &pixmap
);
93 XUnmapWindow(dpy
, win
);
95 ximage
= XGetImage(dpy
, scr
->root_win
, x
, y
, w
, h
, AllPlanes
, ZPixmap
);
96 XCopyArea(dpy
, pixmap
, scr
->root_win
, gc
, 0, 0, w
, h
, x
, y
);
97 XFreePixmap(dpy
, pixmap
);
99 back
= RCreateImageFromXImage(scr
->rcontext
, ximage
, NULL
);
100 XDestroyImage(ximage
);
106 for (i
= 0, run
= 0; i
< DEMATERIALIZE_STEPS
; i
++) {
108 if (!run
&& XCheckTypedEvent(dpy
, ButtonPress
, &foo
)) {
110 XPutBackEvent(dpy
, &foo
);
112 image
= RCloneImage(back
);
113 RCombineImagesWithOpaqueness(image
, icon
,
114 (DEMATERIALIZE_STEPS
- 1 - i
) * 256 / (DEMATERIALIZE_STEPS
+ 2));
115 RConvertImage(scr
->rcontext
, image
, &pixmap
);
116 XCopyArea(dpy
, pixmap
, scr
->root_win
, gc
, 0, 0, w
, h
, x
, y
);
117 XFreePixmap(dpy
, pixmap
);
123 while (XCheckTypedEvent(dpy
, MotionNotify
, &event
)) {
132 #endif /* DEMATERIALIZE_ICON */
134 #ifdef NORMAL_ICON_KABOOM
135 void DoKaboom(WScreen
* scr
, Window win
, int x
, int y
)
138 int sw
= scr
->scr_width
, sh
= scr
->scr_height
;
139 #define KAB_PRECISION 4
142 #ifdef ICON_KABOOM_EXTRA
143 short ptx
[2][PIECES
], pty
[2][PIECES
];
146 char pvx
[PIECES
], pvy
[PIECES
];
147 /* in MkLinux/PPC gcc seems to think that char is unsigned? */
148 signed char ax
[PIECES
], ay
[PIECES
];
151 XSetClipMask(dpy
, scr
->copy_gc
, None
);
152 tmp
= XCreatePixmap(dpy
, scr
->root_win
, wPreferences
.icon_size
, wPreferences
.icon_size
, scr
->depth
);
153 if (scr
->w_visual
== DefaultVisual(dpy
, scr
->screen
))
154 XCopyArea(dpy
, win
, tmp
, scr
->copy_gc
, 0, 0, wPreferences
.icon_size
, wPreferences
.icon_size
, 0, 0);
158 image
= XGetImage(dpy
, win
, 0, 0, wPreferences
.icon_size
,
159 wPreferences
.icon_size
, AllPlanes
, ZPixmap
);
161 XUnmapWindow(dpy
, win
);
164 XPutImage(dpy
, tmp
, scr
->copy_gc
, image
, 0, 0, 0, 0,
165 wPreferences
.icon_size
, wPreferences
.icon_size
);
166 XDestroyImage(image
);
169 for (i
= 0, k
= 0; i
< wPreferences
.icon_size
/ ICON_KABOOM_PIECE_SIZE
&& k
< PIECES
; i
++) {
170 for (j
= 0; j
< wPreferences
.icon_size
/ ICON_KABOOM_PIECE_SIZE
&& k
< PIECES
; j
++) {
174 px
[k
] = (x
+ i
* ICON_KABOOM_PIECE_SIZE
) << KAB_PRECISION
;
175 py
[k
] = y
+ j
* ICON_KABOOM_PIECE_SIZE
;
176 pvx
[k
] = rand() % (1 << (KAB_PRECISION
+ 3)) - (1 << (KAB_PRECISION
+ 3)) / 2;
177 pvy
[k
] = -15 - rand() % 7;
178 #ifdef ICON_KABOOM_EXTRA
179 for (ll
= 0; ll
< 2; ll
++) {
191 XUnmapWindow(dpy
, win
);
197 if (XCheckTypedEvent(dpy
, ButtonPress
, &foo
)) {
198 XPutBackEvent(dpy
, &foo
);
199 XClearWindow(dpy
, scr
->root_win
);
203 for (i
= 0; i
< j
; i
++) {
205 int _px
= px
[i
] >> KAB_PRECISION
;
206 #ifdef ICON_KABOOM_EXTRA
207 XClearArea(dpy
, scr
->root_win
, ptx
[1][i
], pty
[1][i
],
208 ICON_KABOOM_PIECE_SIZE
, ICON_KABOOM_PIECE_SIZE
, False
);
210 ptx
[1][i
] = ptx
[0][i
];
211 pty
[1][i
] = pty
[0][i
];
215 XClearArea(dpy
, scr
->root_win
, _px
, py
[i
],
216 ICON_KABOOM_PIECE_SIZE
, ICON_KABOOM_PIECE_SIZE
, False
);
220 _px
= px
[i
] >> KAB_PRECISION
;
222 if (_px
< -wPreferences
.icon_size
|| _px
> sw
|| py
[i
] >= sh
) {
223 #ifdef ICON_KABOOM_EXTRA
224 if (py
[i
] > sh
&& _px
< sw
&& _px
> 0) {
225 pvy
[i
] = -(pvy
[i
] / 2);
226 if (abs(pvy
[i
]) > 3) {
227 py
[i
] = sh
- ICON_KABOOM_PIECE_SIZE
;
228 XCopyArea(dpy
, tmp
, scr
->root_win
, scr
->copy_gc
,
229 ax
[i
] * ICON_KABOOM_PIECE_SIZE
,
230 ay
[i
] * ICON_KABOOM_PIECE_SIZE
,
231 ICON_KABOOM_PIECE_SIZE
,
232 ICON_KABOOM_PIECE_SIZE
, _px
, py
[i
]);
240 for (ll
= 0; ll
< 2; ll
++)
241 XClearArea(dpy
, scr
->root_win
, ptx
[ll
][i
], pty
[ll
][i
],
242 ICON_KABOOM_PIECE_SIZE
,
243 ICON_KABOOM_PIECE_SIZE
, False
);
246 #else /* !ICON_KABOOM_EXTRA */
249 #endif /* !ICON_KABOOM_EXTRA */
251 XCopyArea(dpy
, tmp
, scr
->root_win
, scr
->copy_gc
,
252 ax
[i
] * ICON_KABOOM_PIECE_SIZE
, ay
[i
] * ICON_KABOOM_PIECE_SIZE
,
253 ICON_KABOOM_PIECE_SIZE
, ICON_KABOOM_PIECE_SIZE
, _px
, py
[i
]);
260 play(dpy
, 100 + rand() % 250, 12);
262 # if (MINIATURIZE_ANIMATION_DELAY_Z > 0)
263 wusleep(MINIATURIZE_ANIMATION_DELAY_Z
* 2);
268 XFreePixmap(dpy
, tmp
);
270 #endif /* NORMAL_ICON_KABOOM */
272 Pixmap
MakeGhostDock(WDock
* dock
, int sx
, int dx
, int y
)
274 WScreen
*scr
= dock
->screen_ptr
;
276 RImage
*back
, *dock_image
;
278 int i
, virtual_tiles
, h
, j
, n
;
279 unsigned long red_mask
, green_mask
, blue_mask
;
282 for (i
= 0; i
< dock
->max_icons
; i
++) {
283 if (dock
->icon_array
[i
] != NULL
&& dock
->icon_array
[i
]->yindex
> virtual_tiles
)
284 virtual_tiles
= dock
->icon_array
[i
]->yindex
;
287 h
= virtual_tiles
* wPreferences
.icon_size
;
288 h
= (y
+ h
> scr
->scr_height
) ? scr
->scr_height
- y
: h
;
289 virtual_tiles
= h
/ wPreferences
.icon_size
; /* The visible ones */
290 if (h
% wPreferences
.icon_size
)
291 virtual_tiles
++; /* There is one partially visible tile at end */
293 img
= XGetImage(dpy
, scr
->root_win
, dx
, y
, wPreferences
.icon_size
, h
, AllPlanes
, ZPixmap
);
297 red_mask
= img
->red_mask
;
298 green_mask
= img
->green_mask
;
299 blue_mask
= img
->blue_mask
;
301 back
= RCreateImageFromXImage(scr
->rcontext
, img
, NULL
);
307 for (i
= 0; i
< dock
->max_icons
; i
++) {
308 if (dock
->icon_array
[i
] != NULL
&& dock
->icon_array
[i
]->yindex
< virtual_tiles
) {
310 j
= dock
->icon_array
[i
]->yindex
* wPreferences
.icon_size
;
311 n
= (h
- j
< wPreferences
.icon_size
) ? h
- j
: wPreferences
.icon_size
;
312 if (dock
->icon_array
[i
]->icon
->pixmap
)
313 which
= dock
->icon_array
[i
]->icon
->pixmap
;
315 which
= dock
->icon_array
[i
]->icon
->core
->window
;
317 img
= XGetImage(dpy
, which
, 0, 0, wPreferences
.icon_size
, n
, AllPlanes
, ZPixmap
);
323 img
->red_mask
= red_mask
;
324 img
->green_mask
= green_mask
;
325 img
->blue_mask
= blue_mask
;
327 dock_image
= RCreateImageFromXImage(scr
->rcontext
, img
, NULL
);
333 RCombineAreaWithOpaqueness(back
, dock_image
, 0, 0,
334 wPreferences
.icon_size
, n
, 0, j
, 30 * 256 / 100);
335 RReleaseImage(dock_image
);
339 RConvertImage(scr
->rcontext
, back
, &pixmap
);
346 Pixmap
MakeGhostIcon(WScreen
* scr
, Drawable drawable
)
355 back
= RCreateImageFromDrawable(scr
->rcontext
, drawable
, None
);
364 RClearImage(back
, &color
);
365 RConvertImage(scr
->rcontext
, back
, &pixmap
);
372 #ifdef WINDOW_BIRTH_ZOOM
373 void DoWindowBirth(WWindow
* wwin
)
375 int width
= wwin
->frame
->core
->width
;
376 int height
= wwin
->frame
->core
->height
;
377 int w
= WMIN(width
, 20);
378 int h
= WMIN(height
, 20);
382 time_t time0
= time(NULL
);
384 dw
= (width
- w
) / WINDOW_BIRTH_STEPS
;
385 dh
= (height
- h
) / WINDOW_BIRTH_STEPS
;
387 x
= wwin
->frame_x
+ (width
- w
) / 2;
388 y
= wwin
->frame_y
+ (height
- h
) / 2;
390 XMoveResizeWindow(dpy
, wwin
->frame
->core
->window
, x
, y
, w
, h
);
392 XMapWindow(dpy
, wwin
->frame
->core
->window
);
395 for (i
= 0; i
< WINDOW_BIRTH_STEPS
; i
++) {
396 x
-= dw
/ 2 + dw
% 2;
397 y
-= dh
/ 2 + dh
% 2;
400 XMoveResizeWindow(dpy
, wwin
->frame
->core
->window
, x
, y
, w
, h
);
403 if (time(NULL
) - time0
> MAX_ANIMATION_TIME
)
407 XMoveResizeWindow(dpy
, wwin
->frame
->core
->window
, wwin
->frame_x
, wwin
->frame_y
, width
, height
);
411 #ifdef WINDOW_BIRTH_ZOOM2
412 extern void animateResize();
414 void DoWindowBirth(WWindow
* wwin
)
418 int center_x
, center_y
;
419 int width
= wwin
->frame
->core
->width
;
420 int height
= wwin
->frame
->core
->height
;
421 int w
= WMIN(width
, 20);
422 int h
= WMIN(height
, 20);
423 WScreen
*scr
= wwin
->screen_ptr
;
425 center_x
= wwin
->frame_x
+ (width
- w
) / 2;
426 center_y
= wwin
->frame_y
+ (height
- h
) / 2;
428 animateResize(scr
, center_x
, center_y
, 1, 1, wwin
->frame_x
, wwin
->frame_y
, width
, height
, 0);
431 void DoWindowBirth(WWindow
* wwin
)
439 static WMPixmap
*data
[12];
441 static Bool
loadData(WScreen
* scr
)
448 f
= fopen(PKGDATADIR
"/xtree.dat", "rb");
452 image
= RCreateImage(50, 50, False
);
458 for (i
= 0; i
< 12; i
++) {
459 if (fread(image
->data
, 50 * 50 * 3, 1, f
) != 1) {
462 if (!RConvertImage(scr
->rcontext
, image
, &(d
[i
]))) {
466 RReleaseImage(image
);
470 for (i
= 0; i
< 12; i
++) {
471 data
[i
] = WMCreatePixmapFromXPixmaps(scr
->wmscreen
, d
[i
], None
, 50, 50, scr
->w_depth
);
477 RReleaseImage(image
);
482 XFreePixmap(dpy
, d
[i
]);
488 WMPixmap
*DoXThing(WWindow
* wwin
)
490 static int order
= 0;
494 return data
[order
% 12];
497 Bool
InitXThing(WScreen
* scr
)
508 if ((l
->tm_mon
!= 11 || l
->tm_mday
< 24 || l
->tm_mday
> 26)) {
520 #endif /* SILLYNESS */
522 #ifdef GHOST_WINDOW_MOVE
538 /* the combined image */
544 _GhostWindowData
*InitGhostWindowMove(WWindow
* wwin
)
546 _GhostWindowData
*gdata
;
547 WScreen
*scr
= wwin
->screen_ptr
;
552 gdata
= wmalloc(sizeof(_GhostWindowData
));
554 gdata
->width
= wwin
->frame
->core
->width
;
555 gdata
->height
= wwin
->frame
->core
->height
;
557 gdata
->iniX
= wwin
->frame_x
;
558 gdata
->iniY
= wwin
->frame_y
;
560 gdata
->boxX
= wwin
->frame_x
;
561 gdata
->boxY
= wwin
->frame_y
;
564 XCreateSimpleWindow(dpy
, scr
->root_win
, wwin
->frame_x
, wwin
->frame_y
,
565 gdata
->width
, gdata
->height
, 0, 0, 0);
567 gdata
->winImage
= RGetXImage(scr
->rcontext
, wwin
->frame
->core
->window
, 0, 0, gdata
->width
, gdata
->height
);
569 gdata
->backImage
= RCreateXImage(scr
->rcontext
, scr
->w_depth
, gdata
->width
, gdata
->height
);
571 memcpy(gdata
->backImage
->image
->data
, gdata
->winImage
->image
->data
,
572 gdata
->winImage
->image
->bytes_per_line
* gdata
->height
);
574 gdata
->image
= RCreateXImage(scr
->rcontext
, scr
->w_depth
, gdata
->width
, gdata
->height
);
576 ptr
= (unsigned short *)gdata
->winImage
->image
->data
;
578 mask
= 0x7b00 | 0x3d0 | 0x1e;
580 for (i
= 0; i
< gdata
->winImage
->image
->bytes_per_line
* gdata
->height
; i
++, ptr
++) {
588 static void mergeGhostWindow(_GhostWindowData
* gdata
)
590 register unsigned short *ptrw
, *ptrb
, *ptr
;
594 ptr
= (unsigned short *)gdata
->image
->image
->data
;
595 ptrw
= (unsigned short *)gdata
->winImage
->image
->data
;
596 ptrb
= (unsigned short *)gdata
->backImage
->image
->data
;
598 count
= gdata
->winImage
->image
->bytes_per_line
* gdata
->height
;
601 *ptr
= (*ptrw
+ *ptrb
) >> 1;
609 void UpdateGhostWindowMove(void *data
, int x
, int y
)
611 _GhostWindowData
*gdata
= (_GhostWindowData
*) data
;
612 WScreen
*scr
= gdata
->scr
;
614 /* no intersection of new background with current */
615 if (x
+ gdata
->width
<= gdata
->boxX
616 || x
>= gdata
->boxX
+ gdata
->width
617 || y
+ gdata
->height
<= gdata
->boxY
|| y
>= gdata
->boxY
+ gdata
->height
) {
620 RDestroyXImage(gdata
->backImage
);
622 gdata
->backImage
= RGetXImage(scr
->rcontext
, scr
->root_win
, x
, y
, gdata
->width
, gdata
->height
);
624 ptr
= (unsigned short *)gdata
->backImage
->image
->data
;
626 mask
= 0x7b00 | 0x3d0 | 0x1e;
628 for (i
= 0; i
< gdata
->winImage
->image
->bytes_per_line
* gdata
->height
; i
++, ptr
++) {
636 unsigned char *backP
= gdata
->backImage
->image
->data
;
637 unsigned char *winP
= gdata
->winImage
->image
->data
;
638 int backLineLen
= gdata
->backImage
->image
->bytes_per_line
;
639 int winLineLen
= gdata
->winImage
->image
->bytes_per_line
;
641 /* 1st move the area of the current backImage that overlaps
642 * the new backImage to it's new position */
644 if (x
< gdata
->boxX
) {
645 vx
= x
+ gdata
->width
;
646 vw
= gdata
->width
- vx
;
647 } else if (x
> gdata
->boxX
) {
648 vw
= gdata
->boxX
+ gdata
->width
- x
;
649 vx
= gdata
->boxX
- vw
;
655 if (y
< gdata
->boxY
) {
656 vy
= y
+ gdata
->height
;
657 vh
= gdata
->height
- vy
;
658 } else if (y
> gdata
->boxY
) {
659 vh
= gdata
->boxY
+ gdata
->height
- y
;
660 vy
= gdata
->boxY
- vh
;
666 if (y
< gdata
->boxY
) {
667 int dy
= vy
- gdata
->boxY
;
669 if (x
< gdata
->boxX
) {
670 for (i
= vh
- 1; i
>= 0; i
--) {
671 memmove(&backP
[(i
+ dy
) * backLineLen
+ 2 * vx
],
672 &backP
[i
* backLineLen
], 2 * vw
);
674 } else { /* if (x > gdata->boxX) */
676 for (i
= vh
- 1; i
>= 0; i
--) {
677 memmove(&backP
[(i
+ dy
) * backLineLen
],
678 &backP
[i
* backLineLen
+ 2 * vx
], 2 * vw
);
681 } else { /*if (y > gdata->boxY) */
683 int dy
= gdata
->boxY
- vy
;
685 if (x
< gdata
->boxX
) {
686 for (i
= 0; i
< vh
- 1; i
++) {
687 memmove(&backP
[i
* backLineLen
+ 2 * vx
],
688 &backP
[(i
+ dy
) * backLineLen
], 2 * vw
);
690 } else { /*if (x > gdata->boxX) */
692 for (i
= 0; i
< vh
- 1; i
++) {
693 memmove(&backP
[i
* backLineLen
],
694 &backP
[(i
+ dy
) * backLineLen
+ 2 * vx
], 2 * vw
);
699 /* 2nd grab the background image from the screen and copy to the
700 * buffer. also maskout the lsb of rgb in each pixel of grabbed data */
702 if (y
< gdata
->boxY
) {
704 vh
= gdata
->boxY
- vy
;
707 hh
= gdata
->height
- vh
;
708 } else if (y
> gdata
->boxY
) {
709 vy
= gdata
->boxY
+ gdata
->height
;
710 vh
= vy
- (y
+ gdata
->height
);
713 hh
= y
- gdata
->boxY
;
721 if (x
< gdata
->boxX
) {
723 hw
= gdata
->boxX
- hx
;
724 } else if (x
> gdata
->boxX
) {
725 hx
= gdata
->boxX
+ gdata
->width
;
726 hw
= hx
- (x
+ gdata
->width
);
734 /* 1st the top/bottom part */
736 /* 2nd the left/right part */
739 mergeGhostWindow(gdata
);
742 #endif /* GHOST_WINDOW_MOVE */