bug fixes, added background image
authorEleni Maria Stea <elene.mst@gmail.com>
Mon, 11 Mar 2013 21:19:03 +0000 (23:19 +0200)
committerEleni Maria Stea <elene.mst@gmail.com>
Mon, 11 Mar 2013 21:19:03 +0000 (23:19 +0200)
14 files changed:
Makefile
src/fbdev/gfx.cc
src/fbdev/mouse.cc
src/geom.cc
src/geom.h
src/gfx.cc
src/gfx.h
src/main.cc
src/pixmap.cc
src/pixmap.h
src/sdl/gfx.cc
src/sdl/mouse.cc
src/wm.cc
src/wm.h

index a132c3f..4242187 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ dbg = -g
 opt = -O0
 inc = -Isrc
 
-#backend = SDL
+backend = SDL
 
 ifeq ($(backend), SDL)
        def = -DWINNIE_SDL
index 74dec0c..e3677d4 100644 (file)
@@ -20,6 +20,7 @@
 
 static unsigned char *framebuffer;
 static int dev_fd;
+static int rgb_order[3];
 
 struct Graphics {
        Rect screen_rect;
@@ -59,6 +60,10 @@ bool init_gfx()
        gfx->screen_rect.height = sinfo.yres_virtual;
        gfx->color_depth = sinfo.bits_per_pixel;
 
+       rgb_order[0] = sinfo.red.offset / 8;
+       rgb_order[1] = sinfo.green.offset / 8;
+       rgb_order[2] = sinfo.blue.offset / 8;
+
        set_clipping_rect(gfx->screen_rect);
 
        int sz = FRAMEBUFFER_SIZE(gfx->screen_rect.width, gfx->screen_rect.height, gfx->color_depth);
@@ -104,7 +109,7 @@ bool init_gfx()
 void destroy_gfx()
 {
        clear_screen(0, 0, 0);
-       gfx_update();
+       gfx_update(gfx->screen_rect);
 
        if(dev_fd != -1) {
                close(dev_fd);
@@ -161,9 +166,17 @@ void set_cursor_visibility(bool visible)
        }
 }
 
-void gfx_update()
+void gfx_update(const Rect &upd_rect)
 {
-       memcpy(framebuffer, gfx->pixmap->pixels, gfx->pixmap->width * gfx->pixmap->height * (gfx->color_depth / 8));
+       Rect rect = rect_intersection(upd_rect, gfx->screen_rect);
+       unsigned char *sptr = gfx->pixmap->pixels + (rect.y * gfx->screen_rect.width + rect.x) * 4;
+       unsigned char *dptr = framebuffer + (rect.y * gfx->screen_rect.width + rect.x) * 4;
+
+       for(int i=0; i<rect.height; i++) {
+               memcpy(dptr, sptr, rect.width * 4);
+               sptr += gfx->screen_rect.width * 4;
+               dptr += gfx->screen_rect.width * 4;
+       }
 }
 
 void wait_vsync()
@@ -174,4 +187,11 @@ void wait_vsync()
        }
 }
 
+void get_rgb_order(int *r, int *g, int *b)
+{
+       *r = rgb_order[0];
+       *g = rgb_order[1];
+       *b = rgb_order[2];
+}
+
 #endif // WINNIE_FBDEV
index dae9b98..cb383de 100644 (file)
@@ -38,6 +38,7 @@ bool init_mouse()
        if(!(mouse = (Mouse*)sh_malloc(sizeof *mouse))) {
                return false;
        }
+       memset(mouse, 0, sizeof *mouse);
 
        mouse->dev_fd = -1;
 
index c9d5c51..7561397 100644 (file)
@@ -1,5 +1,18 @@
 #include "geom.h"
 
