From f9e72e31411e47a5a887f62c97f3d0562d33fb92 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Wed, 9 Nov 2005 02:26:56 +0000 Subject: [PATCH] New GUI code --- Makefile | 2 +- box.cc | 49 ++++--- box.h | 12 +- command.cc | 2 +- main.cc | 2 +- message.h | 27 ++-- osd.cc | 14 +- osd.h | 5 +- region.cc | 88 ++++++++++++ region.h | 23 ++++ surface.cc | 51 ++----- surface.h | 10 +- vchannellist.cc | 2 +- view.cc | 17 +-- viewman.cc | 340 +++++++++++++++++++++++++++++----------------- viewman.h | 17 ++- vlivebanner.cc | 8 +- vrecordinglist.cc | 10 +- vrecordingmenu.cc | 2 +- vserverselect.cc | 2 +- vvideolive.cc | 2 +- vwelcome.cc | 2 +- widget.cc | 6 +- wjpeg.cc | 16 +-- wselectlist.cc | 6 +- 25 files changed, 443 insertions(+), 272 deletions(-) create mode 100644 region.cc create mode 100644 region.h diff --git a/Makefile b/Makefile index 2ab18e5..d3ed82b 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ OBJECTS = main.o command.o log.o remote.o led.o mtd.o video.o audio.o tcp.o dire recording.o channel.o message.o playervideo.o playerradio.o messagequeue.o \ view.o vinfo.o vwallpaper.o vvolume.o vrecordinglist.o vlivebanner.o vmute.o \ vrecordingmenu.o vquestion.o vchannellist.o vwelcome.o vvideolive.o vvideorec.o vradiolive.o \ - vchannelselect.o vserverselect.o colour.o vconnect.o voptions.o \ + vchannelselect.o vserverselect.o colour.o vconnect.o voptions.o region.o \ widget.o wselectlist.o wjpeg.o wsymbol.o wbutton.o woptionbox.o i18n.o \ fonts/helvB24.o fonts/helvB18.o diff --git a/box.cc b/box.cc index dc28da5..ef441a4 100644 --- a/box.cc +++ b/box.cc @@ -24,11 +24,11 @@ char Box::numBoxes = 0; Box::Box() { - height = 0; - width = 0; + area.x = 0; + area.y = 0; + area.w = 0; + area.h = 0; - screenX = 0; - screenY = 0; offsetX = 0; offsetY = 0; @@ -50,8 +50,8 @@ void Box::draw() void Box::setScreenPos(int x, int y) { - screenX = x; - screenY = y; + area.x = x; + area.y = y; } void Box::setSurfaceOffset(UINT x, UINT y) @@ -60,38 +60,53 @@ void Box::setSurfaceOffset(UINT x, UINT y) offsetY = y; } -void Box::show(int noBufferToScreen) +void Box::show() { - Log::getInstance()->log("Box", Log::DEBUG, "Show data %p %u %u %u %u %u", surface, screenX, screenY, width, height, noBufferToScreen); - surface->updateToBuffer(screenX, screenY, width, height); - if (!noBufferToScreen) Surface::bufferToScreen(screenX, screenY, width, height); + show(area); +} + +void Box::show(Region& r) +{ + Log::getInstance()->log("Box", Log::DEBUG, "Show region %p %u %u %u %u", surface, r.x, r.y, r.w, r.h); +// surface->updateToScreen(area.x, area.y, area.w, area.h); + + /* surface update to screen needs: + source x distance into this surface + source y distance into this surface + width of update + height of update + destination x on screen + destination y on screen + */ + + surface->updateToScreen(r.x - area.x, r.y - area.y, r.w, r.h, r.x, r.y); } int Box::getScreenX() { - return screenX; + return area.x; } int Box::getScreenY() { - return screenY; + return area.y; } int Box::getWidth() { - return width; + return area.w; } int Box::getHeight() { - return height; + return area.h; } // Level 1 drawing functions void Box::fillColour(Colour& colour) { - rectangle(0, 0, width, height, colour); + rectangle(0, 0, area.w, area.h, colour); } void Box::drawPara(char* text, int x, int y, Colour& colour) @@ -127,7 +142,7 @@ void Box::drawPara(char* text, int x, int y, Colour& colour) } thisCharWidth = surface->getCharWidth(text[textPos]); - if ((lineWidth + thisCharWidth) > (int)(width - (2 * paraMargin))) + if ((lineWidth + thisCharWidth) > (int)(area.w - (2 * paraMargin))) { // this character would break the right margin if (text[textPos] == ' ') @@ -159,7 +174,7 @@ void Box::drawPara(char* text, int x, int y, Colour& colour) { drawText(line, x, ypos, colour); ypos += lineHeight; - if (ypos > (int)(height - lineHeight)) break; + if (ypos > (int)(area.h - lineHeight)) break; } else { diff --git a/box.h b/box.h index 8f48056..cbefd60 100644 --- a/box.h +++ b/box.h @@ -26,6 +26,7 @@ #include "log.h" #include "colour.h" #include "surface.h" +#include "region.h" // Abstract ??????? class Box @@ -37,7 +38,8 @@ class Box void setScreenPos(int x, int y); void setSurfaceOffset(UINT x, UINT y); - void show(int noBufferToScreen = 0); + void show(); + void show(Region& r); virtual void draw(); @@ -56,15 +58,21 @@ class Box int getWidth(); int getHeight(); + // so viewman can read it: + Region area; + Surface* surface; // temp - is there a get function for this? FIXME private: protected: - Surface* surface; + + +/* UINT width; UINT height; int screenX; int screenY; +*/ UINT offsetX; UINT offsetY; diff --git a/command.cc b/command.cc index d30729c..ee9cf36 100644 --- a/command.cc +++ b/command.cc @@ -253,7 +253,7 @@ void Command::doJustConnected(VConnect* vconnect) { I18n::Initialize(); Video* video = Video::getInstance(); - viewman->removeView(vconnect, 0, 1); + viewman->removeView(vconnect, 0); VInfo* vi = new VInfo(); vi->create(400, 200); diff --git a/main.cc b/main.cc index 333d63f..a4e1bfe 100644 --- a/main.cc +++ b/main.cc @@ -206,7 +206,7 @@ int main(int argc, char** argv) shutdown(1); } - success = osd->init("/dev/stbgfx", 1); + success = osd->init("/dev/stbgfx"); if (success) { logger->log("Core", Log::INFO, "OSD module initialised"); diff --git a/message.h b/message.h index fafb3c4..2624faa 100644 --- a/message.h +++ b/message.h @@ -41,20 +41,19 @@ class Message const static ULONG CLOSE_ME = 2; const static ULONG PLAY_SELECTED_RECORDING = 3; const static ULONG DELETE_SELECTED_RECORDING = 4; - const static ULONG UPDATE_SCREEN = 5; - const static ULONG SWAP_ME_FOR = 6; - const static ULONG CHANNEL_CHANGE = 7; - const static ULONG RESUME_SELECTED_RECORDING = 8; - const static ULONG STANDBY = 9; - const static ULONG STOP_PLAYBACK = 10; - const static ULONG SERVER_SELECTED = 11; - const static ULONG VDR_CONNECTED = 12; - const static ULONG REDRAW_DATA = 13; - const static ULONG ADD_VIEW = 14; - const static ULONG CHANNEL_UP = 15; - const static ULONG CHANNEL_DOWN = 16; - const static ULONG STREAM_END = 17; - const static ULONG CHILD_CLOSE = 18; + const static ULONG SWAP_ME_FOR = 5; + const static ULONG CHANNEL_CHANGE = 6; + const static ULONG RESUME_SELECTED_RECORDING = 7; + const static ULONG STANDBY = 8; + const static ULONG STOP_PLAYBACK = 9; + const static ULONG SERVER_SELECTED = 10; + const static ULONG VDR_CONNECTED = 11; + const static ULONG REDRAW_DATA = 12; + const static ULONG ADD_VIEW = 13; + const static ULONG CHANNEL_UP = 14; + const static ULONG CHANNEL_DOWN = 15; + const static ULONG STREAM_END = 16; + const static ULONG CHILD_CLOSE = 17; }; #endif diff --git a/osd.cc b/osd.cc index 71190f0..751b858 100644 --- a/osd.cc +++ b/osd.cc @@ -30,7 +30,6 @@ Osd::Osd() fdOsd = 0; screen = NULL; - buffer = NULL; } Osd::~Osd() @@ -50,7 +49,7 @@ int Osd::getFD() return fdOsd; } -int Osd::init(char* device, int doubleBuffering) +int Osd::init(char* device) { if (initted) return 0; @@ -71,16 +70,6 @@ int Osd::init(char* device, int doubleBuffering) screen->create(video->getScreenWidth(), video->getScreenHeight()); screen->display(); - if (doubleBuffering) - { - buffer = new Surface(Surface::BUFFER); - buffer->create(video->getScreenWidth(), video->getScreenHeight()); - } - else - { - Surface::disableBuffer(); - } - return 1; } @@ -88,7 +77,6 @@ int Osd::shutdown() { if (!initted) return 0; initted = 0; - if (buffer) delete buffer; delete screen; close(fdOsd); return 1; diff --git a/osd.h b/osd.h index aae8605..cc258ed 100644 --- a/osd.h +++ b/osd.h @@ -37,7 +37,7 @@ class Osd ~Osd(); static Osd* getInstance(); - int init(char* device, int doubleBuffering); + int init(char* device); int shutdown(); int getFD(); @@ -47,10 +47,7 @@ class Osd private: static Osd* instance; int initted; - Surface* screen; - Surface* buffer; - int fdOsd; }; diff --git a/region.cc b/region.cc new file mode 100644 index 0000000..f92326f --- /dev/null +++ b/region.cc @@ -0,0 +1,88 @@ +#include "region.h" + +Region::Region() +{ + x = 0; + y = 0; + w = 0; + h = 0; + z = 0; +} + +bool Region::overlappedBy(Region& d) +{ + return + ( (d.x2() >= x) && + (d.x <= x2()) && + (d.y <= y2()) && + (d.y2() >= y) ); +} + +UINT Region::x2() +{ + return x + w - 1; +} + +UINT Region::y2() +{ + return y + h - 1; +} +/* +Region Region::subtract(Region& other) +{ + printf("This: %i %i %i %i\n", x, y, w, h); + printf("Subtract this: %i %i %i %i\n", other.x, other.y, other.w, other.h); + + + Region s; + + if (x < other.x) + { + printf("Case 1\n"); + s.x = x; + s.y = y; + s.w = other.x - x; + s.h = h; + } + else if (x2() > other.x2()) + { + printf("Case 2\n"); + s.x = other.x2()+1; + s.y = y; + s.w = w - s.x; + s.h = h; + } + else if (y < other.y) + { + printf("Case 3\n"); + s.x = x; + s.y = y; + s.w = w; + s.h = other.y - y; + } + else if (y2() > other.y2()) + { + printf("Case 4\n"); + s.x = x; + s.y = other.y2()+1; + s.w = w; + s.h = h - s.y; + } + else + { + s.x = 0; + s.y = 0; + s.w = 0; + s.h = 0; + } + printf("Result: %i %i %i %i\n", s.x, s.y, s.w, s.h); + + return s; +} +*/ + + //i.x = (x >= other.x ? x : other.x); + //i.y = (y >= other.y ? y : other.y); + //i.w = (x2() <= other.x2() ? x2() : other.x2()) - i.x; + //i.h = (y2() <= other.y2() ? y2() : other.y2()) - i.y; + //return i; diff --git a/region.h b/region.h new file mode 100644 index 0000000..3d98406 --- /dev/null +++ b/region.h @@ -0,0 +1,23 @@ +#ifndef REGION_H +#define REGION_H + +#include +#include "defines.h" + +class Region +{ + public: + Region(); + bool overlappedBy(Region& doesthisOverlap); +// Region subtract(Region& other); + UINT x2(); + UINT y2(); + + UINT x; + UINT y; + UINT w; + UINT h; + int z; +}; + +#endif diff --git a/surface.cc b/surface.cc index 13af55e..9f6c54e 100644 --- a/surface.cc +++ b/surface.cc @@ -23,14 +23,11 @@ #include "osd.h" Surface* Surface::screen = NULL; -Surface* Surface::buffer = NULL; -int Surface::disableDoubleBuffering = 0; osd_font_t* Surface::font = &font_helvB18; Surface::Surface(int id) { if (id == SCREEN) screen = this; - if (id == BUFFER) buffer = this; fdOsd = Osd::getInstance()->getFD(); memset(&surface, 0, sizeof(osd_surface_t)); @@ -55,17 +52,9 @@ Surface::~Surface() } -void Surface::disableBuffer() +Surface* Surface::getScreen() { - disableDoubleBuffering = 1; -} - -Surface* Surface::getObject(int id) -{ - if (id == SCREEN) return screen; - if (disableDoubleBuffering) return screen; - if (id == BUFFER) return buffer; - return NULL; + return screen; } int Surface::create(UINT width, UINT height) @@ -282,36 +271,18 @@ void Surface::drawVertLine(int x, int y1, int y2, unsigned int c) fillblt(x, y1, 1, y2-y1, c); } -void Surface::bufferToScreen() // static, this is for Box::showAll -{ - if (disableDoubleBuffering) return; - - Log::getInstance()->log("Surface", Log::DEBUG, "Full buffer to screen"); - bufferToScreen(0, 0, buffer->surface.sfc.width, buffer->surface.sfc.height); -} -//int Surface::updateToScreen(int x, int y, int width, int height) // main method for all normal windows -//{ - /* - With double buffering: - A view has buffer for its surface. this is buffer, copy area specified to screen - Without double buffering: - A view has screen for its surface. this is screen, all painting work has already been done. ignore + /* surface update to screen needs: + source x distance into this surface + source y distance into this surface + width of update + height of update + destination x on screen + destination y on screen */ - -// if (this == screen) return 0; -// -// return blt(fdOsd, surface.sfc.handle, x, y, width, height, screen->getSurfaceHandle(), x, y); -//} - -int Surface::bufferToScreen(int x, int y, int width, int height) // static -{ - return blt(Osd::getInstance()->getFD(), buffer->getSurfaceHandle(), x, y, width, height, screen->getSurfaceHandle(), x, y); -} - -int Surface::updateToBuffer(int x, int y, int width, int height) // main method for all normal windows +int Surface::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME { - return blt(fdOsd, surface.sfc.handle, 0, 0, width, height, buffer->getSurfaceHandle(), x, y); + return blt(fdOsd, surface.sfc.handle, sx, sy, w, h, screen->getSurfaceHandle(), dx, dy); } int Surface::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy) diff --git a/surface.h b/surface.h index 1b5dfa4..ac11deb 100644 --- a/surface.h +++ b/surface.h @@ -170,8 +170,7 @@ class Surface Surface(int id = 0); ~Surface(); - static Surface* getObject(int id); - static int bufferToScreen(int x, int y, int width, int height); + static Surface* getScreen(); static int getFontHeight(); int create(UINT width, UINT height); @@ -182,7 +181,8 @@ class Surface void drawPixel(int x, int y, unsigned int c); void drawHorzLine(int x1, int x2, int y, unsigned int c); void drawVertLine(int x, int y1, int y2, unsigned int c); - int updateToBuffer(int x, int y, int width, int height); + int updateToScreen(int sx, int sy, int w, int h, int dx, int dy); + int drawText(char* text, int x, int y, int r, int g, int b); int drawTextRJ(char* text, int x, int y, int r, int g, int b); int getCharWidth(char c); @@ -192,8 +192,6 @@ class Surface static void initConversionTables(); - static void disableBuffer(); - static void bufferToScreen(); static int blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy); const static int SCREEN = 1; @@ -216,8 +214,6 @@ class Surface private: static Surface* screen; - static Surface* buffer; - static int disableDoubleBuffering; static osd_font_t* font; int fdOsd; diff --git a/vchannellist.cc b/vchannellist.cc index 50f0312..82d0e05 100644 --- a/vchannellist.cc +++ b/vchannellist.cc @@ -48,7 +48,7 @@ VChannelList::VChannelList(ULONG type) sl.setSurface(surface); sl.setSurfaceOffset(10, 30 + 5); - sl.setDimensions(width - 20, height - 30 - 15 - 30); + sl.setDimensions(area.w - 20, area.h - 30 - 15 - 30); } VChannelList::~VChannelList() diff --git a/view.cc b/view.cc index 33c5420..c0e348d 100644 --- a/view.cc +++ b/view.cc @@ -24,11 +24,6 @@ char View::numViews = 0; View::View() { - width = 0; - height = 0; - screenX = 0; - screenY = 0; - delSec = 0; delNSec = 0; seconds = 0; @@ -56,11 +51,11 @@ View::~View() bool View::create(UINT w, UINT h) { - width = w; - height = h; + area.w = w; + area.h = h; surface = new Surface(); - return surface->create(width, height); + return surface->create(area.w, area.h); } void View::setTitleText(char* takeText) @@ -75,8 +70,8 @@ void View::draw() if (borderOn) { - rectangle(0, 0, width, height, titleBarColour); - rectangle(5, 5, width-10, height-10, backgroundColour); + rectangle(0, 0, area.w, area.h, titleBarColour); + rectangle(5, 5, area.w-10, area.h-10, backgroundColour); } else { @@ -85,7 +80,7 @@ void View::draw() if (titleBarOn) { - rectangle(0, 0, width, 30, titleBarColour); + rectangle(0, 0, area.w, 30, titleBarColour); if (titleText) drawText(titleText, 5, 5, Colour::LIGHTTEXT); } } diff --git a/viewman.cc b/viewman.cc index 8840d86..6619f5b 100644 --- a/viewman.cc +++ b/viewman.cc @@ -27,7 +27,7 @@ ViewMan::ViewMan() if (instance) return; instance = this; initted = 0; - topView = 0; + numViews = 0; resetThreadFlag = 0; autoDeleteThreadRun = 0; callFromThread = 0; @@ -73,12 +73,11 @@ int ViewMan::shutdown() int ViewMan::add(View* v) { if (!initted) return 0; - if (topView == 10) return 0; + if (numViews == 20) return 0; pthread_mutex_lock(&viewManLock); - topView++; - views[topView] = v; + views[numViews++] = v; resetThread(); pthread_mutex_unlock(&viewManLock); @@ -89,10 +88,9 @@ int ViewMan::add(View* v) int ViewMan::addNoLock(View* v) { if (!initted) return 0; - if (topView == 10) return 0; + if (numViews == 20) return 0; - topView++; - views[topView] = v; + views[numViews++] = v; resetThread(); @@ -102,40 +100,32 @@ int ViewMan::addNoLock(View* v) // ---------------------------------------------------- REMOVE CODE -int ViewMan::removeView(View* toDelete, int noLock, int noShow) +int ViewMan::removeView(View* toDelete, int noLock) { if (!initted) return 0; - if (topView == 0) return 0; + if (numViews == 0) return 0; if (!noLock) pthread_mutex_lock(&viewManLock); - Log::getInstance()->log("ViewMan", Log::DEBUG, "entering remove, %u topview", topView); + Log::getInstance()->log("ViewMan", Log::DEBUG, "entering remove, numViews=%i", numViews); int i; - int wasTopView = 0; - int slotTakenFrom = 0; if (toDelete == NULL) { - toDelete = views[topView]; - i = topView; - wasTopView = 1; + toDelete = views[numViews-1]; + i = numViews - 1; } else { // to be deleted view is more likely to be at the top - - - for (i = topView; i > 0; i--) + for (i = numViews-1; i >= 0; i--) { - if (views[i] == toDelete) - { - if (i == topView) wasTopView = 1; - break; - } + Log::getInstance()->log("ViewMan", Log::DEBUG, "todel: %p, i=%i, views[i]=%p", toDelete, i, views[i]); + if (views[i] == toDelete) break; } - if (i == 0) + if (i == -1) { // not a View we have! if (!noLock) pthread_mutex_unlock(&viewManLock); @@ -143,117 +133,227 @@ int ViewMan::removeView(View* toDelete, int noLock, int noShow) } } - // Save the position we are deleting the view from - slotTakenFrom = i; + Log::getInstance()->log("ViewMan", Log::DEBUG, "Starting deleteView"); + deleteView(i); + Log::getInstance()->log("ViewMan", Log::DEBUG, "Done deleteView"); // Shift the views on top down one - for(; i < topView; i++) - { - views[i] = views[i + 1]; - } - topView--; + --numViews; + for(int j = i; j < numViews; j++) views[j] = views[j+1]; - // Done. Now on to drawing. + // Delete the view + delete toDelete; - View* newTopBox = views[topView]; // just to make second optimisation easier + resetThread(); + if (!noLock) pthread_mutex_unlock(&viewManLock); + + return 1; +} + +///////////////////////////////////////////////////////////////////////////// +// NEW STUFF +///////////////////////////////////////////////////////////////////////////// - // First optimisation. If there are no views left, don't do anything! - if (topView == 0) +void ViewMan::deleteView(int z) +{ + Log::getInstance()->log("ViewMan", Log::DEBUG, "Delete view %i of %i", z, numViews); + RegionList rl; + boxSplit(views[z]->area, z + 1, numViews, 1, rl); + while(!rl.empty()) { - Log::getInstance()->log("ViewMan", Log::DEBUG, "re-draw using optimisation 1"); + repaintRevealed(z, rl.front()); + rl.pop_front(); } +} + +/* For later... +void ViewMan::update(int z) +{ + // get the region for the whole view, could be less than that + // for smaller updates - // second optimisation. if view being deleted is entirely within the view underneath it, - // and was the top most box, - // only need to redraw the one underneath - else if ( wasTopView - && (toDelete->getScreenX() >= newTopBox->getScreenX()) - && (toDelete->getScreenY() >= newTopBox->getScreenY()) - && ((toDelete->getScreenX() + toDelete->getWidth()) <= (newTopBox->getScreenX() + newTopBox->getWidth())) - && ((toDelete->getScreenY() + toDelete->getHeight()) <= (newTopBox->getScreenY() + newTopBox->getHeight())) - ) + Region r = views[z]->area; + RegionList rl; + + r.y += 10; + + Region r2; + boxSplit(r, z+1, numViews, 1, rl); + while(!rl.empty()) { - newTopBox->show(); - Log::getInstance()->log("ViewMan", Log::DEBUG, "re-draw using optimisation 2"); + r2 = rl.front(); + r2.z = z; + views[z]->show(r2); + rl.pop_front(); } +} +*/ + +void ViewMan::repaintRevealed(int x, Region r) +{ + RegionList rl; + boxSplit(r, x - 1, -1, -1, rl); - // third optimisation. if the box being deleted is totally within one above it, don't do anything - else if ((slotTakenFrom <= topView) && isTotallyCovered(toDelete, slotTakenFrom)) + Region r2; + while(!rl.empty()) { - Log::getInstance()->log("ViewMan", Log::DEBUG, "re-draw using optimisation 3"); + r2 = rl.front(); + views[r2.z]->show(r2); + rl.pop_front(); } +} - // no optimisations left, redo everything. - else +void ViewMan::boxSplit(Region r, int start, int end, int direction, RegionList& rl) +{ +// printf("Y= S=%i E=%i D=%i: Boxsplit: %i %i %i %i\n", start, end, direction, r.x, r.y, r.w, r.h); + + for(int z = start; z != end; z += direction) { - for (int j = 1; j <= topView; j++) + if (r.overlappedBy(views[z]->area)) { - views[j]->show(1); - } - if (!noShow) Surface::bufferToScreen(); +// printf("Z=%i S=%i E=%i D=%i: %i overlaps\n", z, start, end, direction, z); - Log::getInstance()->log("ViewMan", Log::DEBUG, "re-draw using no optimisation"); - } + int top = r.y; + int btm = r.y2(); - // Delete the view - delete toDelete; + if (views[z]->area.y > r.y) + { +// printf("Z=%i S=%i E=%i D=%i: Case 1 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, views[z]->area.x, views[z]->area.y, views[z]->area.w, views[z]->area.h); + top = views[z]->area.y; + Region newR; + newR.x = r.x; + newR.y = r.y; + newR.w = r.w; + newR.h = views[z]->area.y - r.y; + boxSplit(newR, z + direction, end, direction, rl); + + if (direction == -1) + { + Region newR2; + newR2.x = r.x; + newR2.y = views[z]->area.y; + newR2.w = r.w; + newR2.h = r.h - newR.h; + boxSplit(newR2, z, end, -1, rl); + return; + } + } - resetThread(); - if (!noLock) pthread_mutex_unlock(&viewManLock); + if (views[z]->area.y2() < r.y2()) + { +// printf("Z=%i S=%i E=%i D=%i: Case 2 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, views[z]->area.x, views[z]->area.y, views[z]->area.w, views[z]->area.h); + btm = views[z]->area.y2(); + Region newR; + newR.x = r.x; + newR.y = views[z]->area.y2() + 1; + newR.w = r.w; + newR.h = r.y2() - newR.y + 1; + boxSplit(newR, z + direction, end, direction, rl); + + if (direction == -1) + { + Region newR2; + newR2.x = r.x; + newR2.y = r.y; + newR2.w = r.w; + newR2.h = r.h - newR.h; + boxSplit(newR2, z, end, -1, rl); + return; + } + } - return 1; -} + if (views[z]->area.x > r.x) + { +// printf("Z=%i S=%i E=%i D=%i: Case 3 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, views[z]->area.x, views[z]->area.y, views[z]->area.w, views[z]->area.h); + Region newR; + newR.x = r.x; + newR.y = top; + newR.w = views[z]->area.x - r.x; + newR.h = btm - top + 1; + boxSplit(newR, z + direction, end, direction, rl); + + if (direction == -1) + { + Region newR2; + newR2.x = r.x + newR.w; + newR2.y = r.y; + newR2.w = r.w - newR.w; + newR2.h = r.h; + boxSplit(newR2, z, end, -1, rl); + return; + } + } -int ViewMan::isTotallyCovered(View* toDelete, int slotTakenFrom) -{ - int todelx1 = toDelete->getScreenX(); - int todelx2 = toDelete->getScreenX() + toDelete->getWidth(); - int todely1 = toDelete->getScreenY(); - int todely2 = toDelete->getScreenY() + toDelete->getHeight(); - - int x1 = 999999; - int x2 = 0; - int y1 = 999999; - int y2 = 0; - - int currentx1; - int currentx2; - int currenty1; - int currenty2; - - for (int i = slotTakenFrom; i <= topView; i++) - { - currentx1 = views[i]->getScreenX(); - currentx2 = currentx1 + views[i]->getWidth(); - currenty1 = views[i]->getScreenY(); - currenty2 = currenty1 + views[i]->getHeight(); + if (views[z]->area.x2() < r.x2()) + { +// printf("Z=%i S=%i E=%i D=%i: Case 4 for %i %i %i %i split by %i: %i %i %i %i\n", z, start, end, direction, r.x, r.y, r.w, r.h, z, views[z]->area.x, views[z]->area.y, views[z]->area.w, views[z]->area.h); + Region newR; + newR.x = views[z]->area.x2() + 1; + newR.y = top; + newR.w = r.x2() - newR.x + 1; + newR.h = btm - top + 1; + boxSplit(newR, z + direction, end, direction, rl); + + if (direction == -1) + { + Region newR2; + newR2.x = r.x; + newR2.y = r.y; + newR2.w = r.w - newR.w; + newR2.h = r.h; + boxSplit(newR2, z, end, -1, rl); + return; + } + } -// printf("Iteration in tc before. i=%i x1=%i x2=%i y1=%i y2=%i cx1=%i cx2=%i cy1=%i cy2=%i\n", i, x1, x2, y1, y2, currentx1, currentx2, currenty1, currenty2); + if (direction == -1) + { + // we are going down the stack + // r is underlapped by views[z] + // but we have not split + // Therefore this region under test is + // completely covering views[z] - if (currentx1 < x1) x1 = currentx1; - if (currentx2 > x2) x2 = currentx2; - if (currenty1 < y1) y1 = currenty1; - if (currenty2 > y2) y2 = currenty2; + // don't go any further down, generate a region and quit -// printf("Iteration in tc after . i=%i x1=%i x2=%i y1=%i y2=%i\n", i, x1, x2, y1, y2); +// printf("Repaint region: %i %i %i %i\n", r.x, r.y, r.w, r.h); + r.z = z; + rl.push_front(r); + } + +// printf("Returning from Z=%i\n", z); + return; + } + else + { +// printf("Z=%i S=%i E=%i D=%i: %i does not overlap\n", z, start, end, direction, z); + } } - // k, now x1 x2 y1 y2 contain the dimensions of the biggest box over the deleted slot + // if direction = 1 then we have come to a region that is + // entirely clear of higher views and needs to be redrawn - if ( (x1 <= todelx1) - && (x2 >= todelx2) - && (y1 <= todely1) - && (y2 >= todely2) - ) - { - return 1; - } - else + // if direction = -1 then we have come to a region that is on + // the very bottom with nothing below it to repaint. + // do nothing. stale window data will be left on screen? + + if (direction == 1) { - return 0; + rl.push_front(r); } } +// TEMP +void ViewMan::drawBlack(Region& r) +{ + Surface* surface = Surface::getScreen(); + surface->fillblt(r.x, r.y, r.w, r.h, surface->rgba(0, 0, 0, 255)); +} + +///////////////////////////////////////////////////////////////////////////// +// END NEW STUFF +///////////////////////////////////////////////////////////////////////////// + // ---------------------------------------------------- END OF REMOVE CODE @@ -261,14 +361,13 @@ void ViewMan::removeAll() { pthread_mutex_lock(&viewManLock); - // FIXME for don't delete wallpaper cos surface destroy doesn't work - - for (; topView > 1; topView--) + // 1.. Don't delete wallpaper. No point. + for (; numViews > 1; --numViews) { - delete views[topView]; + delete views[numViews-1]; } - Surface::bufferToScreen(); +// Surface::bufferToScreen(); resetThread(); pthread_mutex_unlock(&viewManLock); @@ -284,15 +383,15 @@ int ViewMan::handleCommand(UCHAR command) if (command != Remote::NA_NONE) { - // handle command return values // 0 - drop through to next view // 1 - dont drop to next view, but not handled // 2 - handled - stop command here // 4 - handled - delete this view - for (i=topView; i>0; i--) + for (i=numViews-1; i>=0; i--) { + Log::getInstance()->log("ViewMan", Log::DEBUG, "Giving command to i=%i", i); retVal = views[i]->handleCommand(command); if (retVal == 1) { @@ -321,6 +420,7 @@ int ViewMan::handleCommand(UCHAR command) // removeNoLock(views[i]); // Box::showAll(); // resetThread(); + Log::getInstance()->log("ViewMan", Log::DEBUG, "Return 4: i=%i, views[i]=%p", i, views[i]); removeView(views[i], 1); pthread_mutex_unlock(&viewManLock); retVal2 = 1; @@ -346,7 +446,7 @@ void ViewMan::processMessage(Message* m) { if (m->to != this) { - for (int i = topView; i > 0; i--) + for (int i = numViews-1; i >= 0; i--) { if (views[i] == m->to) { @@ -364,22 +464,17 @@ void ViewMan::processMessage(Message* m) { case Message::CLOSE_ME: { - removeView((View*)m->from, 1, 1); - break; - } - case Message::UPDATE_SCREEN: - { - Surface::bufferToScreen(); + removeView((View*)m->from, 1); break; } case Message::SWAP_ME_FOR: { View* toReplace = (View*) m->parameter; - removeView((View*)m->from, 1, 1); + removeView((View*)m->from, 1); - topView++; - views[topView] = toReplace; + views[numViews] = toReplace; + ++numViews; if (toReplace->seconds) { struct timespec currentTime; @@ -389,7 +484,6 @@ void ViewMan::processMessage(Message* m) } toReplace->draw(); toReplace->show(); - Surface::bufferToScreen(); resetThread(); break; } @@ -489,7 +583,7 @@ void ViewMan::startAutoDeleteThread3() nextTime.tv_nsec = 0; nextToDelete = NULL; - for(int i = 1; i <= topView; i++) + for(int i = 0; i < numViews; i++) { if ((views[i]->delSec > 0) && (views[i]->delNSec > 0)) { diff --git a/viewman.h b/viewman.h index 40da740..8399445 100644 --- a/viewman.h +++ b/viewman.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "defines.h" #include "view.h" @@ -32,6 +33,9 @@ #include "messagequeue.h" #include "remote.h" #include "surface.h" +#include "region.h" + +typedef slist RegionList; class ViewMan : public MessageQueue { @@ -46,7 +50,7 @@ class ViewMan : public MessageQueue // All these reset the thread int add(View* v); int addNoLock(View* v); - int removeView(View* toRemove = NULL, int noLock = 0, int noShow = 0); + int removeView(View* toRemove = NULL, int noLock = 0); void removeAll(); int handleCommand(UCHAR command); @@ -56,13 +60,11 @@ class ViewMan : public MessageQueue void startAutoDeleteThread3(); private: - int isTotallyCovered(View* toDelete, int slotTakenFrom); - static ViewMan* instance; int initted; - View* views[11]; - UCHAR topView; + View* views[20]; + int numViews; // Threading stuff @@ -77,6 +79,11 @@ class ViewMan : public MessageQueue void processMessage(Message* m); + // New windowing stuff + void deleteView(int z); + void repaintRevealed(int x, Region r); + void boxSplit(Region r, int start, int end, int direction, RegionList& rl); + void drawBlack(Region& r); }; #endif diff --git a/vlivebanner.cc b/vlivebanner.cc index 6398730..8c7cc9b 100644 --- a/vlivebanner.cc +++ b/vlivebanner.cc @@ -42,7 +42,7 @@ VLiveBanner::VLiveBanner(View* tparent, Channel* channel) sl.setSurface(surface); sl.setSurfaceOffset(0, 30); - sl.setDimensions(width, height - 60); + sl.setDimensions(area.w, area.h - 60); sl.setNoLoop(); setChannel(channel); @@ -115,10 +115,10 @@ void VLiveBanner::draw() { View::draw(); sl.draw(); - rectangle(0, height - 30, width, 30, titleBarColour); + rectangle(0, area.h - 30, area.w, 30, titleBarColour); - rectangle(7, height - 24, 18, 16, Colour::RED); - drawText(tr("info"), 32, height - 25, Colour::LIGHTTEXT); + rectangle(7, area.h - 24, 18, 16, Colour::RED); + drawText(tr("info"), 32, area.h - 25, Colour::LIGHTTEXT); } int VLiveBanner::handleCommand(int command) diff --git a/vrecordinglist.cc b/vrecordinglist.cc index 5cce73c..c0b5443 100644 --- a/vrecordinglist.cc +++ b/vrecordinglist.cc @@ -41,7 +41,7 @@ VRecordingList::VRecordingList(VRecordingList* tparent) sl.setSurface(surface); sl.setSurfaceOffset(10, 30 + 5); - sl.setDimensions(width - 20, height - 30 - 15 - 30); + sl.setDimensions(area.w - 20, area.h - 30 - 15 - 30); } VRecordingList::~VRecordingList() @@ -284,14 +284,6 @@ void VRecordingList::doDeleteSelected() } show(); - -/* - Message* m2 = new Message(); - m2->from = this; - m2->to = ViewMan::getInstance(); - m2->message = Message::UPDATE_SCREEN; - ViewMan::getInstance()->postMessage(m2); -*/ } int VRecordingList::doPlay() diff --git a/vrecordingmenu.cc b/vrecordingmenu.cc index bbc3b3b..6f64602 100644 --- a/vrecordingmenu.cc +++ b/vrecordingmenu.cc @@ -43,7 +43,7 @@ VRecordingMenu::VRecordingMenu() sl.setSurface(surface); sl.setSurfaceOffset(10, 30 + 5); - sl.setDimensions(width - 20, height - 30 - 15); + sl.setDimensions(area.w - 20, area.h - 30 - 15); sl.addOption(tr("Play"), 1); sl.addOption(tr("Resume"), 0); sl.addOption(tr("Summary"), 0); diff --git a/vserverselect.cc b/vserverselect.cc index 687c4a4..9ade764 100644 --- a/vserverselect.cc +++ b/vserverselect.cc @@ -44,7 +44,7 @@ VServerSelect::VServerSelect(std::vector* serverIPs) sl.setSurface(surface); sl.setSurfaceOffset(10, 30 + 5); - sl.setDimensions(width - 20, height - 30 - 15); + sl.setDimensions(area.w - 20, area.h - 30 - 15); sl.addOption((*serverIPs)[0], 1); for(UINT k = 1; k < serverIPs->size(); k++) diff --git a/vvideolive.cc b/vvideolive.cc index 1dc413a..bb0c33a 100644 --- a/vvideolive.cc +++ b/vvideolive.cc @@ -234,7 +234,7 @@ void VVideoLive::play(int noShowVLB) void VVideoLive::stop(int noRemoveVLB) { if (unavailable) return; - if (!noRemoveVLB) viewman->removeView(vlb, 1, 1); // if live banner is present, remove it. won't cause damage if its not present + if (!noRemoveVLB) viewman->removeView(vlb, 1); // if live banner is present, remove it. won't cause damage if its not present player->stop(); vdr->stopStreaming(); diff --git a/vwelcome.cc b/vwelcome.cc index 29cc91c..313be10 100644 --- a/vwelcome.cc +++ b/vwelcome.cc @@ -242,7 +242,7 @@ void VWelcome::doRecordingsList() } Log::getInstance()->log("VWelcome", Log::DEBUG, "possible delay start"); - viewman->removeView(viewWait, 1, 1); + viewman->removeView(viewWait, 1); Log::getInstance()->log("VWelcome", Log::DEBUG, "possible delay end"); } diff --git a/widget.cc b/widget.cc index 8317fa6..3e833fe 100644 --- a/widget.cc +++ b/widget.cc @@ -22,8 +22,6 @@ Widget::Widget() { - width = 0; - height = 0; } Widget::~Widget() @@ -37,6 +35,6 @@ void Widget::setSurface(Surface* tsurface) void Widget::setDimensions(int twidth, int theight) { - width = twidth; - height = theight; + area.w = twidth; + area.h = theight; } diff --git a/wjpeg.cc b/wjpeg.cc index b803564..fb64a6a 100644 --- a/wjpeg.cc +++ b/wjpeg.cc @@ -54,11 +54,11 @@ void WJpeg::draw() // MAKE THE 2D ARRAY - unsigned char* buffer = (unsigned char*)malloc(width * height * 3); - logger->log("BJpeg", Log::DEBUG, "Buffer allocated at %p, width = %i height = %i", buffer, width, height); + unsigned char* buffer = (unsigned char*)malloc(area.w * area.h * 3); + logger->log("BJpeg", Log::DEBUG, "Buffer allocated at %p, width = %i height = %i", buffer, area.w, area.h); - unsigned char* bufferPointers[height]; - for(UINT ps = 0; ps < height; ps++) bufferPointers[ps] = buffer + (ps * width * 3); + unsigned char* bufferPointers[area.h]; + for(UINT ps = 0; ps < area.h; ps++) bufferPointers[ps] = buffer + (ps * area.w * 3); logger->log("BJpeg", Log::DEBUG, "done array check"); @@ -66,7 +66,7 @@ void WJpeg::draw() while (cinfo.output_scanline < cinfo.output_height) { // logger->log("BJpeg", Log::DEBUG, "%i", rowsread); - rowsread += jpeg_read_scanlines(&cinfo, &bufferPointers[rowsread], height); + rowsread += jpeg_read_scanlines(&cinfo, &bufferPointers[rowsread], area.h); } logger->log("BJpeg", Log::DEBUG, "Done all jpeg_read"); @@ -76,17 +76,17 @@ void WJpeg::draw() fclose(infile); - logger->log("BJpeg", Log::DEBUG, "jpeg shutdown done, x, y %u %u", width, height); + logger->log("BJpeg", Log::DEBUG, "jpeg shutdown done, x, y %u %u", area.w, area.h); Colour c; UINT x, y, xoff; unsigned char* p; - for (y = 0; y < height; y++) + for (y = 0; y < area.h; y++) { p = bufferPointers[y]; - for (x = 0; x < width; x++) + for (x = 0; x < area.w; x++) { xoff = x * 3; diff --git a/wselectlist.cc b/wselectlist.cc index 85c50e7..2cd7c9e 100644 --- a/wselectlist.cc +++ b/wselectlist.cc @@ -80,7 +80,7 @@ void WSelectList::draw() int fontHeight = surface->getFontHeight(); int ySeperation = fontHeight + 1; - numOptionsDisplayable = (height - 5) / ySeperation; + numOptionsDisplayable = (area.h - 5) / ySeperation; if (selectedOption == (topOption + numOptionsDisplayable)) topOption++; if (selectedOption == ((UINT)topOption - 1)) topOption--; @@ -100,11 +100,11 @@ void WSelectList::draw() for (UINT i = topOption; i < (topOption + numOptionsDisplayable); i++) { if (i == options.size()) return; - if ((ypos + ySeperation) > height) break; + if ((ypos + ySeperation) > area.h) break; if (i == selectedOption) { - rectangle(0, ypos, width, fontHeight, Colour::SELECTHIGHLIGHT); + rectangle(0, ypos, area.w, fontHeight, Colour::SELECTHIGHLIGHT); drawOptionLine(options[i], 5, ypos, Colour::DARKTEXT); } else -- 2.39.5