#include "GnomeScreensaver.h" static gboolean expose (GtkWidget *da, GdkEventExpose *event, GnomeScreensaver *gs) { return gs->exposeCB(da, event); } static gboolean configure (GtkWidget *da, GdkEventConfigure *event, GnomeScreensaver *gs) { return gs->configureCB(da, event); } static gboolean update (void *gs) { return ((GnomeScreensaver *)gs)->updateCB(); } GnomeScreensaver::GnomeScreensaver(int *argc, char ***argv, bool (*configure_callback)(GnomeScreensaver &, int, int), bool (*expose_callback)(GnomeScreensaver &), bool (*update_callback)(GnomeScreensaver &), int32_t interval_msec) : m_configure_callback(configure_callback), m_expose_callback(expose_callback), m_update_callback(update_callback) { gchar *geometry = NULL; GOptionEntry options[] = { {"geometry", 0, 0, G_OPTION_ARG_STRING, &geometry, N_("The initial size and position of window"), N_("WIDTHxHEIGHT+X+Y")}, {NULL} }; GtkWidget *window; GdkGLConfig *glconfig; GtkStateType state; GError *error = NULL; gtk_init_with_args (argc, argv, _(""), NULL, NULL, &error); gtk_gl_init(argc, argv); if (error != NULL) { g_printerr (_("%s. See --help for usage information.\n"), _(error->message)); g_error_free (error); } window = gs_theme_window_new (); g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (gtk_main_quit), NULL); m_drawing_area = gtk_drawing_area_new (); glconfig = gdk_gl_config_new_by_mode( (GdkGLConfigMode) ( GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE ) ); if (!glconfig) { g_assert_not_reached(); } if (!gtk_widget_set_gl_capability(m_drawing_area, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE)) { g_assert_not_reached(); } g_signal_connect(m_drawing_area, "configure-event", G_CALLBACK(configure), this); g_signal_connect(m_drawing_area, "expose-event", G_CALLBACK(expose), this); gtk_widget_show (m_drawing_area); gtk_container_add (GTK_CONTAINER (window), m_drawing_area); if ((geometry == NULL) || !gtk_window_parse_geometry (GTK_WINDOW (window), geometry)) { gtk_window_set_default_size (GTK_WINDOW (window), 800, 600); } gtk_widget_show (window); gtk_timeout_add(interval_msec, update, this); struct timeval tv; gettimeofday(&tv, NULL); m_start_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000; } uint32_t GnomeScreensaver::getTicks() { struct timeval tv; gettimeofday(&tv, NULL); uint64_t msec = tv.tv_sec * 1000 + tv.tv_usec / 1000; return msec - m_start_msec; } gboolean GnomeScreensaver::exposeCB(GtkWidget *da, GdkEventExpose *event) { GdkGLContext *glcontext = gtk_widget_get_gl_context(da); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(da); if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) { g_assert_not_reached(); } gboolean rc = m_expose_callback(*this); if (gdk_gl_drawable_is_double_buffered(gldrawable)) gdk_gl_drawable_swap_buffers(gldrawable); else glFlush(); gdk_gl_drawable_gl_end(gldrawable); return rc; } gboolean GnomeScreensaver::configureCB(GtkWidget *da, GdkEventConfigure *event) { GdkGLContext *glcontext = gtk_widget_get_gl_context(da); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(da); if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) { g_assert_not_reached(); } gboolean rc = m_configure_callback(*this, da->allocation.width, da->allocation.height); gdk_gl_drawable_gl_end(gldrawable); return rc; } gboolean GnomeScreensaver::updateCB() { gboolean rc = m_update_callback(*this); if (rc) { gtk_widget_queue_draw(m_drawing_area); } return rc; }