1 /*
2 * dockapp.c - dockapp part
3 *
4 * Copyright (C) 2003 Draghicioiu Mihai <misuceldestept@go.ro>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <signal.h>
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 #include <X11/xpm.h>
27 #include <X11/extensions/shape.h>
28 #include <X11/cursorfont.h>
29
30 #include "wmmemfree.h"
31 #include "options.h"
32 #include "draw.h"
33
34 #include "xpm/bg.xpm"
35 #include "xpm/on.xpm"
36 #include "xpm/off.xpm"
37 #include "xpm/numbers.xpm"
38 #include "xpm/panel.xpm"
39
40 #define WINDOW_WIDTH 64
41 #define WINDOW_HEIGHT 64
42
43 Display *display;
44 int screen;
45 Window iconwindow, window, mapwindow;
46 Colormap colormap;
47 GC gc;
48 Pixmap background, backgroundmask, on, off, numbers, buffer, panel;
49 Atom wm_delete_window;
50 Atom _motif_wm_hints;
51 int moving, oldx, oldy;
52 int screenwidth, screenheight;
53 Cursor fleur;
54
free_stuff()55 void free_stuff()
56 {
57 XUnmapWindow(display, mapwindow);
58 XFreeGC(display, gc);
59 XDestroyWindow(display, iconwindow);
60 XDestroyWindow(display, window);
61 XFreePixmap(display, buffer);
62 XFreePixmap(display, numbers);
63 XFreePixmap(display, off);
64 XFreePixmap(display, on);
65 XFreePixmap(display, backgroundmask);
66 XFreePixmap(display, background);
67 XCloseDisplay(display);
68 }
69
handle_signal(int sig)70 void handle_signal(int sig)
71 {
72 switch(sig)
73 {
74 case SIGINT:
75 fprintf(stderr, "Interrupt received\n");
76 break;
77 case SIGQUIT:
78 fprintf(stderr, "Quit signal received\n");
79 break;
80 case SIGTERM:
81 fprintf(stderr, "Terminate signal received\n");
82 default:
83 fprintf(stderr, "Got signal %d\n", sig);
84 }
85 stop_timer();
86 free_stuff();
87 exit(0);
88 }
89
make_window()90 void make_window()
91 {
92 Window rootwindow;
93 XpmAttributes xpmattributes;
94 XSetWindowAttributes windowattributes;
95 int shapeevent, shapeerror;
96 XWMHints *wmhints;
97 XClassHint *classhint;
98 XSizeHints *sizehints;
99 XGCValues gcvalues;
100 unsigned int depth;
101 struct
102 {
103 long flags;
104 long functions;
105 long decorations;
106 long input_mode;
107 long unknown;
108 } mwmhints;
109
110
111 display = XOpenDisplay(opt_display);
112 if(!display)
113 {
114 fprintf(stderr, "Could not open display %s\n", opt_display);
115 exit(1);
116 }
117 screen = DefaultScreen(display);
118 screenwidth = DisplayWidth(display, screen);
119 screenheight = DisplayHeight(display, screen);
120 rootwindow = RootWindow(display, screen);
121 colormap = DefaultColormap(display, screen);
122 depth = DefaultDepth(display, screen);
123 xpmattributes.valuemask = XpmColormap | XpmCloseness;
124 xpmattributes.colormap = colormap;
125 xpmattributes.closeness = 40000;
126 XpmCreatePixmapFromData(display, rootwindow, bg_xpm,
127 &background, &backgroundmask, &xpmattributes);
128 XpmCreatePixmapFromData(display, rootwindow, on_xpm,
129 &on, None, &xpmattributes);
130 XpmCreatePixmapFromData(display, rootwindow, off_xpm,
131 &off, None, &xpmattributes);
132 XpmCreatePixmapFromData(display, rootwindow, numbers_xpm,
133 &numbers, None, &xpmattributes);
134 buffer = XCreatePixmap(display, rootwindow,
135 WINDOW_WIDTH, WINDOW_HEIGHT, depth);
136 windowattributes.background_pixmap = background;
137 windowattributes.event_mask = ExposureMask |
138 ButtonPressMask |
139 ButtonReleaseMask |
140 PointerMotionMask |
141 PropertyChangeMask;
142 windowattributes.colormap = colormap;
143 window = XCreateWindow(display, rootwindow,
144 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0,
145 CopyFromParent,
146 InputOutput,
147 CopyFromParent,
148 CWBackPixmap | CWEventMask | CWColormap,
149 &windowattributes);
150 iconwindow = XCreateWindow(display, rootwindow,
151 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0,
152 CopyFromParent,
153 InputOutput,
154 CopyFromParent,
155 CWBackPixmap | CWEventMask,
156 &windowattributes);
157 fleur = XCreateFontCursor(display, XC_fleur);
158 if(XShapeQueryExtension(display, &shapeevent, &shapeerror) && opt_shape)
159 {
160 XShapeCombineMask(display, window, ShapeBounding,
161 0, 0, backgroundmask, ShapeSet);
162 XShapeCombineMask(display, iconwindow, ShapeBounding,
163 0, 0, backgroundmask, ShapeSet);
164 }
165 else
166 {
167 XpmCreatePixmapFromData(display, rootwindow, panel_xpm,
168 &panel, None, &xpmattributes);
169 gcvalues.function = GXcopy;
170 gcvalues.graphics_exposures = False;
171 gcvalues.clip_mask = backgroundmask;
172 gcvalues.clip_x_origin = 0;
173 gcvalues.clip_y_origin = 0;
174 gc = XCreateGC(display, rootwindow,
175 GCFunction |
176 GCGraphicsExposures |
177 GCClipMask |
178 GCClipXOrigin |
179 GCClipYOrigin,
180 &gcvalues);
181 XCopyArea(display, background, panel, gc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
182 gcvalues.clip_mask = None;
183 XChangeGC(display, gc, GCClipMask, &gcvalues);
184 XCopyArea(display, panel, background, gc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
185 XFreeGC(display, gc);
186 XFreePixmap(display, panel);
187 }
188
189 mapwindow = opt_window ? iconwindow : window;
190 wmhints = XAllocWMHints();
191 wmhints -> flags = InputHint | WindowGroupHint | IconWindowHint | StateHint;
192 wmhints -> input = True;
193 wmhints -> window_group = window;
194 wmhints -> icon_window = iconwindow;
195 wmhints -> initial_state = WithdrawnState;
196 XSetWMHints(display, window, wmhints);
197 XFree(wmhints);
198
199 classhint = XAllocClassHint();
200 classhint -> res_name = OPT_CLASS_NAME;
201 classhint -> res_class = OPT_CLASS_CLASS;
202 XSetClassHint(display, mapwindow, classhint);
203 XFree(classhint);
204
205 sizehints = XAllocSizeHints();
206 sizehints -> flags = USSize | PSize | PMinSize | PMaxSize | PBaseSize;
207 sizehints -> width = WINDOW_WIDTH;
208 sizehints -> height = WINDOW_HEIGHT;
209 sizehints -> min_width = WINDOW_WIDTH;
210 sizehints -> min_height = WINDOW_HEIGHT;
211 sizehints -> max_width = WINDOW_WIDTH;
212 sizehints -> max_height = WINDOW_HEIGHT;
213 sizehints -> base_width = WINDOW_WIDTH;
214 sizehints -> base_height = WINDOW_HEIGHT;
215 XSetWMNormalHints(display, mapwindow, sizehints);
216 XFree(sizehints);
217
218 XStoreName(display, window, OPT_WINDOW_NAME);
219 XStoreName(display, iconwindow, OPT_WINDOW_NAME); /* For other wms */
220
221 gcvalues.graphics_exposures = False;
222 gcvalues.function = GXcopy;
223 gc = XCreateGC(display, rootwindow,
224 GCGraphicsExposures | GCFunction,
225 &gcvalues);
226 XCopyArea(display, background, buffer, gc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
227 XSetCommand(display, window, argv, argc);
228 wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", 0);
229 XSetWMProtocols(display, mapwindow, &wm_delete_window, 1);
230 if(opt_window)
231 {
232 _motif_wm_hints = XInternAtom(display, "_MOTIF_WM_HINTS", 0);
233 mwmhints.flags = 2;
234 mwmhints.functions = 0x71; /* WTF IS THIS ? */
235 mwmhints.decorations = 0;
236 XChangeProperty(display, mapwindow,
237 _motif_wm_hints, _motif_wm_hints,
238 32, PropModeReplace, (unsigned char *)&mwmhints, 5);
239 }
240 XMapWindow(display, mapwindow);
241 signal(SIGINT, handle_signal);
242 signal(SIGQUIT, handle_signal);
243 signal(SIGTERM, handle_signal);
244 }
245
update_window()246 void update_window()
247 {
248 XCopyArea(display, buffer, iconwindow, gc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
249 XCopyArea(display, buffer, window, gc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
250 }
251
process_events()252 void process_events()
253 {
254 XEvent event;
255 int winx, winy;
256
257 XNextEvent(display, &event);
258 switch(event.type)
259 {
260 case Expose:
261 update_window();
262 break;
263 case ButtonPress:
264 if(opt_window && (event.xbutton.button == 1))
265 {
266 XDefineCursor(display, mapwindow, fleur);
267 moving = 1;
268 oldx = event.xbutton.x;
269 oldy = event.xbutton.y;
270 }
271 break;
272 case MotionNotify:
273 winx = event.xmotion.x_root - oldx;
274 winy = event.xmotion.y_root - oldy;
275 if(winx < 0) winx = 0;
276 if(winy < 0) winy = 0;
277 if(winx > (screenwidth - WINDOW_WIDTH))
278 winx = screenwidth - WINDOW_WIDTH;
279 if(winy > (screenheight - WINDOW_HEIGHT))
280 winy = screenheight - WINDOW_HEIGHT;
281 if(moving)
282 XMoveWindow(display, mapwindow, winx, winy);
283 break;
284 case ButtonRelease:
285 if(opt_window)
286 {
287 moving = 0;
288 XUndefineCursor(display, mapwindow);
289 }
290 break;
291 case ClientMessage:
292 if(event.xclient.data.l[0] == wm_delete_window)
293 exitloop = 1;
294 break;
295 }
296 }
297