#include "cfg.h" #ifdef GRDRV_ATHEOS #include #include #include #include #include #include #include #include using namespace std; extern "C" { #include "links.h" } #define WINDOW_TITLE_SIZE 16 #define TOP_PANEL_SIZE 32 #define NEW_WINDOW_X_ADD 16 #define NEW_WINDOW_Y_ADD 16 #define NEW_WINDOW_X_MIN 8 #define NEW_WINDOW_Y_MIN 8 #ifdef debug #undef debug #endif #ifdef debug2 #undef debug2 #endif #define debug(x) #define debug2(x) extern struct graphics_driver atheos_driver; using namespace os; class LinksApplication : public Application { public: LinksApplication():Application("application/x-vnd.links"){} virtual bool OkToQuit(){return false;} }; class LinksView; class LinksWindow : public Window { public: LinksWindow(Rect r); ~LinksWindow(); virtual void FrameSized(const Point &d); virtual bool OkToQuit(); int resized; LinksView *view; }; class LinksView : public View { public: LinksView(LinksWindow *w); ~LinksView(); virtual void Paint(const Rect &r); virtual void MouseDown(const Point &p, uint32 b); virtual void MouseUp(const Point &p, uint32 b, Message *m); virtual void MouseMove(const Point &p, int c, uint32 b, Message *m); virtual void KeyDown(const char *s, const char *rs, uint32 q); virtual void WheelMoved(const Point &d); LinksWindow *win; struct graphics_device *dev; void d_flush(); int flushing; int last_x, last_y; }; #define lv(dev) ((LinksView *)(dev)->driver_data) #define lock_dev(dev) do { if (lv(dev)->win->Lock()) return; } while (0) #define lock_dev0(dev) do { if (lv(dev)->win->Lock()) return 0; } while (0) #define unlock_dev(dev) do { lv(dev)->win->Unlock(); } while (0) static LinksApplication *ath_links_app; static Locker *ath_lock = NULL; static int msg_pipe[2]; static thread_id ath_app_thread_id; #define rpipe (msg_pipe[0]) #define wpipe (msg_pipe[1]) #define small_color (sizeof(Color32_s) <= sizeof(long)) #define get_color32(c, rgb) Color32_s c((rgb >> 16) & 255, (rgb >> 8) & 255, rgb & 255, 255) static color_space ath_cs_desktop, ath_cs_bmp; static int ath_x_size, ath_y_size; static int ath_y_panel; static int ath_win_x_size, ath_win_y_size; static int ath_win_x_pos, ath_win_y_pos; LinksWindow::LinksWindow(Rect r):Window(r, "links_wnd", "Links") { debug2("LINKSWINDOW\n"); resized = 0; view = NULL; } LinksWindow::~LinksWindow() { view = NULL; debug2("~LINKSWINDOW\n"); } void LinksWindow::FrameSized(const Point &d) { resized = 1; } bool LinksWindow::OkToQuit() { ath_lock->Lock(); Lock(); if (view) if (view->dev) view->dev->keyboard_handler(view->dev, KBD_CTRL_C, 0); Unlock(); ath_lock->Unlock(); write(wpipe, " ", 1); /*debug2("key: :%s: :%s: %d %d\n", s, rs, q, c);*/ return false; } static void do_flush(void *p_dev) { struct graphics_device *dev = (struct graphics_device *)p_dev; LinksView *v = lv(dev); v->win->Lock(); v->win->Flush(); v->win->Unlock(); v->flushing = 0; } LinksView::LinksView(LinksWindow *w):View(w->GetBounds(), "Links", CF_FOLLOW_ALL, WID_WILL_DRAW | WID_FULL_UPDATE_ON_RESIZE) { debug2("LINKSVIEW\n"); (win = w)->AddChild(this); w->SetFocusChild(this); w->view = this; flushing = 0; last_x = last_y = 0; } LinksView::~LinksView() { win->view = NULL; debug2("~LINKSVIEW\n"); } void LinksView::d_flush() { if (flushing) return; register_bottom_half(do_flush, this->dev); flushing = 1; } #undef select int ath_select(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t) { int v; if (ath_lock) ath_lock->Unlock(); v = select(n, r, w, e, t); if (ath_lock) { ath_lock->Lock(); check_bottom_halves(); } return v; } static void ath_get_event(void *dummy) { char dummy_buffer[256]; read(rpipe, dummy_buffer, 256); debug2("GETE\n"); } static void ath_get_size(struct graphics_device *dev) { Rect r = lv(dev)->GetBounds(); dev->size.x1 = dev->size.y1 = 0; dev->size.x2 = (int)r.Width() + 1; dev->size.y2 = (int)r.Height() + 1; } void LinksView::Paint(const Rect &r) { struct rect rr; win->Unlock(); ath_lock->Lock(); win->Lock(); rr.x1 = (int)r.left; rr.x2 = (int)r.right + 1; rr.y1 = (int)r.top; rr.y2 = (int)r.bottom + 1; /*debug2("paint: %d %d %d %d\n", rr.x1, rr.x2, rr.y1, rr.y2);*/ if (dev) { if (!win->resized) dev->redraw_handler(dev, &rr); else { ath_get_size(dev); win->resized = 0; dev->resize_handler(dev); } } check_bottom_halves(); ath_lock->Unlock(); write(wpipe, " ", 1); } void LinksView::MouseDown(const Point &p, uint32 b) { win->Unlock(); ath_lock->Lock(); win->Lock(); if (dev) dev->mouse_handler(dev, last_x = (int)p.x, last_y = (int)p.y, B_DOWN | (b == 2 ? B_RIGHT : b == 3 ? B_MIDDLE : B_LEFT)); ath_lock->Unlock(); write(wpipe, " ", 1); } void LinksView::MouseUp(const Point &p, uint32 b, Message *m) { win->Unlock(); ath_lock->Lock(); win->Lock(); if (dev) dev->mouse_handler(dev, last_x = (int)p.x, last_y = (int)p.y, B_UP | (b == 2 ? B_RIGHT : b == 3 ? B_MIDDLE : B_LEFT)); ath_lock->Unlock(); write(wpipe, " ", 1); } void LinksView::MouseMove(const Point &p, int c, uint32 b, Message *m) { win->Unlock(); ath_lock->Lock(); win->Lock(); if (dev) dev->mouse_handler(dev, last_x = (int)p.x, last_y = (int)p.y, !b ? B_MOVE : B_DRAG | (b & 1 ? B_LEFT : b & 2 ? B_RIGHT : b & 4 ? B_MIDDLE : B_LEFT)); ath_lock->Unlock(); write(wpipe, " ", 1); } void LinksView::WheelMoved(const Point &d) { win->Unlock(); ath_lock->Lock(); win->Lock(); if (d.y) if (dev) dev->mouse_handler(dev, last_x, last_y, B_MOVE | (d.y > 0 ? B_WHEELDOWN : B_WHEELUP)); if (d.x) if (dev) dev->mouse_handler(dev, last_x, last_y, B_MOVE | (d.x < 0 ? B_WHEELLEFT : B_WHEELRIGHT)); ath_lock->Unlock(); write(wpipe, " ", 1); } void LinksView::KeyDown(const char *s, const char *rs, uint32 q) { int c; unsigned char *ss = q & (QUAL_CTRL | QUAL_ALT) ? (unsigned char *)rs : (unsigned char *)s; win->Unlock(); ath_lock->Lock(); win->Lock(); GET_UTF_8(ss, c); switch (c) { case VK_BACKSPACE: c = KBD_BS; break; case VK_ENTER: c = KBD_ENTER; break; case VK_SPACE: c = ' '; break; case VK_TAB: c = KBD_TAB; break; case VK_ESCAPE: c = KBD_ESC; break; case VK_LEFT_ARROW: c = KBD_LEFT; break; case VK_RIGHT_ARROW: c = KBD_RIGHT; break; case VK_UP_ARROW: c = KBD_UP; break; case VK_DOWN_ARROW: c = KBD_DOWN; break; case VK_INSERT: c = KBD_INS; break; case VK_DELETE: c = KBD_DEL; break; case VK_HOME: c = KBD_HOME; break; case VK_END: c = KBD_END; break; case VK_PAGE_UP: c = KBD_PAGE_UP; break; case VK_PAGE_DOWN: c = KBD_PAGE_DOWN; break; default: if (c < 32) c = 0; else q &= ~QUAL_SHIFT; break; } if (c) if (dev) dev->keyboard_handler(dev, c, (q & QUAL_SHIFT ? KBD_SHIFT : 0) | (q & QUAL_CTRL ? KBD_CTRL : 0) | (q & QUAL_ALT ? KBD_ALT : 0)); ath_lock->Unlock(); write(wpipe, " ", 1); /*debug2("key: :%s: :%s: %d %d\n", s, rs, q, c);*/ } static uint32 ath_app_thread(void *p) { ath_links_app->Run(); delete ath_links_app; return 0; } static unsigned char *ath_init_driver(unsigned char *param, unsigned char *display) { Desktop *d; ath_links_app = new LinksApplication(); if (!ath_links_app) { return stracpy((unsigned char *)"Unable to allocate Application object.\n"); } ath_lock = new Locker("links_sem", false, false); if (!ath_lock || ath_lock->Lock()) { delete ath_links_app; return stracpy((unsigned char *)"Could not create lock.\n"); } if (c_pipe(msg_pipe)) { delete ath_lock; ath_lock = NULL; delete ath_links_app; return stracpy((unsigned char *)"Could not create pipe.\n"); } set_nonblock(rpipe); set_nonblock(wpipe); set_handlers(rpipe, ath_get_event, NULL, NULL); ath_app_thread_id = spawn_thread("links_app", (void *)ath_app_thread, 0, 0, NULL); if (ath_app_thread_id == -1) { int r; EINTRLOOP(r, close(rpipe)); EINTRLOOP(r, close(wpipe)); delete ath_lock; ath_lock = NULL; delete ath_links_app; return stracpy((unsigned char *)"Could not spawn thread.\n"); } resume_thread(ath_app_thread_id); if ((d = new Desktop)) { ath_cs_desktop = d->GetColorSpace(); ath_x_size = d->GetResolution().x; ath_y_size = d->GetResolution().y; delete d; } else { ath_cs_desktop = CS_NO_COLOR_SPACE; ath_x_size = 640; ath_y_size = 480; } ath_y_panel = WINDOW_TITLE_SIZE; #ifdef __SYLLABLE__ ath_y_panel += TOP_PANEL_SIZE; #endif if (ath_y_panel > ath_y_size) ath_y_panel = 0; ath_win_y_size = (ath_y_size - ath_y_panel) * 9 / 10; ath_win_x_size = ath_win_y_size; /* debug2("%d %d\n", ath_x_size, ath_y_size); debug2("%d %d\n", ath_win_x_size, ath_win_y_size); */ ath_win_y_pos = (ath_y_size - ath_y_panel - ath_win_y_size) / 2 + ath_y_panel; ath_win_x_pos = ath_x_size - ath_win_x_size - ath_win_y_pos; if (/*ath_cs_desktop == CS_RGB32 ||*/ ath_cs_desktop == CS_RGB24 || ath_cs_desktop == CS_RGB16 || ath_cs_desktop == CS_RGB15) ath_cs_bmp = ath_cs_desktop; else if (ath_cs_desktop == CS_RGB32 || ath_cs_desktop == CS_RGBA32) ath_cs_bmp = CS_RGB24; else ath_cs_bmp = CS_RGB15; switch (ath_cs_bmp) { case CS_RGB24: atheos_driver.depth = 0xc3; break; case CS_RGB16: atheos_driver.depth = 0x82; break; case CS_RGB15: atheos_driver.depth = 0x7a; break; default: internal_error("unknown depth"); } return NULL; } static void ath_shutdown_driver() { int r; debug((unsigned char *)"D"); set_handlers(rpipe, NULL, NULL, NULL); EINTRLOOP(r, close(rpipe)); EINTRLOOP(r, close(wpipe)); ath_lock->Unlock(); debug((unsigned char *)"DD"); ath_links_app->PostMessage(M_TERMINATE); debug((unsigned char *)"E"); /*delete ath_lock; ath_lock = NULL;*/ debug((unsigned char *)"F"); } static void ath_after_fork() { int r; EINTRLOOP(r, close(rpipe)); EINTRLOOP(r, close(wpipe)); } static struct graphics_device *ath_init_device() { LinksView *view; LinksWindow *win; struct graphics_device *dev = (struct graphics_device *)mem_calloc(sizeof(struct graphics_device)); if (!dev) return NULL; debug((unsigned char *)"1"); retry: win = new LinksWindow(Rect(ath_win_x_pos, ath_win_y_pos, ath_win_x_pos + ath_win_x_size, ath_win_y_pos + ath_win_y_size)); debug((unsigned char *)"2"); if (!win) { if (out_of_memory(0, NULL, 0)) goto retry; mem_free(dev); return NULL; } debug((unsigned char *)"3"); retry2: view = new LinksView(win); if (!view) { if (out_of_memory(0, NULL, 0)) goto retry2; delete win; mem_free(dev); return NULL; } view->dev = dev; dev->driver_data = view; ath_get_size(dev); memcpy(&dev->clip, &dev->size, sizeof(struct rect)); debug((unsigned char *)"4"); win->Show(); win->MakeFocus(); debug((unsigned char *)"5"); ath_win_x_pos += NEW_WINDOW_X_ADD; ath_win_y_pos += NEW_WINDOW_Y_ADD; if (ath_win_x_pos + ath_win_x_size > ath_x_size - NEW_WINDOW_X_MIN) ath_win_x_pos = NEW_WINDOW_X_MIN; if (ath_win_y_pos + ath_win_y_size > ath_y_size - NEW_WINDOW_Y_MIN) ath_win_y_pos = ath_y_panel + NEW_WINDOW_Y_MIN; return dev; } static void ath_shutdown_device(struct graphics_device *dev) { LinksWindow *win = lv(dev)->win; unregister_bottom_half(do_flush, dev); lv(dev)->dev = NULL; win->PostMessage(M_TERMINATE); mem_free(dev); } static void ath_set_title(struct graphics_device *dev, unsigned char *title) { LinksWindow *win = lv(dev)->win; lock_dev(dev); win->SetTitle(string((char *)title)); lv(dev)->d_flush(); unlock_dev(dev); } static int ath_get_empty_bitmap(struct bitmap *bmp) { debug2("bmp\n"); Bitmap *b; retry: b = new Bitmap(bmp->x, bmp->y, ath_cs_bmp, Bitmap::SHARE_FRAMEBUFFER); if (!b) { if (out_of_memory(0, NULL, 0)) goto retry; bmp->data = NULL; bmp->flags = NULL; return -1; } bmp->data = b->LockRaster(); bmp->skip = b->GetBytesPerRow(); bmp->flags = b; return 0; } static void ath_register_bitmap(struct bitmap *bmp) { Bitmap *b = (Bitmap *)bmp->flags; if (!b) return; b->UnlockRaster(); } static void *ath_prepare_strip(struct bitmap *bmp, int top, int lines) { debug2("preps\n"); Bitmap *b = (Bitmap *)bmp->flags; if (!b) return NULL; bmp->data = b->LockRaster(); bmp->skip = b->GetBytesPerRow(); return ((char *)bmp->data) + bmp->skip * top; } static void ath_commit_strip(struct bitmap *bmp, int top, int lines) { Bitmap *b = (Bitmap *)bmp->flags; if (!b) return; b->UnlockRaster(); } static void ath_unregister_bitmap(struct bitmap *bmp) { debug2("unb\n"); Bitmap *b = (Bitmap *)bmp->flags; if (!b) return; delete b; } static void ath_draw_bitmap(struct graphics_device *dev, struct bitmap *bmp, int x, int y) { debug2("drawb\n"); Bitmap *b = (Bitmap *)bmp->flags; if (!b) return; CLIP_DRAW_BITMAP lock_dev(dev); lv(dev)->DrawBitmap(b, b->GetBounds(), Rect(x, y, x + bmp->x - 1, y + bmp->y - 1)); lv(dev)->d_flush(); unlock_dev(dev); } static long ath_get_color(int rgb) { if (small_color) { get_color32(c, rgb); return *(long *)(void *)&c; } else return rgb & 0xffffff; } static void ath_fill_area(struct graphics_device *dev, int x1, int y1, int x2, int y2, long color) { debug2("fill\n"); CLIP_FILL_AREA lock_dev(dev); if (small_color) lv(dev)->FillRect(Rect(x1, y1, x2 - 1, y2 - 1), *(Color32_s *)(void *)&color); else lv(dev)->FillRect(Rect(x1, y1, x2 - 1, y2 - 1), get_color32(, color)); lv(dev)->d_flush(); unlock_dev(dev); } static void ath_draw_hline(struct graphics_device *dev, int x1, int y, int x2, long color) { debug2("hline\n"); CLIP_DRAW_HLINE lock_dev(dev); if (small_color) lv(dev)->SetFgColor(*(Color32_s *)(void *)&color); else lv(dev)->SetFgColor(get_color32(, color)); lv(dev)->DrawLine(Point(IPoint(x1, y)), Point(IPoint(x2 - 1, y))); lv(dev)->d_flush(); unlock_dev(dev); } static void ath_draw_vline(struct graphics_device *dev, int x, int y1, int y2, long color) { debug2("vline\n"); CLIP_DRAW_VLINE lock_dev(dev); if (small_color) lv(dev)->SetFgColor(*(Color32_s *)(void *)&color); else lv(dev)->SetFgColor(get_color32(, color)); lv(dev)->DrawLine(Point(IPoint(x, y1)), Point(IPoint(x, y2 - 1))); lv(dev)->d_flush(); unlock_dev(dev); } static int ath_scroll(struct graphics_device *dev, struct rect_set **ignore, int scx, int scy) { debug2("hscroll\n"); lock_dev0(dev); lv(dev)->ScrollRect( Rect( dev->clip.x1 - (scx < 0 ? scx : 0), dev->clip.y1 - (scy < 0 ? scy : 0), dev->clip.x2 - (scx >= 0 ? scx : 0) - 1, dev->clip.y2 - (scy >= 0 ? scy : 0) - 1), Rect( dev->clip.x1 + (scx >= 0 ? scx : 0), dev->clip.y1 + (scy >= 0 ? scy : 0), dev->clip.x2 + (scx < 0 ? scx : 0) - 1, dev->clip.y2 + (scy < 0 ? scy : 0) - 1) ); lv(dev)->d_flush(); unlock_dev(dev); return 1; } static void ath_set_clip_area(struct graphics_device *dev) { debug2("setc\n"); lock_dev(dev); lv(dev)->SetDrawingRegion(Region(IRect(dev->clip.x1, dev->clip.y1, dev->clip.x2 - 1, dev->clip.y2 - 1))); unlock_dev(dev); } static void ath_flush(struct graphics_device *dev) { unregister_bottom_half(do_flush, dev); do_flush(dev); } struct graphics_driver atheos_driver = { (unsigned char *)"atheos", ath_init_driver, ath_init_device, ath_shutdown_device, ath_shutdown_driver, NULL, ath_after_fork, NULL, NULL, NULL, NULL, ath_get_empty_bitmap, ath_register_bitmap, ath_prepare_strip, ath_commit_strip, ath_unregister_bitmap, ath_draw_bitmap, ath_get_color, ath_fill_area, ath_draw_hline, ath_draw_vline, ath_scroll, ath_set_clip_area, ath_flush, NULL, /* block */ NULL, /* unblock */ NULL, /* set_palette */ NULL, /* get_real_colors */ ath_set_title, NULL, /* exec */ NULL, /* set_clipboard_text */ NULL, /* get_clipboard_text */ 0, /* depth */ 0, 0, /* size */ GD_UNICODE_KEYS | GD_NO_OS_SHELL | GD_NO_LIBEVENT,/* flags */ NULL, /* param */ }; #endif