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
24 static int DIE_NOW = 0;
31 gettimeofday (&tp, 0);
32 return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
36 update_clients(MainWin *mw, dlist *clients, Bool *touched)
40 stack = dlist_first(wm_get_stack(mw->dpy));
41 iter = clients = dlist_first(clients);
46 /* Terminate clients that are no longer managed */
49 ClientWin *cw = (ClientWin *)iter->data;
50 if(! dlist_find_data(stack, (void *)cw->client.window))
52 dlist *tmp = iter->next;
53 clientwin_destroy((ClientWin *)iter->data, True);
54 clients = dlist_remove(iter);
65 for(iter = dlist_first(stack); iter; iter = iter->next)
67 ClientWin *cw = (ClientWin*)dlist_find(clients, clientwin_cmp_func, iter->data);
68 if(! cw && (Window)iter->data != mw->window)
70 cw = clientwin_create(mw, (Window)iter->data);
73 clients = dlist_add(clients, cw);
86 do_layout(MainWin *mw, dlist *clients, Window focus, Window leader)
88 CARD32 desktop = wm_get_current_desktop(mw->dpy);
89 unsigned int width, height;
94 /* Update the client table, pick the ones we want and sort them */
95 clients = update_clients(mw, clients, 0);
100 tmp = dlist_first(dlist_find_all(clients, (dlist_match_func)clientwin_validate_func, &desktop));
103 mw->cod = dlist_first(dlist_find_all(tmp, clientwin_check_group_leader_func, (void*)&leader));
111 dlist_sort(mw->cod, clientwin_sort_func, 0);
113 /* Move the mini windows around */
114 layout_run(mw, mw->cod, &width, &height);
115 factor = (float)(mw->width - 100) / width;
116 if(factor * height > mw->height - 100)
117 factor = (float)(mw->height - 100) / height;
119 xoff = (mw->width - (float)width * factor) / 2;
120 yoff = (mw->height - (float)height * factor) / 2;
121 mainwin_transform(mw, factor);
122 for(iter = mw->cod; iter; iter = iter->next)
123 clientwin_move((ClientWin*)iter->data, factor, xoff, yoff);
125 /* Get the currently focused window and select which mini-window to focus */
126 iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)focus);
129 mw->focus = (ClientWin*)iter->data;
130 mw->focus->focused = 1;
132 /* Map the client windows */
133 for(iter = mw->cod; iter; iter = iter->next)
134 clientwin_map((ClientWin*)iter->data);
135 XWarpPointer(mw->dpy, None, mw->focus->mini.window, 0, 0, 0, 0, mw->focus->mini.width / 2, mw->focus->mini.height / 2);
141 skippy_run(MainWin *mw, dlist *clients, Window focus, Window leader, Bool all_xin)
145 Bool refocus = False, refroot = False ;
147 XWindowAttributes rootattr;
149 /* Update the main window's geometry (and Xinerama info if applicable) */
154 #else /* ! XINERAMA */
156 #endif /* XINERAMA */
158 /* Map the main window and run our event loop */
165 XGetWindowAttributes(mw->dpy, mw->root, &rootattr);
166 if(mw->width != rootattr.width)
168 /*printf("rotated\n");*/
169 mw->width = rootattr.width;
170 mw->height = rootattr.height;
171 mainwin_update_background(mw);
174 clients = do_layout(mw, clients, focus, leader);
181 /* Map the main window and run our event loop */
185 last_rendered = time_in_millis();
187 int i, j, now, timeout, mh;
188 int move_x = -1, move_y = -1;
193 r_fd.fd = ConnectionNumber(mw->dpy);
194 r_fd.events = POLLIN;
195 if(mw->poll_time > 0)
196 timeout = MAX(0, mw->poll_time + last_rendered - time_in_millis());
199 i = poll(&r_fd, 1, timeout);
201 now = time_in_millis();
202 if(now >= last_rendered + mw->poll_time)
204 REDUCE(if( ((ClientWin*)iter->data)->damaged ) clientwin_repair(iter->data), mw->cod);
208 i = XPending(mw->dpy);
209 for(j = 0; j < i; ++j)
211 XNextEvent(mw->dpy, &ev);
212 if (ev.type == MotionNotify)
214 move_x = ev.xmotion.x_root;
215 move_y = ev.xmotion.y_root;
217 else if(ev.type == DestroyNotify || ev.type == UnmapNotify) {
218 dlist *iter = dlist_find(clients, clientwin_cmp_func, (void *)ev.xany.window);
221 ClientWin *cw = (ClientWin *)iter->data;
222 clients = dlist_first(dlist_remove(iter));
223 iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)ev.xany.window);
225 mw->cod = dlist_first(dlist_remove(iter));
226 clientwin_destroy(cw, True);
234 else if (mw->poll_time >= 0 && ev.type == mw->damage_event_base + XDamageNotify)
236 XDamageNotifyEvent *d_ev = (XDamageNotifyEvent *)&ev;
237 dlist *iter = dlist_find(mw->cod, clientwin_cmp_func, (void *)d_ev->drawable);
240 if(mw->poll_time == 0)
241 clientwin_repair((ClientWin *)iter->data);
243 ((ClientWin *)iter->data)->damaged = True;
247 else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_escape)
253 else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_f6)
260 else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_f7)
267 else if(ev.type == KeyRelease && ev.xkey.keycode == mw->key_q)
273 else if(ev.type == KeyPress && ev.xkey.keycode == mw->key_f5 )
279 else if(ev.xany.window == mw->window)
280 mh = mainwin_handle(mw, &ev);
281 if(mh == 0 || mh == 1 || mh == 2){
287 /* else if(ev.type == PropertyNotify)
289 if(ev.xproperty.atom == ESETROOT_PMAP_ID || ev.xproperty.atom == _XROOTPMAP_ID)
291 mainwin_update_background(mw);
292 REDUCE(clientwin_render((ClientWin *)iter->data), mw->cod);
296 else if(mw->tooltip && ev.xany.window == mw->tooltip->window)
297 tooltip_handle(mw->tooltip, &ev);
301 for(iter = mw->cod; iter; iter = iter->next)
303 ClientWin *cw = (ClientWin *)iter->data;
304 if(cw->mini.window == ev.xany.window)
306 die = clientwin_handle(cw, &ev);
317 if(mw->tooltip && move_x != -1)
318 tooltip_move(mw->tooltip, move_x + 20, move_y + 20);
322 /* Unmap the main window and clean up */
326 REDUCE(clientwin_unmap((ClientWin*)iter->data), mw->cod);
334 XSetInputFocus(mw->dpy, focus, RevertToPointerRoot, CurrentTime);
337 client_msg(mw->dpy, DefaultRootWindow(mw->dpy), "_NET_SHOWING_DESKTOP",
347 dlist *clients = 0, *config = 0;
348 Display *dpy = XOpenDisplay(NULL);
352 const char *tmp, *homedir;
354 Bool invertShift = False;
355 const char *img_l_file, *img_p_file;
356 Window focused = None;
360 fprintf(stderr, "FATAL: Couldn't connect to display.\n");
366 if(! wm_check(dpy)) {
367 fprintf(stderr, "FATAL: WM not NETWM or GNOME WM Spec compliant.\n");
371 homedir = getenv("HOME");
373 snprintf(cfgpath, 8191, "%s/%s", homedir, ".skippy-xd.rc");
374 config = config_load(cfgpath);
377 fprintf(stderr, "WARNING: $HOME not set, not loading config.\n");
379 wm_use_netwm_fullscreen(strcasecmp("true", config_get(config, "general", "useNETWMFullscreen", "true")) == 0);
380 wm_ignore_skip_taskbar(strcasecmp("true", config_get(config, "general", "ignoreSkipTaskbar", "false")) == 0);
382 XGetInputFocus(dpy, &focused, &revert_to);
384 mw = mainwin_create(dpy, config);
387 fprintf(stderr, "FATAL: Couldn't create main window.\n");
389 XCloseDisplay(mw->dpy);
393 client_msg(dpy, focused, "_NET_ACTIVE_WINDOW", 0, 0, 0, 0, 0);
394 XSetInputFocus(dpy, focused, RevertToParent, CurrentTime);
397 f6prog = config_get(config, "maemo", "f6prog", "/usr/bin/dbus-send --system --type=method_call --dest=com.nokia.mce /com/nokia/mce/request com.nokia.mce.request.req_tklock_mode_change string:locked &");
398 f7prog = config_get(config, "maemo", "f7prog", "/usr/bin/osso-xterm &");
399 mw->gquality = atoi(config_get(config, "maemo", "gQuality", "0"));
400 printf("Filter: %d\n", mw->gquality);
402 img_l_file = config_get(config, "maemo", "imgLandscape", "/usr/share/skippy-xd/skippy-bg-l.jpg");
403 printf("ImgL: %s\n", img_l_file);
404 img_p_file = config_get(config, "maemo", "imgPortrait", "/usr/share/skippy-xd/skippy-bg-p.jpg");
405 printf("ImgP: %s\n", img_p_file);
407 mw->img_l = imlib_load_image(img_l_file);
408 mw->img_p = imlib_load_image(img_p_file);
410 invertShift = strcasecmp("true", config_get(config, "xinerama", "showAll", "false")) == 0;
412 tmp = config_get(config, "general", "keysym", "F11");
413 keysym = XStringToKeysym(tmp);
414 if(keysym == NoSymbol)
416 fprintf(stderr, "FATAL: Couldn't look up keysym for '%s', bailing out.\n", tmp);
418 XCloseDisplay(mw->dpy);
422 /* XSelectInput(mw->dpy, mw->root, ButtonReleaseMask | ButtonPressMask | PropertyChangeMask);*/
425 /* XSelectInput(mw->dpy, mw->root, PropertyChangeMask);*/
426 XSelectInput(mw->dpy, mw->window, ButtonReleaseMask | ButtonPressMask );
428 keycode = XKeysymToKeycode(mw->dpy, keysym);
429 XGrabKey(mw->dpy, keycode, AnyModifier, mw->root, False, GrabModeAsync, GrabModeAsync);
433 XNextEvent(mw->dpy, &ev);
434 /*if(ev.type == PropertyNotify && (ev.xproperty.atom == ESETROOT_PMAP_ID || ev.xproperty.atom == _XROOTPMAP_ID))
435 mainwin_update_background(mw);
436 else */if(ev.type == KeyPress && ev.xkey.keycode == keycode)
438 Window leader = None, focused = wm_get_focused(mw->dpy);
439 Bool shifted = (ev.xkey.state & ShiftMask) ? ! invertShift : invertShift;
441 if(ev.xkey.state & Mod1Mask)
444 leader = wm_get_group_leader(mw->dpy, focused);
448 clients = skippy_run(mw, clients, focused, leader, shifted);
452 dlist_free_with_func(clients, (dlist_free_func)clientwin_destroy);