/* stdafx.h: be sure to include berkelium before esenthel
Also adjust library and include paths for berkelium, and put the
needed dll and berkelium exe in your exe directory
*/
/******************************************************************************/
#include <berkelium/Berkelium.hpp>
#include <berkelium/Context.hpp>
#include <berkelium/Window.hpp>
#include <berkelium/WindowDelegate.hpp>
#include <EsenthelEngine/EsenthelEngine.h>
/******************************************************************************/
/* main.cpp: the main program, use this like an EE tutorial
A browser element gets focused if you click on it.
*/
/******************************************************************************/
#include "stdafx.h"
#include "webwindow.h"
// we'll create 2 browsers in this tutorial
webWindow Web1;
webWindow Web2;
void InitPre() {
App.name("Berkelium");
Paks.add("data/engine.pak");
D.sync(true);
}
Bool Init() {
Web1.create(Rect(-D.w(),0,D.w(),D.h()), "http://www.google.com");
Web2.create(Rect(-D.w(),-D.h(),D.w(),0), "http://attr-x.net");
Gui += Web1;
Gui += Web2;
return true;
}
void Shut() {}
Bool Update() {
if(Kb.bp(KB_ESC ))return false;
Gui.update();
return true;
}
void Draw() {
D.clear(BLACK);
Gui.draw();
}
/******************************************************************************/
/* webwindow.h: contains a struct extending a GuiImage with a browser
contains a nested class for berkelium callbacks
*/
/******************************************************************************/
struct webWindow : GuiImage {
Image imgcube;
Berkelium::Window* window;
Berkelium::Context* context;
VecI2 size;
Int wheel;
webWindow();
~webWindow();
void create(Rect& r, Str8 url);
virtual void update(GuiPC &gpc);
virtual void draw (GuiPC &pgc);
void handleEvents();
// declaration of draw function where onpaint goes
void DrawBerkelium(Berkelium::Window *win ,
const unsigned char *sourceBuffer ,
const Berkelium::Rect &sourceBufferRect ,
size_t numCopyRects ,
const Berkelium::Rect *copyRects ,
int dx ,
int dy ,
const Berkelium::Rect &scrollRect );
friend class MyDelegate;
// Berkelium callback class
class MyDelegate : public Berkelium::WindowDelegate {
webWindow * self;
public:
MyDelegate(webWindow * window) : self(window) {}
virtual void onStartLoading(Berkelium::Window *win, Berkelium::URLString newURL) {
Int i=0;
}
virtual void onPaint(Berkelium::Window *win ,
const unsigned char *sourceBuffer ,
const Berkelium::Rect &sourceBufferRect,
size_t numCopyRects ,
const Berkelium::Rect *copyRects ,
int dx ,
int dy ,
const Berkelium::Rect &scrollRect) {
self->DrawBerkelium(win,sourceBuffer,sourceBufferRect,numCopyRects,copyRects,dx,dy,scrollRect);
}
};
};
/******************************************************************************/
/* webwindow.cpp: the rest of the berkelium code and handler for key and
mouse events
*/
/******************************************************************************/
#include "stdafx.h"
#include "webwindow.h"
UInt __berkeliumWindows = 0;
UInt berkTxtBtns[][3] = {
{ KB_ENTER , 13 , 0 },
{ KB_ESC , 27 , 0 },
{ KB_DEL , 0x2E , 0 },
{ KB_NPENTER, 13 , 0 },
{ KB_BACK , (UInt)'\b', 0 }
};
UInt berkSpecBtns[][3] = {
{ KB_TAB, (UInt)'\t', 0 }
};
// DrawBerkelium, code ripped from rndbit :D
void webWindow::DrawBerkelium( Berkelium::Window *win,
const unsigned char *sourceBuffer,
const Berkelium::Rect &sourceBufferRect,
size_t numCopyRects ,
const Berkelium::Rect *copyRects ,
int dx ,
int dy ,
const Berkelium::Rect &scrollRect ) {
if(!imgcube.is()) {
imgcube.create2D(size.x,size.y,IMAGE_B8G8R8A8);
}
imgcube.lock();
unsigned char* texd = imgcube.data();
UInt tp = imgcube.pitch();
UInt tw = imgcube.x ();
UInt th = imgcube.y ();
UInt sz = tw*th*4;
// scrolling
{
Int wid = scrollRect.width ();
Int hig = scrollRect.height();
Int top = scrollRect.top ();
Int left = scrollRect.left ();
if(dy < 0) { // scroll down
for (int y = -dy; y < hig; y++) {
UInt tb = ((top + y) * tw + left) * 4;
UInt tb2 = tb + dy * tw * 4;
if (tb >= 0 && tb < sz && tb2 >= 0 && tb2 < sz)
memcpy(&texd[tb2], &texd[tb], wid * 4);
}
}
else if(dy > 0) { // scroll up
for (int y = hig - dy; y > -1; y--) {
UInt tb = ((top + y) * tw + left) * 4;
UInt tb2 = tb + dy * tw * 4;
if (tb >= 0 && tb < sz && tb2 >= 0 && tb2 < sz)
memcpy(&texd[tb2], &texd[tb], wid * 4);
}
}
if(dx != 0) { // scroll
int subx = dx > 0 ? 0 : -dx;
for (int y = 0; y < hig; y++) {
UInt tb = ((top + y) * tw + left) * 4;
UInt tb2 = tb - dx * 4;
if (tb >= 0 && tb < sz && tb2 >= 0 && tb2 < sz)
memcpy(&texd[tb], &texd[tb2], wid * 4 - subx);
}
}
}
// copy new rects
for(UInt i = 0; i < numCopyRects; i++) {
Berkelium::Rect cr = copyRects[i];
Int wid = cr.width();
Int hig = cr.height();
Int top = cr.top() - sourceBufferRect.top();
Int left = cr.left() - sourceBufferRect.left();
for(int y = 0; y < hig; y++) {
UInt tb = ((cr.top() + y) * tp + cr.left()* 4) ;
UInt tb2 = (left + (y + top) * sourceBufferRect.width()) * 4;
memcpy(&texd[tb], &sourceBuffer[tb2], wid * 4);
}
}
imgcube.unlock();
}
webWindow::webWindow() {
window = NULL;
context = NULL;
}
webWindow::~webWindow() {
window->destroy();
context->destroy();
__berkeliumWindows--;
if (__berkeliumWindows == 0) {
Berkelium::destroy();
}
}
void webWindow::create(Rect& r, Str8 url) {
size = D.screenToPixel(r.rd()) - D.screenToPixel(r.lu());
// only initialize on first window
if (__berkeliumWindows == 0) {
Berkelium::init(Berkelium::FileString::empty());
}
__berkeliumWindows++;
context = Berkelium::Context::create();
window = Berkelium::Window::create(context);
window->resize (size.x, size.y );
window->setDelegate( new MyDelegate(this) ); // set callback class
window->focus ( );
window->navigateTo (url(), url.length() );
super::create(r, &imgcube);
}
void webWindow::update(GuiPC &gpc) {
Berkelium::update();
handleEvents();
super::update(gpc);
}
void webWindow::draw(GuiPC &gpc) {
super::draw(gpc);
}
void webWindow::handleEvents() {
if (Cuts(Ms.pos(), T.rect)) {
// send mouse position
VecI2 pos = D.screenToPixel(Ms.pos()) - D.screenToPixel(T.pos());
window->mouseMoved(pos.x, pos.y);
// send mouse clicks and activate object if clicked
if(Ms.b(0)) {
window->mouseButton(0, true);
T.activate();
}
if(Ms.b(1)) {
window->mouseButton(1, true);
T.activate();
}
if(Ms.br(0)) window->mouseButton(0, false);
if(Ms.br(1)) window->mouseButton(1, false);
// send mouse wheel
if (Ms.wheel()!= 0) {
wheel = Ms.wheel() * 20;
window->mouseWheel(0, wheel);
} else {
//smooth mouse wheel
if (wheel > 0) wheel--;
else if (wheel < 0) wheel++;
window->mouseWheel(0, wheel);
}
}
// send keys if this object has keyboard focus
int mods = 0;
static UInt kbRepeatTimeout = 300;
if (Gui.ms() == this) {
while (const Char8 c = Kb.c()) {
if (c == ' ' || c == 127 || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') {
window->keyEvent(true, mods, c, 0);
}
Char outchars[2] = { c, 0};
window->textEvent(outchars, 1);
Kb.nextBufferedChar();
}
for (U32 i = 0; i < Elms(berkTxtBtns); i++) {
Bool bp = Kb.bp((KB_BUTTON)berkTxtBtns[i][0]);
UInt timeDiff = Time.curTimeMs() - berkTxtBtns[i][2];
if (bp || (Kb.b((KB_BUTTON)berkTxtBtns[i][0]) && timeDiff > kbRepeatTimeout)) {
if (!bp || timeDiff < 100) kbRepeatTimeout = 30;
else kbRepeatTimeout = 300;
window->keyEvent(true, mods, berkTxtBtns[i][1], 0);
Char outchars[2] = {berkTxtBtns[i][1], 0 };
window->textEvent(outchars, 1);
berkTxtBtns[i][2] = Time.curTimeMs();
}
}
for (U32 i = 0; i < Elms(berkSpecBtns); i++) {
Bool bp = Kb.bp((KB_BUTTON)berkSpecBtns[i][0]);
UInt timeDiff = Time.curTimeMs() - berkSpecBtns[i][2];
if (bp || (Kb.b((KB_BUTTON)berkSpecBtns[i][0]) && timeDiff > kbRepeatTimeout)) {
if (!bp || timeDiff < 100) kbRepeatTimeout = 30;
else kbRepeatTimeout = 300;
window->keyEvent(true, mods, berkSpecBtns[i][1], 0);
}
}
Kb.eat();
}
}