int main(int argc, char *argv[]) { std::ostream& stream = std::cout; const char *parm = (argc > 1 ? argv[1] : 0); stream << "welcome to goat attack "; stream << GameVersion; stream << "...\n" << std::endl; init_hpet(); start_net(); try { Configuration config(UserDirectory, ConfigFilename); #ifdef DEDICATED_SERVER SubsystemNull subsystem(stream, "Goat Attack"); #else SubsystemSDL subsystem(stream, "Goat Attack", config.get_bool("shading_pipeline")); #endif #ifdef __APPLE__ CFBundleRef mainBundle = CFBundleGetMainBundle(); CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); char path[PATH_MAX]; if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX)) { throw Exception("Cannot get bundle path"); } CFRelease(resourcesURL); std::string data_directory(path); Resources resources(subsystem, data_directory); #else # ifdef DEDICATED_SERVER const char *data_directory = STRINGIZE_VALUE_OF(DATA_DIRECTORY); # else const char *data_directory = (parm ? parm : STRINGIZE_VALUE_OF(DATA_DIRECTORY)); # endif Resources resources(subsystem, data_directory); #endif Game game(resources, subsystem, config); game.run(parm ? parm : ""); } catch (const ResourcesMissingException& e) { stream << std::endl << "ERROR: "; #ifdef DEDICATED_SERVER stream << e.what() << std::endl; #else stream << e.what() << std::endl; stream << "Ensure that you can add a data folder as parameter." << std::endl; stream << "Example: " << argv[0] << " path/to/your/data/folder" << std::endl; #endif } catch (const Exception& e) { stream << std::endl << "ERROR: "; stream << e.what() << std::endl; } stop_net(); stream << "\nbye bye... :)" << std::endl; return 0; }
void cleanup_systray() { stop_net(); systray_enabled = 0; systray_max_icon_size = 0; systray_monitor = 0; systray.area.on_screen = FALSE; free_area(&systray.area); if (render_background) { XFreePixmap(server.display, render_background); render_background = 0; } }
void start_net() { if (systray_profile) fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__); if (net_sel_win) { // protocol already started if (!systray_enabled) stop_net(); return; } else { if (!systray_enabled) return; } Window win = XGetSelectionOwner(server.display, server.atom._NET_SYSTEM_TRAY_SCREEN); // freedesktop systray specification if (win != None) { // search pid Atom _NET_WM_PID, actual_type; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char *prop = 0; int pid; _NET_WM_PID = XInternAtom(server.display, "_NET_WM_PID", True); int ret = XGetWindowProperty(server.display, win, _NET_WM_PID, 0, 1024, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); fprintf(stderr, RED "tint2 : another systray is running" RESET); if (ret == Success && prop) { pid = prop[1] * 256; pid += prop[0]; fprintf(stderr, " pid=%d", pid); } fprintf(stderr, RESET "\n"); return; } // init systray protocol net_sel_win = XCreateSimpleWindow(server.display, server.root_win, -1, -1, 1, 1, 0, 0, 0); fprintf(stderr, "systray window %ld\n", net_sel_win); // v0.3 trayer specification. tint2 always horizontal. // Vertical panel will draw the systray horizontal. long orientation = 0; XChangeProperty(server.display, net_sel_win, server.atom._NET_SYSTEM_TRAY_ORIENTATION, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&orientation, 1); if (systray.icon_size > 0) { long icon_size = systray.icon_size; XChangeProperty(server.display, net_sel_win, server.atom._NET_SYSTEM_TRAY_ICON_SIZE, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&icon_size, 1); } long padding = 0; XChangeProperty(server.display, net_sel_win, server.atom._NET_SYSTEM_TRAY_PADDING, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&padding, 1); VisualID vid; if (systray_composited) vid = XVisualIDFromVisual(server.visual32); else vid = XVisualIDFromVisual(server.visual); XChangeProperty(server.display, net_sel_win, XInternAtom(server.display, "_NET_SYSTEM_TRAY_VISUAL", False), XA_VISUALID, 32, PropModeReplace, (unsigned char *)&vid, 1); XSetSelectionOwner(server.display, server.atom._NET_SYSTEM_TRAY_SCREEN, net_sel_win, CurrentTime); if (XGetSelectionOwner(server.display, server.atom._NET_SYSTEM_TRAY_SCREEN) != net_sel_win) { stop_net(); fprintf(stderr, RED "tint2 : can't get systray manager" RESET "\n"); return; } fprintf(stderr, GREEN "tint2 : systray started" RESET "\n"); if (systray_profile) fprintf(stderr, "[%f] %s:%d\n", profiling_get_time(), __FUNCTION__, __LINE__); XClientMessageEvent ev; ev.type = ClientMessage; ev.window = server.root_win; ev.message_type = server.atom.MANAGER; ev.format = 32; ev.data.l[0] = CurrentTime; ev.data.l[1] = server.atom._NET_SYSTEM_TRAY_SCREEN; ev.data.l[2] = net_sel_win; ev.data.l[3] = 0; ev.data.l[4] = 0; XSendEvent(server.display, server.root_win, False, StructureNotifyMask, (XEvent *)&ev); }
void systray_render_icon_composited(void *t) { // we end up in this function only in real transparency mode or if systray_task_asb != 100 0 0 // we made also sure, that we always have a 32 bit visual, i.e. we can safely create 32 bit pixmaps here TrayWindow *traywin = t; if (systray_profile) fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); // wine tray icons update whenever mouse is over them, so we limit the updates to 50 ms struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); struct timespec earliest_render = add_msec_to_timespec(traywin->time_last_render, min_refresh_period); if (compare_timespecs(&earliest_render, &now) > 0) { traywin->num_fast_renders++; if (traywin->num_fast_renders > max_fast_refreshes) { traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout); if (systray_profile) fprintf(stderr, YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); return; } } else { traywin->time_last_render.tv_sec = now.tv_sec; traywin->time_last_render.tv_nsec = now.tv_nsec; traywin->num_fast_renders = 0; } if (traywin->width == 0 || traywin->height == 0) { // reschedule rendering since the geometry information has not yet been processed (can happen on slow cpu) traywin->render_timeout = add_timeout(min_refresh_period, 0, systray_render_icon_composited, traywin, &traywin->render_timeout); if (systray_profile) fprintf(stderr, YELLOW "[%f] %s:%d win = %lu (%s) delaying rendering" RESET "\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); return; } if (traywin->render_timeout) { stop_timeout(traywin->render_timeout); traywin->render_timeout = NULL; } // good systray icons support 32 bit depth, but some icons are still 24 bit. // We create a heuristic mask for these icons, i.e. we get the rgb value in the top left corner, and // mask out all pixel with the same rgb value // Very ugly hack, but somehow imlib2 is not able to get the image from the traywindow itself, // so we first render the tray window onto a pixmap, and then we tell imlib2 to use this pixmap as // drawable. If someone knows why it does not work with the traywindow itself, please tell me ;) Pixmap tmp_pmap = XCreatePixmap(server.display, traywin->win, traywin->width, traywin->height, 32); if (!tmp_pmap) { goto on_systray_error; } XRenderPictFormat *f; if (traywin->depth == 24) { f = XRenderFindStandardFormat(server.display, PictStandardRGB24); } else if (traywin->depth == 32) { f = XRenderFindStandardFormat(server.display, PictStandardARGB32); } else { fprintf(stderr, RED "Strange tray icon found with depth: %d" RESET "\n", traywin->depth); XFreePixmap(server.display, tmp_pmap); return; } XRenderPictFormat *f32 = XRenderFindVisualFormat(server.display, server.visual32); if (!f || !f32) { XFreePixmap(server.display, tmp_pmap); goto on_systray_error; } XSync(server.display, False); error = FALSE; XErrorHandler old = XSetErrorHandler(window_error_handler); // if (server.real_transparency) // Picture pict_image = XRenderCreatePicture(server.display, traywin->parent, f, 0, 0); // reverted Rev 407 because here it's breaking alls icon with systray + xcompmgr Picture pict_image = XRenderCreatePicture(server.display, traywin->win, f, 0, 0); if (!pict_image) { XFreePixmap(server.display, tmp_pmap); XSetErrorHandler(old); goto on_error; } Picture pict_drawable = XRenderCreatePicture(server.display, tmp_pmap, XRenderFindVisualFormat(server.display, server.visual32), 0, 0); if (!pict_drawable) { XRenderFreePicture(server.display, pict_image); XFreePixmap(server.display, tmp_pmap); XSetErrorHandler(old); goto on_error; } XRenderComposite(server.display, PictOpSrc, pict_image, None, pict_drawable, 0, 0, 0, 0, 0, 0, traywin->width, traywin->height); XRenderFreePicture(server.display, pict_image); XRenderFreePicture(server.display, pict_drawable); // end of the ugly hack and we can continue as before imlib_context_set_visual(server.visual32); imlib_context_set_colormap(server.colormap32); imlib_context_set_drawable(tmp_pmap); Imlib_Image image = imlib_create_image_from_drawable(0, 0, 0, traywin->width, traywin->height, 1); imlib_context_set_visual(server.visual); imlib_context_set_colormap(server.colormap); XFreePixmap(server.display, tmp_pmap); if (!image) { imlib_context_set_visual(server.visual); imlib_context_set_colormap(server.colormap); XSetErrorHandler(old); goto on_error; } else { if (traywin->image) { imlib_context_set_image(traywin->image); imlib_free_image_and_decache(); } traywin->image = image; } imlib_context_set_image(traywin->image); // if (traywin->depth == 24) // imlib_save_image("/home/thil77/test.jpg"); imlib_image_set_has_alpha(1); DATA32 *data = imlib_image_get_data(); if (traywin->depth == 24) { create_heuristic_mask(data, traywin->width, traywin->height); } if (systray.alpha != 100 || systray.brightness != 0 || systray.saturation != 0) adjust_asb(data, traywin->width, traywin->height, systray.alpha, (float)systray.saturation / 100, (float)systray.brightness / 100); imlib_image_put_back_data(data); systray_render_icon_from_image(traywin); if (traywin->damage) XDamageSubtract(server.display, traywin->damage, None, None); XSync(server.display, False); XSetErrorHandler(old); if (error) goto on_error; panel_refresh = TRUE; if (systray_profile) fprintf(stderr, "[%f] %s:%d win = %lu (%s)\n", profiling_get_time(), __FUNCTION__, __LINE__, traywin->win, traywin->name); return; on_error: fprintf(stderr, RED "systray %d: rendering error for icon %lu (%s) pid %d" RESET "\n", __LINE__, traywin->win, traywin->name, traywin->pid); return; on_systray_error: fprintf(stderr, RED "systray %d: rendering error for icon %lu (%s) pid %d. " "Disabling compositing and restarting systray..." RESET "\n", __LINE__, traywin->win, traywin->name, traywin->pid); systray_composited = 0; stop_net(); start_net(); return; }