+Rect::Rect()
+{
+       x = y = width = height = 0;
+}
+
+Rect::Rect(int x, int y, int w, int h)
+{
+       this->x = x;
+       this->y = y;
+       width = w;
+       height = h;
+}
+
 static inline int min(int x, int y)
 {
        return x < y ? x : y;
index 9c00b41..203914a 100644 (file)
@@ -4,6 +4,9 @@
 struct Rect {
        int x, y;
        int width, height;
+
+       Rect();
+       Rect(int x, int y, int w, int h);
 };
 
 Rect rect_union(const Rect &a, const Rect &b);
index f0be460..c517b39 100644 (file)
@@ -47,6 +47,9 @@ void fill_rect(const Rect &rect, int r, int g, int b)
 void blit(unsigned char *src_img, const Rect &src_rect, unsigned char* dest_img,
                const Rect &dest_rect, int dest_x, int dest_y)
 {
+       int red_offs, green_offs, blue_offs;
+       get_rgb_order(&red_offs, &green_offs, &blue_offs);
+
        Rect irect = rect_intersection(get_clipping_rect(), dest_rect);
 
        int width = src_rect.width;
@@ -82,7 +85,11 @@ void blit(unsigned char *src_img, const Rect &src_rect, unsigned char* dest_img,
        unsigned char *dptr = dest_img + (dest_y * dest_rect.width + dest_x) * 4;
 
        for(int i=0; i<height; i++) {
-               memcpy(dptr, sptr, width * 4);
+               for(int j=0; j<width; j++) {
+                       dptr[j * 4 + red_offs] = sptr[j * 4];
+                       dptr[j * 4 + green_offs] = sptr[j * 4 + 1];
+                       dptr[j * 4 + blue_offs] = sptr[j * 4 + 2];
+               }
                sptr += src_rect.width * 4;
                dptr += dest_rect.width * 4;
        }
@@ -91,6 +98,9 @@ void blit(unsigned char *src_img, const Rect &src_rect, unsigned char* dest_img,
 void blit_key(unsigned char *src_img, const Rect &src_rect, unsigned char* dest_img,
                const Rect &dest_rect, int dest_x, int dest_y, int key_r, int key_g, int key_b)
 {
+       int red_offs, green_offs, blue_offs;
+       get_rgb_order(&red_offs, &green_offs, &blue_offs);
+
        Rect irect = rect_intersection(get_clipping_rect(), dest_rect);
 
        int width = src_rect.width;
@@ -132,9 +142,9 @@ void blit_key(unsigned char *src_img, const Rect &src_rect, unsigned char* dest_
                        int b = sptr[j * 4 + 2];
 
                        if(r != key_r || g != key_g || b != key_b) {
-                               dptr[j * 4] = r;
-                               dptr[j * 4 + 1] = g;
-                               dptr[j * 4 + 2] = b;
+                               dptr[j * 4 + red_offs] = r;
+                               dptr[j * 4 + green_offs] = g;
+                               dptr[j * 4 + blue_offs] = b;
                        }
                }
 
index 76cb08a..221b0aa 100644 (file)
--- a/src/gfx.h
+++ b/src/gfx.h
@@ -27,8 +27,10 @@ void blit(unsigned char *src_img, const Rect &src_rect, unsigned char* dest_img,
 void blit_key(unsigned char *src_img, const Rect &src_rect, unsigned char* dest_img,
                const Rect &dest_rect, int dest_x, int dest_y, int key_r, int key_g, int key_b);
 
-void gfx_update();
+void gfx_update(const Rect &rect);
 
 void wait_vsync(); // vertical synchronization
 
+void get_rgb_order(int *r, int *g, int *b);
+
 #endif //GFX_H_
index ae88575..f49f686 100644 (file)
@@ -39,6 +39,13 @@ int main()
        wm->add_window(win1);
        wm->add_window(win2);
 
+       Pixmap bg;
+       if(!(bg.load("data/bg.ppm"))) {
+               fprintf(stderr, "failed to load pixmap\n");
+       }
+
+       wm->set_background(&bg);
+
        while(1) {
                process_events();
        }
index 5c9b242..ada337d 100644 (file)
@@ -9,6 +9,22 @@ Pixmap::Pixmap()
        pixels = 0;
 }
 
+Pixmap::Pixmap(const Pixmap &pixmap)
+{
+       width = height = 0;
+       pixels = 0;
+       set_image(pixmap.width, pixmap.height, pixmap.pixels);
+}
+
+Pixmap &Pixmap::operator=(const Pixmap &pixmap)
+{
+       if(this != &pixmap) {
+               set_image(pixmap.width, pixmap.height, pixmap.pixels);
+       }
+
+       return *this;
+}
+
 Pixmap::~Pixmap()
 {
        if(pixels) {
@@ -28,7 +44,7 @@ int Pixmap::get_height() const
 
 Rect Pixmap::get_rect() const
 {
-       Rect rect = {0, 0, width, height};
+       Rect rect(0, 0, width, height);
        return rect;
 }
 
@@ -58,7 +74,61 @@ unsigned char *Pixmap::get_image()
 
 bool Pixmap::load(const char *fname)
 {
-       return false;   // TODO
+       FILE *fp;
+       int hdrline = 0;
+
+       if(!(fp = fopen(fname, "rb"))) {
+               fprintf(stderr, "failed to open pixmap: %s: %s\n", fname, strerror(errno));
+               return false;
+       }
+
+       /* read ppm header */
+       while(hdrline < 3) {
+               char buf[64];
+
+               if(!fgets(buf, sizeof buf, fp))
+                       goto err;
+               
+               /* skip comments */
+               if(buf[0] == '#')
+                       continue;
+
+               switch(hdrline++) {
+               case 0:
+                       /* first header line should be P6 */
+                       if(strcmp(buf, "P6\n") != 0)
+                               goto err;
+                       break;
+
+               case 1:
+                       /* second header line contains the pixmap dimensions */
+                       if(sscanf(buf, "%d %d", &width, &height) != 2)
+                               goto err;
+                       break;
+               }
+       }
+
+       set_image(width, height, 0);
+
+       for(int i=0; i<width * height * 4; i++) {
+               int c;
+               if(i % 4 != 3) {
+                       c = fgetc(fp);
+                       if(c < 0)
+                               goto err;
+               }
+               else {
+                       c = 255;
+               }
+               pixels[i] = c;
+       }
+       fclose(fp);
+       return true;
+
+err:
+       fprintf(stderr, "failed to load pixmap: %s\n", fname);
+       fclose(fp);
+       return false;
 }
 
 bool Pixmap::save(const char *fname) const
index 9e5d5fb..aebec70 100644 (file)
@@ -9,6 +9,10 @@ public:
        unsigned char *pixels;
 
        Pixmap();
+
+       Pixmap(const Pixmap &pixmap);
+       Pixmap &operator=(const Pixmap& pixmap);
+
        ~Pixmap();
 
        int get_width() const;
index cd1a4a6..11c6e79 100644 (file)
@@ -28,7 +28,7 @@ bool init_gfx()
                return false;
        }
 
-       Rect scr_rect = {0, 0, 1024, 768};
+       Rect scr_rect(0, 0, 1024, 768);
        gfx->screen_rect = scr_rect;
        gfx->color_depth = 32;
 
@@ -86,75 +86,6 @@ int get_color_depth()
        return gfx->color_depth;
 }
 
-/*void set_clipping_rect(const Rect &rect)
-{
-       gfx->clipping_rect = rect_intersection(rect, gfx->screen_rect);
-
-       SDL_Rect sdl_rect;
-       sdl_rect.x = gfx->clipping_rect.x;
-       sdl_rect.y = gfx->clipping_rect.y;
-       sdl_rect.w = gfx->clipping_recvoid fill_rect(const Rect &rect, int r, int g, int b)
-{
-       Rect drect = rect;
-       Rect screen_rect = get_screen_size();
-
-       if(drect.x < clipping_rect.x) {
-               drect.width -= clipping_rect.x - drect.x;
-               drect.x = clipping_rect.x;
-       }
-
-       if(drect.y < clipping_rect.y) {
-               drect.height -= clipping_rect.y - drect.y;
-               drect.y = clipping_rect.y;
-       }
-
-       if(drect.x + drect.width >= clipping_rect.x + clipping_rect.width) {
-               drect.width = clipping_rect.width + clipping_rect.x - drect.x;
-       }
-
-       if(drect.y + drect.height >= clipping_rect.y + clipping_rect.height) {
-               drect.height = clipping_rect.height + clipping_rect.y - drect.y;
-       }
-
-       unsigned char *fb = get_framebuffer() + (drect.x + screen_rect.width * drect.y) * 4;
-       for(int i=0; i<drect.height; i++) {
-               for(int j=0; j<drect.width; j++) {
-                       fb[j * 4] = b;
-                       fb[j * 4 + 1] = g;
-                       fb[j * 4 + 2] = r;
-               }
-               fb += screen_rect.width * 4;
-       }
-}
-t.width;
-       sdl_rect.h = gfx->clipping_rect.height;
-
-       SDL_SetClipRect(fbsurf, &sdl_rect);
-}
-
-const Rect &get_clipping_rect()
-{
-       return gfx->clipping_rect;
-}
-
-void clear_screen(int r, int g, int b)
-{
-       fill_rect(gfx->screen_rect, r, g, b);
-}
-
-void fill_rect(const Rect &rect, int r, int g, int b)
-{
-       uint32_t color = ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
-       
-       SDL_Rect sdl_rect;
-       sdl_rect.x = rect.x;
-       sdl_rect.y = rect.y;
-       sdl_rect.w = rect.width;
-       sdl_rect.h = rect.height;
-
-       SDL_FillRect(fbsurf, &sdl_rect, color);
-}*/
-
 void set_clipping_rect(const Rect &rect)
 {
        gfx->clipping_rect = rect_intersection(rect, get_screen_size());
@@ -170,20 +101,38 @@ void set_cursor_visibility(bool visible)
 {
 }
 
-void gfx_update()
+void gfx_update(const Rect &upd_rect)
 {
        if(SDL_MUSTLOCK(fbsurf)) {
                SDL_LockSurface(fbsurf);
        }
-       memcpy(fbsurf->pixels, gfx->pixmap->pixels, gfx->pixmap->width * gfx->pixmap->height * (gfx->color_depth / 8));
+
+       Rect rect = rect_intersection(upd_rect, gfx->screen_rect);
+
+       unsigned char *sptr = gfx->pixmap->pixels + (rect.y * gfx->screen_rect.width + rect.x) * 4;
+       unsigned char *dptr = (unsigned char*)fbsurf->pixels + (rect.y * gfx->screen_rect.width + rect.x) * 4;
+
+       for(int i=0; i<rect.height; i++) {
+               memcpy(dptr, sptr, rect.width * 4);
+               sptr += gfx->screen_rect.width * 4;
+               dptr += gfx->screen_rect.width * 4;
+       }
+
        if(SDL_MUSTLOCK(fbsurf)) {
                SDL_UnlockSurface(fbsurf);
        }
-       SDL_UpdateRect(fbsurf, 0, 0, 0, 0);
+       SDL_UpdateRect(fbsurf, rect.x, rect.y, rect.width, rect.height);
 }
 
 void wait_vsync()
 {
 }
 
+void get_rgb_order(int *r, int *g, int *b)
+{
+       *r = fbsurf->format->Rshift / 8;
+       *g = fbsurf->format->Gshift / 8;
+       *b = fbsurf->format->Bshift / 8;
+}
+
 #endif // WINNIE_SDL
index 546f3bf..86e9cce 100644 (file)
@@ -21,6 +21,7 @@ bool init_mouse()
        if(!(mouse = (Mouse*)sh_malloc(sizeof *mouse))) {
                return false;
        }
+       memset(mouse, 0, sizeof *mouse);
        return true;
 }
 
index 7791e79..dd47d30 100644 (file)
--- a/src/wm.cc
+++ b/src/wm.cc
@@ -91,6 +91,7 @@ WindowManager::WindowManager()
 
        grab_win = 0;
        focused_win = 0;
+       background = 0;
 
        bg_color[0] = 210;
        bg_color[1] = 106;
@@ -141,7 +142,13 @@ void WindowManager::process_windows()
 
        wait_vsync();
 
-       fill_rect(uni, bg_color[0], bg_color[1], bg_color[2]);
+       if(!background) {
+               fill_rect(uni, bg_color[0], bg_color[1], bg_color[2]);
+       }
+       else {
+               blit(background->pixels, Rect(0, 0, background->width, background->height),
+                               get_framebuffer(), get_screen_size(), 0, 0);
+       }
 
        root_win->draw_children(uni);
 
@@ -153,10 +160,10 @@ void WindowManager::process_windows()
                        get_framebuffer(), get_screen_size(), mouse_x, mouse_y,
                        0, 0, 0);
 
-       Rect mouse_rect = {mouse_x, mouse_y, mouse_cursor.get_width(), mouse_cursor.get_height()};
+       Rect mouse_rect(mouse_x, mouse_y, mouse_cursor.get_width(), mouse_cursor.get_height());
        invalidate_region(mouse_rect);
 
-       gfx_update();
+       gfx_update(uni);
 }
 
 void WindowManager::add_window(Window *win)
@@ -284,6 +291,25 @@ void WindowManager::get_unfocused_frame_color(int *r, int *g, int *b) const
        *b = frame_ucolor[2];
 }
 
+void WindowManager::set_background(const Pixmap *pixmap)
+{
+       if(background) {
+               delete background;
+       }
+
+       if(pixmap) {
+               background = new Pixmap(*pixmap);
+       }
+       else {
+               background = 0;
+       }
+}
+
+const Pixmap *WindowManager::get_background() const
+{
+       return background;
+}
+
 Window *WindowManager::get_grab_window() const
 {
        return grab_win;
@@ -349,9 +375,7 @@ void WindowManager::maximize_window(Window *win)
                rect.height -= frame_thickness * 2 + titlebar_thickness;
        }
        else {
-               rect.x = 0;
-               rect.y = 0;
-               win->move(rect.x, rect.y);
+               win->move(0, 0);
        }
 
        win->resize(rect.width, rect.height);
@@ -402,28 +426,26 @@ static void mouse(Window *win, int bn, bool pressed, int x, int y)
        static long last_click = 0;
 
        if(bn == 0) {
-               if(pressed) {
+               if(pressed) {   
+                       wm->grab_mouse(win);
+                       wm->raise_window(win);
+                       prev_x = x;
+                       prev_y = y;
+               }
+               else {
                        long time = winnie_get_time();
                        if((time - last_click) < DCLICK_INTERVAL) {
                                Window *child = win->get_children()[0];
                                Window::State state = child->get_state();
                                if(state == Window::STATE_MAXIMIZED) {
-                                       child->set_state(Window::STATE_NORMAL);
                                        wm->unmaximize_window(child);
                                }
                                else if(state == Window::STATE_NORMAL) {
                                        wm->maximize_window(child);
                                }
                        }
-
-                       wm->grab_mouse(win);
-                       wm->raise_window(win);
-                       prev_x = x;
-                       prev_y = y;
-
                        last_click = time;
-               }
-               else {
+
                        wm->release_mouse();
                }
        }
@@ -439,7 +461,9 @@ static void motion(Window *win, int x, int y)
                prev_x = x - dx;
                prev_y = y - dy;
 
-               Rect rect = win->get_rect();
-               win->move(rect.x + dx, rect.y + dy);
+               if(win->get_children()[0]->get_state() != Window::STATE_MAXIMIZED) {
+                       Rect rect = win->get_rect();
+                       win->move(rect.x + dx, rect.y + dy);
+               }
        }
 }
index 140a3b0..0ba8a04 100644 (file)
--- a/src/wm.h
+++ b/src/wm.h
@@ -28,6 +28,7 @@ private:
        Window *grab_win;
 
        Pixmap mouse_cursor;
+       Pixmap *background;
 
        void create_frame(Window *win);
        void destroy_frame(Window *win);
@@ -55,6 +56,9 @@ public:
        void set_unfocused_frame_color(int r, int g, int b);
        void get_unfocused_frame_color(int *r, int *g, int *b) const;
 
+       void set_background(const Pixmap *pixmap);
+       const Pixmap *get_background() const;
+
        Window *get_grab_window() const;
 
        void grab_mouse(Window *win);