opt = -O0
inc = -Isrc
-#backend = SDL
+backend = SDL
ifeq ($(backend), SDL)
def = -DWINNIE_SDL
static unsigned char *framebuffer;
static int dev_fd;
+static int rgb_order[3];
struct Graphics {
Rect screen_rect;
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);
void destroy_gfx()
{
clear_screen(0, 0, 0);
- gfx_update();
+ gfx_update(gfx->screen_rect);
if(dev_fd != -1) {
close(dev_fd);
}
}
-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()
}
}
+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
if(!(mouse = (Mouse*)sh_malloc(sizeof *mouse))) {
return false;
}
+ memset(mouse, 0, sizeof *mouse);
mouse->dev_fd = -1;
#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;
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);
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;
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;
}
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;
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;
}
}
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_
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();
}
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) {
Rect Pixmap::get_rect() const
{
- Rect rect = {0, 0, width, height};
+ Rect rect(0, 0, width, height);
return rect;
}
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
unsigned char *pixels;
Pixmap();
+
+ Pixmap(const Pixmap &pixmap);
+ Pixmap &operator=(const Pixmap& pixmap);
+
~Pixmap();
int get_width() const;
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;
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());
{
}
-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
if(!(mouse = (Mouse*)sh_malloc(sizeof *mouse))) {
return false;
}
+ memset(mouse, 0, sizeof *mouse);
return true;
}
grab_win = 0;
focused_win = 0;
+ background = 0;
bg_color[0] = 210;
bg_color[1] = 106;
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);
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)
*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;
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);
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();
}
}
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);
+ }
}
}
Window *grab_win;
Pixmap mouse_cursor;
+ Pixmap *background;
void create_frame(Window *win);
void destroy_frame(Window *win);
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);