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