From 668890821fff52b2710aac827dc8540ff2047015 Mon Sep 17 00:00:00 2001 From: Matthew Allum Date: Sun, 3 Apr 2005 16:13:08 +0000 Subject: [PATCH] Add basic toolkit infrastructure --- ChangeLog | 27 ++++ Makefile | 22 +++- cltr-core.c | 44 +++++++ cltr-core.h | 9 ++ cltr-events.c | 176 +++++++++++++++++++++++++ cltr-events.h | 18 +++ cltr-photo-grid.c | 267 ++++++++++++++++++++++++++++---------- cltr-photo-grid.h | 84 +++--------- cltr-private.h | 75 +++++++++++ cltr-texture.c | 1 + cltr-texture.h | 18 +++ cltr-widget.c | 82 ++++++++++++ cltr-widget.h | 36 ++++++ cltr-window.c | 101 +++++++++++++++ cltr-window.h | 23 ++++ cltr.c | 318 +--------------------------------------------- cltr.h | 93 +------------- 17 files changed, 860 insertions(+), 534 deletions(-) create mode 100644 cltr-core.c create mode 100644 cltr-core.h create mode 100644 cltr-events.c create mode 100644 cltr-events.h create mode 100644 cltr-private.h create mode 100644 cltr-widget.c create mode 100644 cltr-widget.h create mode 100644 cltr-window.c create mode 100644 cltr-window.h diff --git a/ChangeLog b/ChangeLog index 57178cd1a..66459f466 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2005-04-03 mallum,,, + + * Makefile: + * cltr-core.c: + * cltr-core.h: + * cltr-events.c: + * cltr-events.h: + * cltr-photo-grid.c: (cltr_photo_grid_handle_xkeyevent), + (cltr_photo_grid_handle_xevent), (cltr_photo_grid_cell_new), + (cltr_photo_grid_append_cell), (ctrl_photo_grid_cell_to_coords), + (ctrl_photo_grid_get_zoomed_coords), (cell_is_offscreen), + (cltr_photo_grid_idle_cb), (cltr_photo_grid_navigate), + (cltr_photo_grid_activate_cell), (cltr_photo_grid_populate), + (cltr_photo_grid_paint), (cltr_photo_grid_show), + (cltr_photo_grid_new): + * cltr-photo-grid.h: + * cltr-private.h: + * cltr-texture.c: + * cltr-texture.h: + * cltr-widget.c: + * cltr-widget.h: + * cltr-window.c: + * cltr-window.h: + * cltr.c: + * cltr.h: + Add very basic initial toolkit infrastructure + 2005-03-31 mallum,,, * cltr-photo-grid.c: (cltr_photo_grid_append_cell), diff --git a/Makefile b/Makefile index 3f98c0aac..2330ef5ea 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,30 @@ CFLAGS=`pkg-config --cflags pangoft2 pango glib-2.0 gthread-2.0` .c.o: $(CC) -g -Wall $(CFLAGS) $(INCS) -c $*.c -OBJS=cltr.o pixbuf.o util.o fonts.o cltr-photo-grid.o cltr-texture.o +OBJS=cltr.o pixbuf.o util.o fonts.o \ + cltr-core.o \ + cltr-texture.o \ + cltr-widget.o \ + cltr-events.o \ + cltr-window.o \ + cltr-photo-grid.o + +# cltr-photo-grid.o clutter: $(OBJS) $(CC) -g -Wall -o $@ $(OBJS) $(LIBS) -$(OBJS): pixbuf.h util.h fonts.h cltr.h cltr-photo-grid.h cltr-texture.h +$(OBJS): pixbuf.h util.h fonts.h \ + cltr.h \ + cltr-private.h \ + cltr-events.h \ + cltr-texture.h \ + cltr-widget.h \ + cltr-window.h \ + cltr-photo-grid.h + +#cltr-photo-grid.h + clean: rm -fr *.o clutter test diff --git a/cltr-core.c b/cltr-core.c new file mode 100644 index 000000000..745f6eff0 --- /dev/null +++ b/cltr-core.c @@ -0,0 +1,44 @@ +#include "cltr-core.h" +#include "cltr-private.h" + +int +cltr_init(int *argc, char ***argv) +{ + int gl_attributes[] = + { + GLX_RGBA, + GLX_DOUBLEBUFFER, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + 0 + }; + + XVisualInfo *vinfo; + + + g_thread_init (NULL); + // XInitThreads (); + + if ((CltrCntx.xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) + { + return 0; + } + + CltrCntx.xscreen = DefaultScreen(CltrCntx.xdpy); + CltrCntx.xwin_root = RootWindow(CltrCntx.xdpy, CltrCntx.xscreen); + + if ((vinfo = glXChooseVisual(CltrCntx.xdpy, + CltrCntx.xscreen, + gl_attributes)) == NULL) + { + fprintf(stderr, "Unable to find visual\n"); + return 0; + } + + CltrCntx.gl_context = glXCreateContext(CltrCntx.xdpy, vinfo, 0, True); + + cltr_events_init(); + + return 1; +} diff --git a/cltr-core.h b/cltr-core.h new file mode 100644 index 000000000..76e2a5c2a --- /dev/null +++ b/cltr-core.h @@ -0,0 +1,9 @@ +#ifndef _HAVE_CLTR_CORE_H +#define _HAVE_CLTR_CORE_H + +#include "cltr.h" + +int +cltr_init(int *argc, char ***argv); + +#endif diff --git a/cltr-events.c b/cltr-events.c new file mode 100644 index 000000000..15425acaa --- /dev/null +++ b/cltr-events.c @@ -0,0 +1,176 @@ +#include + +#include "cltr-events.h" +#include "cltr-private.h" + +typedef void (*CltrXEventFunc) (XEvent *xev, gpointer user_data); + +typedef struct +{ + GSource source; + Display *display; + GPollFD event_poll_fd; +} +CltrXEventSource; + +static gboolean +x_event_prepare (GSource *source, + gint *timeout) +{ + Display *display = ((CltrXEventSource*)source)->display; + + *timeout = -1; + + return XPending (display); +} + +static gboolean +x_event_check (GSource *source) +{ + CltrXEventSource *display_source = (CltrXEventSource*)source; + gboolean retval; + + if (display_source->event_poll_fd.revents & G_IO_IN) + retval = XPending (display_source->display); + else + retval = FALSE; + + return retval; +} + +static gboolean +x_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + Display *display = ((CltrXEventSource*)source)->display; + CltrXEventFunc event_func = (CltrXEventFunc) callback; + + XEvent xev; + + if (XPending (display)) + { + XNextEvent (display, &xev); + + if (event_func) + (*event_func) (&xev, user_data); + } + + return TRUE; +} + +static const GSourceFuncs x_event_funcs = { + x_event_prepare, + x_event_check, + x_event_dispatch, + NULL +}; + +void +cltr_dispatch_expose(XExposeEvent *xexpev) +{ + // cltr_photo_grid_redraw(Grid); +} + +void +cltr_dispatch_x_event (XEvent *xevent, + gpointer data) +{ + /* Should actually forward on to focussed widget */ + + ClutterMainContext *ctx = CLTR_CONTEXT(); + + cltr_widget_handle_xevent(ctx->window, xevent); + +#if 0 + switch (xevent->type) + { + case MapNotify: + CLTR_DBG("Map Notify Event"); + break; + case Expose: + CLTR_DBG("Expose"); /* TODO COMPRESS */ + cltr_dispatch_expose(&xevent->xexpose); + break; + case KeyPress: + CLTR_DBG("KeyPress"); + cltr_dispatch_keypress(&xevent->xkey); + break; + } +#endif +} + +void +cltr_events_init() +{ + GMainContext *gmain_context; + int connection_number; + GSource *source; + CltrXEventSource *display_source; + + ClutterMainContext *ctx = CLTR_CONTEXT(); + + /* g_main loop stuff */ + + gmain_context = g_main_context_default (); + + g_main_context_ref (gmain_context); + + connection_number = ConnectionNumber (CltrCntx.xdpy); + + source = g_source_new ((GSourceFuncs *)&x_event_funcs, + sizeof (CltrXEventSource)); + + display_source = (CltrXEventSource *)source; + + display_source->event_poll_fd.fd = connection_number; + display_source->event_poll_fd.events = G_IO_IN; + display_source->display = CltrCntx.xdpy; + + g_source_add_poll (source, &display_source->event_poll_fd); + g_source_set_can_recurse (source, TRUE); + + g_source_set_callback (source, + (GSourceFunc) cltr_dispatch_x_event, + NULL /* no userdata */, NULL); + + g_source_attach (source, gmain_context); + g_source_unref (source); + + ctx->internal_event_q = g_queue_new(); +} + +void +cltr_main_loop() +{ + ClutterMainContext *ctx = CLTR_CONTEXT(); + + /* + GMainLoop *loop; + + loop = g_main_loop_new (g_main_context_default (), FALSE); + + g_main_loop_run (loop); + */ + + while (TRUE) + { + if (!g_queue_is_empty (ctx->internal_event_q)) + { + CltrWidget *widget = NULL; + CltrWindow *win = CLTR_WINDOW(ctx->window); + + while ((widget = g_queue_pop_head(ctx->internal_event_q)) != NULL) + { + cltr_widget_paint(widget); + } + + /* Swap Buffers */ + glXSwapBuffers(ctx->xdpy, cltr_window_xwin(win)); + } + + /* while (g_main_context_pending(g_main_context_default ())) */ + g_main_context_iteration (g_main_context_default (), TRUE); + + } +} diff --git a/cltr-events.h b/cltr-events.h new file mode 100644 index 000000000..48180e9b1 --- /dev/null +++ b/cltr-events.h @@ -0,0 +1,18 @@ +#ifndef _HAVE_CLTR_EVENT_H +#define _HAVE_CLTR_EVENT_H + +#include "cltr.h" + + + +void +cltr_main_loop(); + +void +cltr_dispatch_x_event (XEvent *xevent, + gpointer data); + +void +cltr_events_init(); + +#endif diff --git a/cltr-photo-grid.c b/cltr-photo-grid.c index 183bee2a7..b2676b8e3 100644 --- a/cltr-photo-grid.c +++ b/cltr-photo-grid.c @@ -1,18 +1,146 @@ #include "cltr-photo-grid.h" +#include "cltr-private.h" + +/* + TODO + + - image cache !! + + - change idle_cb to timeouts, reduce tearing + inc interactivity on + image load + + - Split events into seperate file ( break up ctrl.c ) + + - offset zoom a little to give border around picture grid + + - figure out highlighting selected cell + + - tape on pictures ? + + - tidy this code here + document ! + - fix threads, lower priority ? + + */ + +#define ANIM_FPS 60 +#define FPS_TO_TIMEOUT(t) (1000/(t)) + +struct CltrPhotoGridCell +{ + Pixbuf *pixb; + float angle; + CltrTexture *texture; + gint anim_step; + + CltrPhotoGridCellState state; +}; + +struct CltrPhotoGrid +{ + CltrWidget widget; + + gchar *img_path; + + int n_rows; + int n_cols; + int row_offset; /* for scrolling */ + + int cell_width; + int cell_height; + + GList *cells_tail; + GList *cell_active; + + /* animation / zoom etc stuff */ + + int anim_n_steps, anim_step; + + float zoom_min, zoom_max, zoom_step; + + float view_min_x, view_max_x, view_min_y, view_max_y; + + float scroll_dist; + + CltrPhotoGridState state; + + int scroll_state, scroll_step; /* urg */ + +}; + +static void +cltr_photo_grid_paint(CltrWidget *widget); + +static gboolean +cltr_photo_grid_handle_xevent (CltrWidget *widget, XEvent *xev); + +static void +cltr_photo_grid_show(CltrWidget *widget); + /* this likely shouldn'y go here */ static GMutex *Mutex_GRID = NULL; -ClutterPhotoGridCell* -cltr_photo_grid_cell_new(ClutterPhotoGrid *grid, - Pixbuf *pixb, - const gchar *filename) + +static void +cltr_photo_grid_handle_xkeyevent(CltrPhotoGrid *grid, XKeyEvent *xkeyev) { - ClutterPhotoGridCell *cell = NULL; - int maxw = grid->width, maxh = grid->height; + KeySym kc; + + kc = XKeycodeToKeysym(xkeyev->display, xkeyev->keycode, 0); + + switch (kc) + { + case XK_Left: + case XK_KP_Left: + cltr_photo_grid_navigate(grid, CLTR_WEST); + break; + case XK_Up: + case XK_KP_Up: + cltr_photo_grid_navigate(grid, CLTR_NORTH); + break; + case XK_Right: + case XK_KP_Right: + cltr_photo_grid_navigate(grid, CLTR_EAST); + break; + case XK_Down: + case XK_KP_Down: + cltr_photo_grid_navigate(grid, CLTR_SOUTH); + break; + case XK_Return: + cltr_photo_grid_activate_cell(grid); + break; + default: + CLTR_DBG("unhandled keysym"); + } +} + +static gboolean +cltr_photo_grid_handle_xevent (CltrWidget *widget, XEvent *xev) +{ + CltrPhotoGrid* grid = CLTR_PHOTO_GRID(widget); + + switch (xev->type) + { + case KeyPress: + CLTR_DBG("KeyPress"); + cltr_photo_grid_handle_xkeyevent(grid, &xev->xkey); + break; + } + + return TRUE; +} + + +CltrPhotoGridCell* +cltr_photo_grid_cell_new(CltrPhotoGrid *grid, + Pixbuf *pixb, + const gchar *filename) +{ + CltrPhotoGridCell *cell = NULL; + int maxw = grid->widget.width, maxh = grid->widget.height; int neww = 0, newh = 0; - cell = g_malloc0(sizeof(ClutterPhotoGridCell)); + cell = g_malloc0(sizeof(CltrPhotoGridCell)); if (pixb->width > pixb->height) /* landscape */ { @@ -49,8 +177,8 @@ cltr_photo_grid_cell_new(ClutterPhotoGrid *grid, } void -cltr_photo_grid_append_cell(ClutterPhotoGrid *grid, - ClutterPhotoGridCell *cell) +cltr_photo_grid_append_cell(CltrPhotoGrid *grid, + CltrPhotoGridCell *cell) { grid->cells_tail = g_list_append(grid->cells_tail, cell); @@ -59,7 +187,7 @@ cltr_photo_grid_append_cell(ClutterPhotoGrid *grid, /* relative */ static void -ctrl_photo_grid_cell_to_coords(ClutterPhotoGrid *grid, +ctrl_photo_grid_cell_to_coords(CltrPhotoGrid *grid, GList *cell, int *x, int *y) @@ -77,7 +205,7 @@ ctrl_photo_grid_cell_to_coords(ClutterPhotoGrid *grid, } static void -ctrl_photo_grid_get_zoomed_coords(ClutterPhotoGrid *grid, +ctrl_photo_grid_get_zoomed_coords(CltrPhotoGrid *grid, int x, int y, float *tx, @@ -94,7 +222,7 @@ ctrl_photo_grid_get_zoomed_coords(ClutterPhotoGrid *grid, } static gboolean -cell_is_offscreen(ClutterPhotoGrid *grid, +cell_is_offscreen(CltrPhotoGrid *grid, GList *cell, CltrDirection *where) { @@ -122,9 +250,9 @@ cell_is_offscreen(ClutterPhotoGrid *grid, gboolean cltr_photo_grid_idle_cb(gpointer data) { - ClutterPhotoGrid *grid = (ClutterPhotoGrid *)data; + CltrPhotoGrid *grid = (CltrPhotoGrid *)data; - cltr_photo_grid_redraw(grid); + cltr_widget_queue_paint(CLTR_WIDGET(grid)); switch(grid->state) { @@ -144,7 +272,7 @@ cltr_photo_grid_idle_cb(gpointer data) void -cltr_photo_grid_navigate(ClutterPhotoGrid *grid, +cltr_photo_grid_navigate(CltrPhotoGrid *grid, CltrDirection direction) { GList *cell_orig = grid->cell_active; @@ -198,7 +326,8 @@ cltr_photo_grid_navigate(ClutterPhotoGrid *grid, } if (grid->state != CLTR_PHOTO_GRID_STATE_ZOOMED) - g_idle_add(cltr_photo_grid_idle_cb, grid); + g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS), + cltr_photo_grid_idle_cb, grid); } if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOMED) @@ -215,7 +344,8 @@ cltr_photo_grid_navigate(ClutterPhotoGrid *grid, grid->anim_step = 0; zoom = grid->zoom_max; - g_idle_add(cltr_photo_grid_idle_cb, grid); + g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS), + cltr_photo_grid_idle_cb, grid); } ctrl_photo_grid_cell_to_coords(grid, grid->cell_active, &x, &y); @@ -226,19 +356,20 @@ cltr_photo_grid_navigate(ClutterPhotoGrid *grid, CLTR_DBG("x: %f, y: %f", grid->view_max_x , grid->view_max_y); - cltr_photo_grid_redraw(grid); + cltr_widget_queue_paint(CLTR_WIDGET(grid)); } } void /* bleh badly named */ -cltr_photo_grid_activate_cell(ClutterPhotoGrid *grid) +cltr_photo_grid_activate_cell(CltrPhotoGrid *grid) { if (grid->state == CLTR_PHOTO_GRID_STATE_BROWSE) { grid->state = CLTR_PHOTO_GRID_STATE_ZOOM_IN; - g_idle_add(cltr_photo_grid_idle_cb, grid); + g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS), + cltr_photo_grid_idle_cb, grid); } else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOMED) { @@ -248,7 +379,8 @@ cltr_photo_grid_activate_cell(ClutterPhotoGrid *grid) grid->view_min_x = 0.0; grid->view_min_y = 0.0; /*- (grid->row_offset * grid->cell_height);*/ - g_idle_add(cltr_photo_grid_idle_cb, grid); + g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS), + cltr_photo_grid_idle_cb, grid); } /* que a draw ? */ @@ -258,7 +390,7 @@ cltr_photo_grid_activate_cell(ClutterPhotoGrid *grid) gpointer cltr_photo_grid_populate(gpointer data) { - ClutterPhotoGrid *grid = (ClutterPhotoGrid *)data; + CltrPhotoGrid *grid = (CltrPhotoGrid *)data; GDir *dir; GError *error; const gchar *entry = NULL; @@ -296,7 +428,7 @@ cltr_photo_grid_populate(gpointer data) if (pixb) { - ClutterPhotoGridCell *cell; + CltrPhotoGridCell *cell; gchar buf[24]; cell = cltr_photo_grid_cell_new(grid, pixb, entry); @@ -328,17 +460,22 @@ cltr_photo_grid_populate(gpointer data) g_mutex_unlock(Mutex_GRID); - cltr_photo_grid_redraw(grid); + cltr_widget_queue_paint(CLTR_WIDGET(grid)); return NULL; } -void -cltr_photo_grid_redraw(ClutterPhotoGrid *grid) +static void +cltr_photo_grid_paint(CltrWidget *widget) { - int x = 0, y = 0, rows = grid->n_rows+1, cols = 0, i =0; + int x = 0, y = 0, rows = 0, cols = 0, i =0; GList *cell_item; float zoom, trans_x, trans_y; + CltrWindow *win = CLTR_WINDOW(widget->parent); + + CltrPhotoGrid *grid = (CltrPhotoGrid *)widget; + + rows = grid->n_rows+1; /* CLTR_MARK();*/ @@ -349,11 +486,12 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid) if (grid->cells_tail == NULL) { /* No pictures to paint yet */ + CltrWindow *win = CLTR_WINDOW(grid->widget.parent); + glColor3f(0.6, 0.6, 0.62); - glRecti(0, 0, 640, 480); + glRecti(0, 0, widget->width, widget->height); glPopMatrix(); - glXSwapBuffers(CltrCntx.xdpy, grid->parent->xwin); return; } @@ -448,8 +586,6 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid) trans_y = ((grid->view_max_y - grid->view_min_y + scroll_min_y_offset) * f) ; y = 0; - printf("%f,%f, %f\n", grid->view_max_y, grid->view_min_y, scroll_min_y_offset); - } } else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOMED_MOVE) @@ -478,20 +614,20 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid) grid->anim_step++; - if (grid->anim_step >= grid->anim_n_steps) + if (grid->anim_step >= (grid->anim_n_steps/4)) { grid->state = CLTR_PHOTO_GRID_STATE_BROWSE; grid->anim_step = 0; + zoom = grid->zoom_min; } else { - float f = (float)grid->anim_step / grid->anim_n_steps; + float f = (float)grid->anim_step / (grid->anim_n_steps/4); trans_y += (grid->scroll_dist * f); if (grid->scroll_dist > 0) /* up */ { y = (grid->row_offset-1) * grid->cell_height; - /* cell_item = g_list_nth(grid->cells_tail, grid->n_cols * (grid->row_offset+1));*/ } else /* down */ { @@ -511,7 +647,7 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid) x = 0; while (cols--) { - ClutterPhotoGridCell *cell = (ClutterPhotoGridCell *)cell_item->data; + CltrPhotoGridCell *cell = (CltrPhotoGridCell *)cell_item->data; Pixbuf *pixb = NULL; int x1, x2, y1, y2, thumb_w, thumb_h; int ns_border, ew_border; @@ -607,9 +743,7 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid) /* finally paint background */ glDisable(GL_TEXTURE_2D); glColor3f(0.6, 0.6, 0.62); - glRecti(0, 0, 640, 480); - - glXSwapBuffers(CltrCntx.xdpy, grid->parent->xwin); + glRecti(0, 0, widget->width, widget->height); g_mutex_lock(Mutex_GRID); @@ -621,42 +755,50 @@ cltr_photo_grid_redraw(ClutterPhotoGrid *grid) } -ClutterPhotoGrid* -cltr_photo_grid_new(ClutterWindow *win, +static void +cltr_photo_grid_show(CltrWidget *widget) +{ + CltrPhotoGrid* grid = CLTR_PHOTO_GRID(widget); + + cltr_widget_queue_paint(widget); +} + +CltrWidget* +cltr_photo_grid_new(int width, + int height, int n_cols, int n_rows, const gchar *img_path) { - ClutterPhotoGrid *grid = NULL; + CltrPhotoGrid *grid = NULL; GThread *loader_thread; - grid = util_malloc0(sizeof(ClutterPhotoGrid)); + grid = g_malloc0(sizeof(CltrPhotoGrid)); + + grid->widget.width = width; + grid->widget.height = height; + + grid->widget.show = cltr_photo_grid_show; + grid->widget.paint = cltr_photo_grid_paint; + + grid->widget.xevent_handler = cltr_photo_grid_handle_xevent; grid->img_path = strdup(img_path); - - grid->width = win->width; - grid->height = win->height; grid->n_cols = n_cols; grid->n_rows = n_rows; - grid->parent = win; - grid->cell_width = grid->width / n_cols; - grid->cell_height = grid->height / n_rows; + grid->cell_width = grid->widget.width / n_cols; + grid->cell_height = grid->widget.height / n_rows; grid->state = CLTR_PHOTO_GRID_STATE_LOADING; - grid->anim_n_steps = 40; /* value needs to be calced dep on rows */ + grid->anim_n_steps = 20; /* value needs to be calced dep on rows */ grid->anim_step = 0; - /* - grid->zoom_step = 0.05; - grid->zoom = 1.0; - */ grid->zoom_min = 1.0; - grid->view_min_x = (grid->width - (grid->zoom_min * grid->width))/2.0; + grid->view_min_x = (grid->widget.width - (grid->zoom_min * grid->widget.width))/2.0; grid->view_min_y = 0.0; - /* Assmes cols == rows */ grid->zoom_max = /* 1.0 + */ (float) (n_rows * 1.0); // - 0.3; @@ -673,17 +815,8 @@ cltr_photo_grid_new(ClutterWindow *win, TRUE, NULL); - /* - ctrl_photo_grid_cell_to_coords(grid, grid->cell_active, &x, &y); + g_timeout_add(FPS_TO_TIMEOUT(20), + cltr_photo_grid_idle_cb, grid); - - ctrl_photo_grid_get_zoomed_coords(grid, grid->zoom_max, - x, y, - &grid->view_max_x, - &grid->view_max_y); - */ - - g_idle_add(cltr_photo_grid_idle_cb, grid); - - return grid; + return CLTR_WIDGET(grid); } diff --git a/cltr-photo-grid.h b/cltr-photo-grid.h index 2004ff437..69c90de68 100644 --- a/cltr-photo-grid.h +++ b/cltr-photo-grid.h @@ -3,11 +3,13 @@ #include "cltr.h" -typedef struct ClutterPhotoGrid ClutterPhotoGrid; +typedef struct CltrPhotoGrid CltrPhotoGrid; -typedef struct ClutterPhotoGridCell ClutterPhotoGridCell; +typedef struct CltrPhotoGridCell CltrPhotoGridCell; -typedef enum ClutterPhotoGridState +#define CLTR_PHOTO_GRID(w) (CltrPhotoGrid*)(w) + +typedef enum CltrPhotoGridState { CLTR_PHOTO_GRID_STATE_LOADING , CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE , @@ -18,90 +20,44 @@ typedef enum ClutterPhotoGridState CLTR_PHOTO_GRID_STATE_ZOOMED_MOVE , CLTR_PHOTO_GRID_STATE_SCROLLED_MOVE , } -ClutterPhotoGridState; +CltrPhotoGridState; -typedef enum ClutterPhotoGridCellState +typedef enum CltrPhotoGridCellState { CLTR_PHOTO_GRID_CELL_STATE_APPEARING, CLTR_PHOTO_GRID_CELL_STATE_STATIC, } -ClutterPhotoGridCellState; +CltrPhotoGridCellState; -struct ClutterPhotoGridCell -{ - Pixbuf *pixb; - float angle; - CltrTexture *texture; - gint anim_step; - - ClutterPhotoGridCellState state; -}; - -struct ClutterPhotoGrid -{ - /* XXX should be base widget stuff */ - int x,y; - int width; - int height; - ClutterWindow *parent; - - /* ****** */ - - gchar *img_path; - - int n_rows; - int n_cols; - int row_offset; /* for scrolling */ - - int cell_width; - int cell_height; - - GList *cells_tail; - GList *cell_active; - - /* animation / zoom etc stuff */ - - int anim_n_steps, anim_step; - - float zoom_min, zoom_max, zoom_step; - - float view_min_x, view_max_x, view_min_y, view_max_y; - - float scroll_dist; - - ClutterPhotoGridState state; - - int scroll_state, scroll_step; /* urg */ - -}; - -ClutterPhotoGridCell* -cltr_photo_grid_cell_new(ClutterPhotoGrid *grid, +CltrPhotoGridCell* +cltr_photo_grid_cell_new(CltrPhotoGrid *grid, Pixbuf *pixb, const gchar *filename); void -cltr_photo_grid_append_cell(ClutterPhotoGrid *grid, - ClutterPhotoGridCell *cell); +cltr_photo_grid_append_cell(CltrPhotoGrid *grid, + CltrPhotoGridCell *cell); void -cltr_photo_grid_navigate(ClutterPhotoGrid *grid, +cltr_photo_grid_navigate(CltrPhotoGrid *grid, CltrDirection direction) ; void /* bleh badly named */ -cltr_photo_grid_activate_cell(ClutterPhotoGrid *grid); +cltr_photo_grid_activate_cell(CltrPhotoGrid *grid); gpointer cltr_photo_grid_populate(gpointer data) ; void -cltr_photo_grid_redraw(ClutterPhotoGrid *grid); +cltr_photo_grid_redraw(CltrPhotoGrid *grid); -ClutterPhotoGrid* -cltr_photo_grid_new(ClutterWindow *win, +CltrWidget* +cltr_photo_grid_new(int width, + int height, int n_cols, int n_rows, - const gchar *imgs_path); + const gchar *img_path); + #endif diff --git a/cltr-private.h b/cltr-private.h new file mode 100644 index 000000000..bc6ae40f3 --- /dev/null +++ b/cltr-private.h @@ -0,0 +1,75 @@ +#ifndef _HAVE_CLTR_PRIVATE_H +#define _HAVE_CLTR_PRIVATE_H + +#include "cltr.h" + +#define CLTR_WANT_DEBUG 1 + +#if (CLTR_WANT_DEBUG) + +#define CLTR_DBG(x, a...) \ + g_printerr ( __FILE__ ":%d,%s() " x "\n", __LINE__, __func__, ##a) + +#define CLTR_GLERR() \ + { \ + GLenum err = glGetError (); /* Roundtrip */ \ + if (err != GL_NO_ERROR) \ + { \ + g_printerr (__FILE__ ": GL Error: %x [at %s:%d]\n", \ + err, __func__, __LINE__); \ + } \ + } + +#else + +#define CLTR_DBG(x, a...) do {} while (0) +#define CLTR_GLERR() do {} while (0) + +#endif + +#define CLTR_MARK() CLTR_DBG("mark") + +typedef void (*WidgetPaintMethod) (CltrWidget *widget ) ; +typedef void (*WidgetShowMethod) (CltrWidget *widget ) ; +typedef void (*WidgetDestroyMethod) (CltrWidget *widget) ; + +typedef gboolean (*WidgetXEventHandler) (CltrWidget *widget, XEvent *xev) ; + +struct CltrWidget +{ + int x,y,width,height; + CltrWidget *parent; + + gboolean visible; + + GList *children; + + /* methods */ + + WidgetPaintMethod paint; + WidgetShowMethod show; + WidgetDestroyMethod destroy; + + WidgetXEventHandler xevent_handler; +}; + +typedef struct ClutterMainContext ClutterMainContext; + +struct ClutterMainContext +{ + Display *xdpy; + Window xwin_root; + int xscreen; + GC xgc; + + GLXContext gl_context; + + CltrWidget *window; + GQueue *internal_event_q; +}; + +ClutterMainContext CltrCntx; + +#define CLTR_CONTEXT() &CltrCntx + +#endif diff --git a/cltr-texture.c b/cltr-texture.c index 09ce187b8..25bcf5003 100644 --- a/cltr-texture.c +++ b/cltr-texture.c @@ -1,4 +1,5 @@ #include "cltr-texture.h" +#include "cltr-private.h" /* IDEAS or less memory diff --git a/cltr-texture.h b/cltr-texture.h index b78cbd30a..833822850 100644 --- a/cltr-texture.h +++ b/cltr-texture.h @@ -3,6 +3,24 @@ #include "cltr.h" +typedef struct CltrTexture CltrTexture; + +struct CltrTexture +{ + Pixbuf *pixb; + + int width, height; + + int n_x_tiles, n_y_tiles; + int *tile_x_position, *tile_x_size, *tile_x_waste; + int *tile_y_position, *tile_y_size, *tile_y_waste; + + GLuint *tiles; + + gint refcnt; +}; + + CltrTexture* cltr_texture_new(Pixbuf *pixb); diff --git a/cltr-widget.c b/cltr-widget.c new file mode 100644 index 000000000..5f1c99726 --- /dev/null +++ b/cltr-widget.c @@ -0,0 +1,82 @@ +#include "cltr-widget.h" +#include "cltr-private.h" + +CltrWidget* +cltr_widget_new(void) +{ + CltrWidget *w = NULL; + + w = g_malloc0(sizeof(CltrWidget)); + + return w; +} + +void +cltr_widget_show(CltrWidget *widget) +{ + if (widget->show) + { + widget->visible = TRUE; + widget->show(widget); + } +} + +void +cltr_widget_show_all(CltrWidget *widget) +{ + GList *widget_item = widget->children;; + + if (widget_item) + { + do + { + CltrWidget *child = CLTR_WIDGET(widget_item->data); + + cltr_widget_show(child); + } + while ((widget_item = g_list_next(widget_item)) != NULL); + } + + cltr_widget_show(widget); +} + +void +cltr_widget_add_child(CltrWidget *widget, CltrWidget *child, int x, int y) +{ + widget->children = g_list_append(widget->children, child); + + child->parent = widget; + child->x = x; + child->y = y; +} + + +void +cltr_widget_hide(CltrWidget *widget) +{ + widget->visible = FALSE; +} + +void +cltr_widget_paint(CltrWidget *widget) +{ + if (widget->paint && widget->visible) + widget->paint(widget); +} + +void +cltr_widget_queue_paint(CltrWidget *widget) +{ + ClutterMainContext *ctx = CLTR_CONTEXT(); + + g_queue_push_head (ctx->internal_event_q, (gpointer)widget); +} + +gboolean +cltr_widget_handle_xevent(CltrWidget *widget, XEvent *xev) +{ + if (widget && widget->xevent_handler) + return widget->xevent_handler(widget, xev); + + return FALSE; +} diff --git a/cltr-widget.h b/cltr-widget.h new file mode 100644 index 000000000..75618ce3c --- /dev/null +++ b/cltr-widget.h @@ -0,0 +1,36 @@ +#ifndef _HAVE_CLTR_WIDGET_H +#define _HAVE_CLTR_WIDGET_H + +typedef struct CltrWidget CltrWidget; + +#include "cltr.h" + +#define CLTR_WIDGET(w) ((CltrWidget*)(w)) + + +CltrWidget* +cltr_widget_new(void); + +void +cltr_widget_show(CltrWidget *widget); + +void +cltr_widget_paint(CltrWidget *widget); + + +gboolean +cltr_widget_handle_xevent(CltrWidget *widget, XEvent *xev); + + + +void +cltr_widget_show_all(CltrWidget *widget); + +void +cltr_widget_queue_paint(CltrWidget *widget); + +void +cltr_widget_add_child(CltrWidget *widget, CltrWidget *child, int x, int y); + + +#endif diff --git a/cltr-window.c b/cltr-window.c new file mode 100644 index 000000000..337c5797a --- /dev/null +++ b/cltr-window.c @@ -0,0 +1,101 @@ +#include "cltr-window.h" +#include "cltr-private.h" + +static gboolean +cltr_window_handle_xevent (CltrWidget *widget, XEvent *xev); + +static void +cltr_window_show(CltrWidget *widget); + +struct CltrWindow +{ + CltrWidget widget; + Window xwin; + CltrWidget *focused_child; +}; + +CltrWidget* +cltr_window_new(int width, int height) +{ + ClutterMainContext *ctx = CLTR_CONTEXT(); + CltrWindow *win; + + win = util_malloc0(sizeof(CltrWindow)); + + win->widget.width = width; + win->widget.height = height; + win->widget.show = cltr_window_show; + win->widget.xevent_handler = cltr_window_handle_xevent; + + win->xwin = XCreateSimpleWindow(CltrCntx.xdpy, + CltrCntx.xwin_root, + 0, 0, + width, height, + 0, 0, WhitePixel(CltrCntx.xdpy, + CltrCntx.xscreen)); + + XSelectInput(CltrCntx.xdpy, win->xwin, + StructureNotifyMask|ExposureMask| + KeyPressMask|PropertyChangeMask); + + glXMakeCurrent(CltrCntx.xdpy, win->xwin, CltrCntx.gl_context); + + /* All likely better somewhere else */ + + /* view port */ + glViewport (0, 0, width, height); + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + glOrtho (0, width, height, 0, -1, 1); /* 2d */ + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + ctx->window = CLTR_WIDGET(win); + + return CLTR_WIDGET(win); +} + +Window +cltr_window_xwin(CltrWindow *win) +{ + return win->xwin; +} + +static void +cltr_window_show(CltrWidget *widget) +{ + ClutterMainContext *ctx = CLTR_CONTEXT(); + CltrWindow *win = CLTR_WINDOW(widget); + + /* XXX set focused call */ + if (widget->children) + { + win->focused_child = g_list_nth_data(widget->children, 0); + } + + XMapWindow(ctx->xdpy, win->xwin); +} + +static gboolean +cltr_window_handle_xevent (CltrWidget *widget, XEvent *xev) +{ + CltrWindow *win = CLTR_WINDOW(widget); + + /* XXX handle exposes here too */ + + if (xev->type == Expose) + { + ; + } + + /* XXX Very basic - assumes we are only interested in mouse clicks */ + if (win->focused_child) + return cltr_widget_handle_xevent(win->focused_child, xev); + + return FALSE; +} + +/* window only */ + + + diff --git a/cltr-window.h b/cltr-window.h new file mode 100644 index 000000000..237bec79b --- /dev/null +++ b/cltr-window.h @@ -0,0 +1,23 @@ +#ifndef _HAVE_CLTR_WINDOW_H +#define _HAVE_CLTR_WINDOW_H + +#include "cltr.h" + +typedef struct CltrWindow CltrWindow; + +#define CLTR_WINDOW(w) ((CltrWindow*)(w)) + +CltrWidget* +cltr_window_new(int width, int height); + +Window +cltr_window_xwin(CltrWindow *win); + +void +cltr_window_paint(CltrWidget *widget); + +void +cltr_window_add_widget(CltrWindow *win, CltrWidget *widget, int x, int y); + + +#endif diff --git a/cltr.c b/cltr.c index b42b0a514..addfdd27f 100644 --- a/cltr.c +++ b/cltr.c @@ -1,308 +1,10 @@ #include "cltr.h" -#include - -/* temp temp temp */ - -float Zoom = 1.0; -ClutterPhotoGrid *Grid = NULL; - -/* ************* */ - -static gboolean -x_event_prepare (GSource *source, - gint *timeout) -{ - Display *display = ((CltrXEventSource*)source)->display; - - *timeout = -1; - - return XPending (display); -} - -static gboolean -x_event_check (GSource *source) -{ - CltrXEventSource *display_source = (CltrXEventSource*)source; - gboolean retval; - - if (display_source->event_poll_fd.revents & G_IO_IN) - retval = XPending (display_source->display); - else - retval = FALSE; - - return retval; -} - -static gboolean -x_event_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - Display *display = ((CltrXEventSource*)source)->display; - CltrXEventFunc event_func = (CltrXEventFunc) callback; - - XEvent xev; - - if (XPending (display)) - { - XNextEvent (display, &xev); - - if (event_func) - (*event_func) (&xev, user_data); - } - - return TRUE; -} - -static const GSourceFuncs x_event_funcs = { - x_event_prepare, - x_event_check, - x_event_dispatch, - NULL -}; - -void -cltr_dispatch_expose(XExposeEvent *xexpev) -{ - cltr_photo_grid_redraw(Grid); -} - -void -cltr_dispatch_keypress(XKeyEvent *xkeyev) -{ - KeySym kc; - - kc = XKeycodeToKeysym(xkeyev->display, xkeyev->keycode, 0); - - switch (kc) - { - case XK_Left: - case XK_KP_Left: - cltr_photo_grid_navigate(Grid, CLTR_WEST); - break; - case XK_Up: - case XK_KP_Up: - cltr_photo_grid_navigate(Grid, CLTR_NORTH); - break; - case XK_Right: - case XK_KP_Right: - cltr_photo_grid_navigate(Grid, CLTR_EAST); - break; - case XK_Down: - case XK_KP_Down: - cltr_photo_grid_navigate(Grid, CLTR_SOUTH); - break; - case XK_Return: - cltr_photo_grid_activate_cell(Grid); - break; - default: - CLTR_DBG("unhandled keysym"); - } -} - -static void -cltr_dispatch_x_event (XEvent *xevent, - gpointer data) -{ - /* Should actually forward on to focussed widget */ - - switch (xevent->type) - { - case MapNotify: - CLTR_DBG("Map Notify Event"); - break; - case Expose: - CLTR_DBG("Expose"); /* TODO COMPRESS */ - cltr_dispatch_expose(&xevent->xexpose); - break; - case KeyPress: - CLTR_DBG("KeyPress"); - cltr_dispatch_keypress(&xevent->xkey); - break; - } -} - -int -cltr_init(int *argc, char ***argv) -{ - int gl_attributes[] = - { - GLX_RGBA, - GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - 0 - }; - - XVisualInfo *vinfo; - - GMainContext *gmain_context; - int connection_number; - GSource *source; - CltrXEventSource *display_source; - - g_thread_init (NULL); - // XInitThreads (); - - if ((CltrCntx.xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) - { - return 0; - } - - CltrCntx.xscreen = DefaultScreen(CltrCntx.xdpy); - CltrCntx.xwin_root = RootWindow(CltrCntx.xdpy, CltrCntx.xscreen); - - if ((vinfo = glXChooseVisual(CltrCntx.xdpy, - CltrCntx.xscreen, - gl_attributes)) == NULL) - { - fprintf(stderr, "Unable to find visual\n"); - return 0; - } - - CltrCntx.gl_context = glXCreateContext(CltrCntx.xdpy, vinfo, 0, True); - - /* g_main loop stuff */ - - gmain_context = g_main_context_default (); - - g_main_context_ref (gmain_context); - - connection_number = ConnectionNumber (CltrCntx.xdpy); - - source = g_source_new ((GSourceFuncs *)&x_event_funcs, - sizeof (CltrXEventSource)); - - display_source = (CltrXEventSource *)source; - - display_source->event_poll_fd.fd = connection_number; - display_source->event_poll_fd.events = G_IO_IN; - display_source->display = CltrCntx.xdpy; - - g_source_add_poll (source, &display_source->event_poll_fd); - g_source_set_can_recurse (source, TRUE); - - g_source_set_callback (source, - (GSourceFunc) cltr_dispatch_x_event, - NULL /* no userdata */, NULL); - - g_source_attach (source, gmain_context); - g_source_unref (source); - - return 1; -} - - -ClutterWindow* -cltr_window_new(int width, int height) -{ - ClutterWindow *win; - - win = util_malloc0(sizeof(ClutterWindow)); - - win->width = width; - win->height = height; - - win->xwin = XCreateSimpleWindow(CltrCntx.xdpy, - CltrCntx.xwin_root, - 0, 0, - width, height, - 0, 0, WhitePixel(CltrCntx.xdpy, - CltrCntx.xscreen)); - - XSelectInput(CltrCntx.xdpy, win->xwin, - StructureNotifyMask|ExposureMask| - KeyPressMask|PropertyChangeMask); - - glXMakeCurrent(CltrCntx.xdpy, win->xwin, CltrCntx.gl_context); - - /* All likely better somewhere else */ - - /* view port */ - glViewport (0, 0, width, height); - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - glOrtho (0, width, height, 0, -1, 1); /* 2d */ - glMatrixMode (GL_MODELVIEW); - glLoadIdentity (); - - glEnable (GL_TEXTURE_2D); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - return win; -} - -void -cltr_main_loop() -{ - GMainLoop *loop; - - loop = g_main_loop_new (g_main_context_default (), FALSE); - - CLTR_MARK(); - - g_main_loop_run (loop); - -} - -gboolean -test_idle_cb(gpointer data) -{ - static float angle = 0.0; - - glClear(GL_COLOR_BUFFER_BIT); - glClearColor( 0.6, 0.6, 0.62, 1.0); - - glColor3f(0.0, 0.0, 0.0); - - glTranslatef( 0.0, 0.0, 0.0); - - /* get a copy of our untranformed matrix */ - glPushMatrix(); - - /* Translate origin to rotation point */ - glTranslatef( 320.0, 240.0, 0.0); - - /* Rotate around Z axis */ - glRotatef ( angle, 0.0, 0.0, 1.0); - - /* Draw tranformed rect with origin at center */ - glRecti(-50, -50, 50, 50); - - /* Reset our un transformed matrix */ - glPopMatrix(); - - glRecti(-50, -50, 50, 50); - - angle += 0.1; - - glXSwapBuffers(CltrCntx.xdpy, (Window)data); - - return TRUE; -} - - - int main(int argc, char **argv) { - ClutterPhotoGrid *grid = NULL; - ClutterWindow *win = NULL; - /* - Pixbuf *p1, *p2, *p3; + CltrWidget *win = NULL, *grid = NULL; - p1 = pixbuf_new(2000,2000); - p2 = pixbuf_new(640,480); - p3 = pixbuf_scale_down(p1, 512, 512); - - pixbuf_copy(p3, p2, 0,0, 1000, 1000,0,0); - - exit(1); - */ if (argc < 2) { g_printerr("usage: '%s' \n" @@ -314,23 +16,11 @@ main(int argc, char **argv) win = cltr_window_new(640, 480); - grid = cltr_photo_grid_new(win, 3, 3, argv[1]); + grid = cltr_photo_grid_new(640, 480, 3, 3, argv[1]); - Grid = grid; /* laaaaaazy globals */ + cltr_widget_add_child(win, grid, 0, 0); - // cltr_photo_grid_redraw(grid); - - // g_idle_add(idle_cb, grid); - - // g_timeout_add (10, idle_cb, grid); - - // g_idle_add(test_idle_cb, (gpointer)win->xwin); - - XFlush(CltrCntx.xdpy); - - XMapWindow(CltrCntx.xdpy, win->xwin); - - XFlush(CltrCntx.xdpy); + cltr_widget_show_all(win); cltr_main_loop(); diff --git a/cltr.h b/cltr.h index 86bdd5f4a..d7029e3c4 100644 --- a/cltr.h +++ b/cltr.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -17,53 +18,6 @@ #include "pixbuf.h" #include "fonts.h" -#define CLTR_WANT_DEBUG 1 - -#if (CLTR_WANT_DEBUG) - -#define CLTR_DBG(x, a...) \ - g_printerr ( __FILE__ ":%d,%s() " x "\n", __LINE__, __func__, ##a) - -#define CLTR_GLERR() \ - { \ - GLenum err = glGetError (); /* Roundtrip */ \ - if (err != GL_NO_ERROR) \ - { \ - g_printerr (__FILE__ ": GL Error: %x [at %s:%d]\n", \ - err, __func__, __LINE__); \ - } \ - } - -#else - -#define CLTR_DBG(x, a...) do {} while (0) -#define CLTR_GLERR() do {} while (0) - -#endif - -#define CLTR_MARK() CLTR_DBG("mark") - -typedef struct CltrTexturePool CltrTexturePool; - -struct CltrTexturePool -{ - GList *texture_items; - gint n_texture_items; - GLuint *gl_textures; -}; - -typedef struct ClutterMainContext ClutterMainContext; - -struct ClutterMainContext -{ - Display *xdpy; - Window xwin_root; - int xscreen; - GC xgc; - GLXContext gl_context; - CltrTexturePool texture_pool; -}; - typedef enum CltrDirection { CLTR_NORTH, @@ -73,51 +27,16 @@ typedef enum CltrDirection } CltrDirection; -typedef struct ClutterWindow ClutterWindow; - -struct ClutterWindow -{ - Window xwin; - int width; - int height; -}; - -ClutterMainContext CltrCntx; - -/* Event Loop Integration */ - -typedef void (*CltrXEventFunc) (XEvent *xev, gpointer user_data); - -typedef struct -{ - GSource source; - Display *display; - GPollFD event_poll_fd; -} -CltrXEventSource; - /* texture stuff */ -typedef struct CltrTexture CltrTexture; - -struct CltrTexture -{ - Pixbuf *pixb; - - int width, height; - - int n_x_tiles, n_y_tiles; - int *tile_x_position, *tile_x_size, *tile_x_waste; - int *tile_y_position, *tile_y_size, *tile_y_waste; - - GLuint *tiles; - - gint refcnt; -}; - /* ******************* */ +#include "cltr-core.h" #include "cltr-texture.h" +#include "cltr-events.h" +#include "cltr-widget.h" +#include "cltr-window.h" + #include "cltr-photo-grid.h" #endif