1 /* Skippy - Seduces Kids Into Perversion
3 * Copyright (C) 2004 Hyriand <hyriand@thegraveyard.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 static int DIE_NOW = 0;
30 gettimeofday (&tp, 0);
31 return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
35 update_clients(MainWin *mw, dlist *clients, Bool *touched)
39 stack = dlist_first(wm_get_stack(mw->dpy));
40 iter = clients = dlist_first(clients);
45 /* Terminate clients that are no longer managed */
48 ClientWin *cw = (ClientWin *)iter->data;
49 if(! dlist_find_data(stack, (void *)cw->client.window))
51 dlist *tmp = iter->next;
52 clientwin_destroy((ClientWin *)iter->data, True);
53 clients = dlist_remove(iter);
64 for(iter = dlist_first(stack); iter; iter = iter->next)
66 ClientWin *cw = (ClientWin*)dlist_find(clients, clientwin_cmp_func, iter->data);
67 if(! cw && (Window)iter->data != mw->window)
69 cw = clientwin_create(mw, (Window)iter->data);
72 clients = dlist_add(clients, cw);
85 do_layout(MainWin *mw, dlist *clients, Window focus, Window leader)
87 CARD32 desktop = wm_get_current_desktop(mw->dpy);
88 unsigned int width, height;
93 /* Update the client table, pick the ones we want and sort them */
94 clients = update_clients(mw, clients, 0);
99 tmp = dlist_first(dlist_find_all(clients, (dlist_match_func)clientwin_validate_func, &desktop));
102 mw->cod = dlist_first(dlist_find_all(tmp, clientwin_check_group_leader_func, (void*)&leader));
110 dlist_sort(mw->cod, clientwin_sort_func, 0);
112 /* Move the mini windows around */
113 layout_run(mw, mw->cod, &width, &height);
114 factor = (float)(mw->width - 100) / width;
115 if(factor * height > mw->height - 100)
116 factor = (float)(mw->height - 100) / height;
118 xoff = (mw->width - (float)width * factor) / 2;
119 yoff = (mw->height - (float)height * factor) / 2;
120 mainwin_transform(mw, factor);
121 for(iter = mw->cod; iter; iter = iter->next)
122 clientwin_move((ClientWin*)iter->data, factor, xoff, yoff);
124 /* Get the currently focused window and select which mini-window to focus */
125 iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)focus);
128 mw->focus = (ClientWin*)iter->data;
129 mw->focus->focused = 1;
131 /* Map the client windows */
132 for(iter = mw->cod; iter; iter = iter->next)
133 clientwin_map((ClientWin*)iter->data);
134 XWarpPointer(mw->dpy, None, mw->focus->mini.window, 0, 0, 0, 0, mw->focus->mini.width / 2, mw->focus->mini.height / 2);
140 skippy_run(MainWin *mw, dlist *clients, Window focus, Window leader, Bool all_xin)
144 Bool refocus = False, refroot = False ;
146 XWindowAttributes rootattr;
148 /* Update the main window's geometry (and Xinerama info if applicable) */
153 #else /* ! XINERAMA */
155 #endif /* XINERAMA */
157 /* Map the main window and run our event loop */
164 XGetWindowAttributes(mw->dpy, mw->root, &rootattr);
165 if(mw->width != rootattr.width)
167 /*printf("rotated\n");*/
168 mw->width = rootattr.width;
169 mw->height = rootattr.height;
170 mainwin_update_background(mw);
173 clients = do_layout(mw, clients, focus, leader);
180 /* Map the main window and run our event loop */
184 last_rendered = time_in_millis();
186 int i, j, now, timeout, mh;
187 int move_x = -1, move_y = -1;
192 r_fd.fd = ConnectionNumber(mw->dpy);
193 r_fd.events = POLLIN;
194 if(mw->poll_time > 0)
195 timeout = MAX(0, mw->poll_time + last_rendered - time_in_millis());
198 i = poll(&r_fd, 1, timeout);
200 now = time_in_millis();
201 if(now >= last_rendered + mw->poll_time)
203 REDUCE(if( ((ClientWin*)iter->data)->damaged ) clientwin_repair(iter->data), mw->cod);
207 i = XPending(mw->dpy);
208 for(j = 0; j < i; ++j)
210 XNextEvent(mw->dpy, &ev);
211 if (ev.type == MotionNotify)
213 move_x = ev.xmotion.x_root;
214 move_y = ev.xmotion.y_root;
216 else if(ev.type == DestroyNotify || ev.type == UnmapNotify) {
217 dlist *iter = dlist_find(clients, clientwin_cmp_func, (void *)ev.xany.window);
220 ClientWin *cw = (ClientWin *)iter->data;
221 clients = dlist_first(dlist_remove(iter));
222 iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)ev.xany.window);
224 mw->cod = dlist_first(dlist_remove(iter));
225 clientwin_destroy(cw, True);
233 else if (mw->poll_time >= 0 && ev.type == mw->damage_event_base + XDamageNotify)
235 XDamageNotifyEvent *d_ev = (XDamageNotifyEvent *)&ev;
236 dlist *iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)d_ev->drawable);
239 if(mw->poll_time == 0)
240 clientwin_repair((ClientWin *)iter->data);
242 ((ClientWin *)iter->data)->damaged = True;
246 else if(ev.type == KeyRelease && (ev.xkey.keycode == mw->key_f6 || ev.xkey.keycode == mw->key_escape))
252 else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_f7)
259 else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_q)
265 else if(ev.type == KeyPress && ev.xkey.keycode == mw->key_f5 )
271 else if(ev.xany.window == mw->window)
272 mh = mainwin_handle(mw, &ev);
273 if(mh == 0 || mh == 1 || mh == 2){
279 /* else if(ev.type == PropertyNotify)
281 if(ev.xproperty.atom == ESETROOT_PMAP_ID || ev.xproperty.atom == _XROOTPMAP_ID)
283 mainwin_update_background(mw);
284 REDUCE(clientwin_render((ClientWin *)iter->data), mw->cod);
288 else if(mw->tooltip && ev.xany.window == mw->tooltip->window)
289 tooltip_handle(mw->tooltip, &ev);
293 for(iter = mw->cod; iter; iter = iter->next)
295 ClientWin *cw = (ClientWin *)iter->data;
296 if(cw->mini.window == ev.xany.window)
298 die = clientwin_handle(cw, &ev);
309 if(mw->tooltip && move_x != -1)
310 tooltip_move(mw->tooltip, move_x + 20, move_y + 20);
314 /* Unmap the main window and clean up */
318 REDUCE(clientwin_unmap((ClientWin*)iter->data), mw->cod);
326 XSetInputFocus(mw->dpy, focus, RevertToPointerRoot, CurrentTime);
329 client_msg(mw->dpy, DefaultRootWindow(mw->dpy), "_NET_SHOWING_DESKTOP",
339 dlist *clients = 0, *config = 0;
340 Display *dpy = XOpenDisplay(NULL);
344 const char *tmp, *homedir;
346 Bool invertShift = False;
347 const char *img_l_file, *img_p_file;
348 Window focused = None;
352 fprintf(stderr, "FATAL: Couldn't connect to display.\n");
358 if(! wm_check(dpy)) {
359 fprintf(stderr, "FATAL: WM not NETWM or GNOME WM Spec compliant.\n");
363 homedir = getenv("HOME");
365 snprintf(cfgpath, 8191, "%s/%s", homedir, ".skippy-xd.rc");
366 config = config_load(cfgpath);
369 fprintf(stderr, "WARNING: $HOME not set, not loading config.\n");
371 wm_use_netwm_fullscreen(strcasecmp("true", config_get(config, "general", "useNETWMFullscreen", "true")) == 0);
372 wm_ignore_skip_taskbar(strcasecmp("true", config_get(config, "general", "ignoreSkipTaskbar", "false")) == 0);
374 XGetInputFocus(dpy, &focused, &revert_to);
376 mw = mainwin_create(dpy, config);
379 fprintf(stderr, "FATAL: Couldn't create main window.\n");
381 XCloseDisplay(mw->dpy);
385 client_msg(dpy, focused, "_NET_ACTIVE_WINDOW", 0, 0, 0, 0, 0);
386 XSetInputFocus(dpy, focused, RevertToParent, CurrentTime);
388 f7prog = config_get(config, "maemo", "f7prog", "/usr/bin/osso-xterm &");
389 mw->gquality = atoi(config_get(config, "maemo", "gQuality", "0"));
390 printf("Filter: %d\n", mw->gquality);
392 img_l_file = config_get(config, "maemo", "imgLandscape", "/usr/share/skippy-xd/skippy-bg-l.jpg");
393 printf("ImgL: %s\n", img_l_file);
394 img_p_file = config_get(config, "maemo", "imgPortrait", "/usr/share/skippy-xd/skippy-bg-p.jpg");
395 printf("ImgP: %s\n", img_p_file);
397 mw->img_l = imlib_load_image(img_l_file);
398 mw->img_p = imlib_load_image(img_p_file);
400 invertShift = strcasecmp("true", config_get(config, "xinerama", "showAll", "false")) == 0;
402 tmp = config_get(config, "general", "keysym", "F11");
403 keysym = XStringToKeysym(tmp);
404 if(keysym == NoSymbol)
406 fprintf(stderr, "FATAL: Couldn't look up keysym for '%s', bailing out.\n", tmp);
408 XCloseDisplay(mw->dpy);
412 /* XSelectInput(mw->dpy, mw->root, ButtonReleaseMask | ButtonPressMask | PropertyChangeMask);*/
415 /* XSelectInput(mw->dpy, mw->root, PropertyChangeMask);*/
416 XSelectInput(mw->dpy, mw->window, ButtonReleaseMask | ButtonPressMask );
418 keycode = XKeysymToKeycode(mw->dpy, keysym);
419 XGrabKey(mw->dpy, keycode, AnyModifier, mw->root, False, GrabModeAsync, GrabModeAsync);
423 XNextEvent(mw->dpy, &ev);
424 /*if(ev.type == PropertyNotify && (ev.xproperty.atom == ESETROOT_PMAP_ID || ev.xproperty.atom == _XROOTPMAP_ID))
425 mainwin_update_background(mw);
426 else */if(ev.type == KeyPress && ev.xkey.keycode == keycode)
428 Window leader = None, focused = wm_get_focused(mw->dpy);
429 Bool shifted = (ev.xkey.state & ShiftMask) ? ! invertShift : invertShift;
431 if(ev.xkey.state & Mod1Mask)
434 leader = wm_get_group_leader(mw->dpy, focused);
438 clients = skippy_run(mw, clients, focused, leader, shifted);
442 dlist_free_with_func(clients, (dlist_free_func)clientwin_destroy);