mirror of
https://gitee.com/houstudio/Cdroid.git
synced 2024-12-02 04:07:42 +08:00
remaking looper impl,remove MessageListener
This commit is contained in:
parent
6bfddb7370
commit
ee104a0285
6
apps/samples/animation.cc
Normal file → Executable file
6
apps/samples/animation.cc
Normal file → Executable file
@ -21,7 +21,7 @@ public :
|
|||||||
canvas.stroke();
|
canvas.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool onMessage(DWORD msg,DWORD wp,ULONG lp)override{
|
/*virtual bool onMessage(DWORD msg,DWORD wp,ULONG lp)override{
|
||||||
if(msg==1000){
|
if(msg==1000){
|
||||||
matrix.scale(cx,cx);cx+=0.01f;
|
matrix.scale(cx,cx);cx+=0.01f;
|
||||||
matrix.rotate(cx);
|
matrix.rotate(cx);
|
||||||
@ -30,7 +30,7 @@ public :
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return Window::onMessage(msg,wp,lp);;
|
return Window::onMessage(msg,wp,lp);;
|
||||||
}
|
}*/
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc,const char*argv[]){
|
int main(int argc,const char*argv[]){
|
||||||
@ -40,7 +40,7 @@ int main(int argc,const char*argv[]){
|
|||||||
|
|
||||||
w->addView(new TextView("HelloWorld",400,80));
|
w->addView(new TextView("HelloWorld",400,80));
|
||||||
|
|
||||||
w->sendMessage(1000,0,0,500);
|
//w->sendMessage(1000,0,0,500);
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,12 +75,12 @@ public:
|
|||||||
canvas->fill();
|
canvas->fill();
|
||||||
mDegrees=0;
|
mDegrees=0;
|
||||||
}
|
}
|
||||||
bool onMessage(DWORD msg,DWORD wp,ULONG lp)override{
|
/*bool onMessage(DWORD msg,DWORD wp,ULONG lp)override{
|
||||||
if(msg==1000){
|
if(msg==1000){
|
||||||
invalidate(nullptr);
|
invalidate(nullptr);
|
||||||
}
|
}
|
||||||
return Window::onMessage(msg,wp,lp);
|
return Window::onMessage(msg,wp,lp);
|
||||||
}
|
}*/
|
||||||
};
|
};
|
||||||
int main(int argc,const char*argv[]){
|
int main(int argc,const char*argv[]){
|
||||||
App app(argc,argv);
|
App app(argc,argv);
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
#include<netinet/in.h>
|
|
||||||
#include<arpa/inet.h>
|
|
||||||
#include<unistd.h>
|
|
||||||
#include<fcntl.h>
|
|
||||||
#include<sys/stat.h>
|
|
||||||
#include<sys/types.h>
|
|
||||||
#include<sys/socket.h>
|
|
||||||
#include<windows.h>
|
|
||||||
#include<asynsource.h>
|
|
||||||
#include<iostream>
|
|
||||||
|
|
||||||
int main(int argc,const char*argv[]){
|
|
||||||
App app(argc,argv);
|
|
||||||
AsyncEventSource*as=new AsyncEventSource();
|
|
||||||
Looper::getDefault()->add_event_source(as,[](EventSource&){return true;});
|
|
||||||
for(int i=0;i<10;i++){
|
|
||||||
std::future<int> res=as->enqueue([i](int a)->int{
|
|
||||||
usleep((a+500)*1000);
|
|
||||||
std::cout<<i<<" 'sresult:="<<a<<std::endl;
|
|
||||||
return a;
|
|
||||||
},i);
|
|
||||||
//std::cout<<i<<" 'sresult:="<<res.get()<<std::endl;
|
|
||||||
}
|
|
||||||
std::cout<<"before exec"<<std::endl;
|
|
||||||
return app.exec();
|
|
||||||
}
|
|
10
apps/samples/multiwindow.cc
Normal file → Executable file
10
apps/samples/multiwindow.cc
Normal file → Executable file
@ -12,7 +12,7 @@ public:
|
|||||||
MWindow(int x,int y,int w,int h):Window(x,y,w,h){dx=dy=50;}
|
MWindow(int x,int y,int w,int h):Window(x,y,w,h){dx=dy=50;}
|
||||||
virtual bool onMessage(DWORD msgid,DWORD wp,ULONG lp){
|
virtual bool onMessage(DWORD msgid,DWORD wp,ULONG lp){
|
||||||
if(1000==msgid){
|
if(1000==msgid){
|
||||||
sendMessage(msgid,wp,lp,lp);
|
//sendMessage(msgid,wp,lp,lp);
|
||||||
int x=getX();
|
int x=getX();
|
||||||
int y=getY();
|
int y=getY();
|
||||||
if(x+getWidth()>1280)dx*=-1;
|
if(x+getWidth()>1280)dx*=-1;
|
||||||
@ -22,7 +22,7 @@ public:
|
|||||||
setPos(x+dx,y+dy);
|
setPos(x+dx,y+dy);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return Window::onMessage(msgid,wp,lp);
|
return true;//Window::onMessage(msgid,wp,lp);
|
||||||
}
|
}
|
||||||
void onDraw(Canvas&c)override{
|
void onDraw(Canvas&c)override{
|
||||||
srand(time(nullptr)*(long)this);
|
srand(time(nullptr)*(long)this);
|
||||||
@ -52,9 +52,9 @@ int main(int argc,const char*argv[]){
|
|||||||
w2->addView(lv2).setId(0);
|
w2->addView(lv2).setId(0);
|
||||||
|
|
||||||
if(argc>5){
|
if(argc>5){
|
||||||
w1->sendMessage(1000,0,2000,100);w1->setDir(50,40);
|
//w1->sendMessage(1000,0,2000,100);w1->setDir(50,40);
|
||||||
w2->sendMessage(1000,0,1000,80);w2->setDir(66,53);
|
//w2->sendMessage(1000,0,1000,80);w2->setDir(66,53);
|
||||||
w3->sendMessage(1000,0,200,85);w3->setDir(23,13);
|
//w3->sendMessage(1000,0,200,85);w3->setDir(23,13);
|
||||||
}
|
}
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ private:
|
|||||||
Spinner*mLevelSelector;
|
Spinner*mLevelSelector;
|
||||||
Button*mStartButton;
|
Button*mStartButton;
|
||||||
protected:
|
protected:
|
||||||
bool onMessage(DWORD msgid,DWORD wp,ULONG lp)override;
|
bool onMessage(DWORD msgid,DWORD wp,ULONG lp);
|
||||||
void onDraw(Canvas&canvas)override;
|
void onDraw(Canvas&canvas)override;
|
||||||
bool onKeyUp(int keyCode,KeyEvent&event)override;
|
bool onKeyUp(int keyCode,KeyEvent&event)override;
|
||||||
public:
|
public:
|
||||||
@ -241,7 +241,7 @@ void TetrisWindow::ResetBlock(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TetrisWindow::StartGame(){
|
void TetrisWindow::StartGame(){
|
||||||
sendMessage(WM_REFRESH,0,0,speed_ms);
|
//sendMessage(WM_REFRESH,0,0,speed_ms);
|
||||||
//产生初始下一个方块
|
//产生初始下一个方块
|
||||||
int block_id=rand()%7;
|
int block_id=rand()%7;
|
||||||
CreateBlock(next_block,block_id);
|
CreateBlock(next_block,block_id);
|
||||||
@ -279,9 +279,9 @@ bool TetrisWindow::onMessage(DWORD msgid,DWORD wp,ULONG lp){
|
|||||||
if((msgid==WM_REFRESH)&&(!mGameIsOver)){
|
if((msgid==WM_REFRESH)&&(!mGameIsOver)){
|
||||||
BlockMove(DOWN);
|
BlockMove(DOWN);
|
||||||
invalidate(nullptr);
|
invalidate(nullptr);
|
||||||
sendMessage(msgid,wp,lp,speed_ms);
|
//sendMessage(msgid,wp,lp,speed_ms);
|
||||||
}else
|
}else
|
||||||
return Window::onMessage(msgid,wp,lp);
|
return true;//Window::onMessage(msgid,wp,lp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TetrisWindow::GameOver(){
|
void TetrisWindow::GameOver(){
|
||||||
|
@ -10,7 +10,7 @@ protected:
|
|||||||
TextView*tv3;
|
TextView*tv3;
|
||||||
public:
|
public:
|
||||||
TestWindow(int w,int h);
|
TestWindow(int w,int h);
|
||||||
bool onMessage(DWORD msg,DWORD wp,ULONG lp)override;
|
bool onMessage(DWORD msg,DWORD wp,ULONG lp);
|
||||||
};
|
};
|
||||||
|
|
||||||
TestWindow::TestWindow(int w,int h):Window(0,0,w,h){
|
TestWindow::TestWindow(int w,int h):Window(0,0,w,h){
|
||||||
@ -78,16 +78,16 @@ bool TestWindow::onMessage(DWORD msg,DWORD wp,ULONG lp){
|
|||||||
if(flag>0){lvl+=200;if(lvl>=10000)flag=-1;}
|
if(flag>0){lvl+=200;if(lvl>=10000)flag=-1;}
|
||||||
if(flag<0){lvl-=200;if(lvl<=0)flag=1;}
|
if(flag<0){lvl-=200;if(lvl<=0)flag=1;}
|
||||||
tv3->getForeground()->setLevel(lvl);
|
tv3->getForeground()->setLevel(lvl);
|
||||||
sendMessage(msg,wp,lp,200);
|
//sendMessage(msg,wp,lp,200);
|
||||||
}break;
|
}break;
|
||||||
default:return Window::onMessage(msg,wp,lp);
|
default:return true;//Window::onMessage(msg,wp,lp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc,const char*argv[]){
|
int main(int argc,const char*argv[]){
|
||||||
App app(argc,argv);
|
App app(argc,argv);
|
||||||
Window*w=new TestWindow(1080,720);
|
Window*w=new TestWindow(1080,720);
|
||||||
w->sendMessage(View::WM_TIMER,0,0,500);
|
//w->sendMessage(View::WM_TIMER,0,0,500);
|
||||||
app.exec();
|
app.exec();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
6
apps/uidemo/lyrics.cc
Normal file → Executable file
6
apps/uidemo/lyrics.cc
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
#include <lyrics.h>
|
#include <lyrics.h>
|
||||||
#include <assets.h>
|
#include <core/assets.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -14,8 +14,8 @@ using namespace tag;
|
|||||||
|
|
||||||
#include <cdtypes.h>
|
#include <cdtypes.h>
|
||||||
#include <cdlog.h>
|
#include <cdlog.h>
|
||||||
#include <iostreams.h>
|
#include <core/iostreams.h>
|
||||||
#include <textutils.h>
|
#include <core/textutils.h>
|
||||||
|
|
||||||
|
|
||||||
namespace priv{
|
namespace priv{
|
||||||
|
2
apps/uidemo/lyrics.h
Normal file → Executable file
2
apps/uidemo/lyrics.h
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||
#ifndef __ID3_LYRICS__H__
|
#ifndef __ID3_LYRICS__H__
|
||||||
#define __ID3_LYRICS__H__
|
#define __ID3_LYRICS__H__
|
||||||
#include <canvas.h>
|
#include <core/canvas.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
1
apps/uidemo/lyricsview.cc
Normal file → Executable file
1
apps/uidemo/lyricsview.cc
Normal file → Executable file
@ -1,5 +1,4 @@
|
|||||||
#include <lyricsview.h>
|
#include <lyricsview.h>
|
||||||
#include <assets.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
1
apps/uidemo/multimedia.cc
Normal file → Executable file
1
apps/uidemo/multimedia.cc
Normal file → Executable file
@ -6,7 +6,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <assets.h>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <lyricsview.h>
|
#include <lyricsview.h>
|
||||||
|
4
src/3rdparty/libjpeg-turbo/CMakeLists.txt
vendored
Normal file → Executable file
4
src/3rdparty/libjpeg-turbo/CMakeLists.txt
vendored
Normal file → Executable file
@ -40,7 +40,7 @@ message(STATUS "VERSION = ${VERSION}, BUILD = ${BUILD}")
|
|||||||
|
|
||||||
# Detect CPU type and whether we're building 64-bit or 32-bit code
|
# Detect CPU type and whether we're building 64-bit or 32-bit code
|
||||||
math(EXPR BITS "${CMAKE_SIZEOF_VOID_P} * 8")
|
math(EXPR BITS "${CMAKE_SIZEOF_VOID_P} * 8")
|
||||||
#string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} CMAKE_SYSTEM_PROCESSOR_LC)
|
string(TOLOWER ${CMAKE_SYSTEM_PROCESSOR} CMAKE_SYSTEM_PROCESSOR_LC)
|
||||||
if(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "x86_64" OR
|
if(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "x86_64" OR
|
||||||
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "amd64" OR
|
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "amd64" OR
|
||||||
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "i[0-9]86" OR
|
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "i[0-9]86" OR
|
||||||
@ -62,6 +62,8 @@ elseif(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "arm*")
|
|||||||
elseif(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "ppc*" OR
|
elseif(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "ppc*" OR
|
||||||
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "powerpc*")
|
CMAKE_SYSTEM_PROCESSOR_LC MATCHES "powerpc*")
|
||||||
set(CPU_TYPE powerpc)
|
set(CPU_TYPE powerpc)
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR_LC MATCHES "mips*")
|
||||||
|
set(CPU_TYPE mipsel)
|
||||||
else()
|
else()
|
||||||
set(CPU_TYPE ${CMAKE_SYSTEM_PROCESSOR_LC})
|
set(CPU_TYPE ${CMAKE_SYSTEM_PROCESSOR_LC})
|
||||||
endif()
|
endif()
|
||||||
|
@ -9,7 +9,6 @@ aux_source_directory(widget SRCS_WIDGET)
|
|||||||
aux_source_directory(drawables SRCS_DRAWABLES)
|
aux_source_directory(drawables SRCS_DRAWABLES)
|
||||||
aux_source_directory(cairomm SRCS_CAIROMM)
|
aux_source_directory(cairomm SRCS_CAIROMM)
|
||||||
aux_source_directory(dialogs SRCS_DIALOG)
|
aux_source_directory(dialogs SRCS_DIALOG)
|
||||||
aux_source_directory(looper SRCS_LOOP)
|
|
||||||
aux_source_directory(animation SRCS_ANIMATION)
|
aux_source_directory(animation SRCS_ANIMATION)
|
||||||
|
|
||||||
message("UI Lua script bindings is ${LUA_BINDINGS} guistatic=${GUI_STATIC}")
|
message("UI Lua script bindings is ${LUA_BINDINGS} guistatic=${GUI_STATIC}")
|
||||||
@ -40,7 +39,7 @@ add_definitions(-DRAPIDJSON_HAS_STDSTRING)
|
|||||||
set(SOURCES_GUI ${SRCS_GUICORE} ${SRCS_VIEWS}
|
set(SOURCES_GUI ${SRCS_GUICORE} ${SRCS_VIEWS}
|
||||||
${SRCS_WIDGET} ${SRCS_DRAWABLES}
|
${SRCS_WIDGET} ${SRCS_DRAWABLES}
|
||||||
${SRCS_CAIROMM} ${SRCS_DIALOG}
|
${SRCS_CAIROMM} ${SRCS_DIALOG}
|
||||||
${SRCS_LOOP} ${SRCS_ANIMATION})
|
${SRCS_ANIMATION})
|
||||||
|
|
||||||
add_library(gui_objs OBJECT ${SOURCES_GUI})
|
add_library(gui_objs OBJECT ${SOURCES_GUI})
|
||||||
add_library(gui_static STATIC $<TARGET_OBJECTS:gui_objs>)
|
add_library(gui_static STATIC $<TARGET_OBJECTS:gui_objs>)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#ifndef __ANIMATION_H__
|
#ifndef __ANIMATION_H__
|
||||||
#define __ANIMATION_H__
|
#define __ANIMATION_H__
|
||||||
#include <context.h>
|
#include <core/context.h>
|
||||||
|
|
||||||
#include <animation/transformation.h>
|
#include <animation/transformation.h>
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ void Animator::appendChangingConfigurations(int configs) {
|
|||||||
|
|
||||||
void Animator::setupStartValues() {
|
void Animator::setupStartValues() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animator::setupEndValues() {
|
void Animator::setupEndValues() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,4 +138,5 @@ AnimatorListenerAdapter::AnimatorListenerAdapter(){
|
|||||||
onAnimationCancel=onAnimationRepeat=onAnimationPause=onAnimationResume=[](Animator&anim){};
|
onAnimationCancel=onAnimationRepeat=onAnimationPause=onAnimationResume=[](Animator&anim){};
|
||||||
onAnimationEnd=onAnimationStart=[](Animator&aim,bool reverse){};
|
onAnimationEnd=onAnimationStart=[](Animator&aim,bool reverse){};
|
||||||
}
|
}
|
||||||
|
|
||||||
}//endof namespace
|
}//endof namespace
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <interpolators.h>
|
#include <animation/interpolators.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
|
2
src/gui/core/interpolators.cc → src/gui/animation/interpolators.cc
Normal file → Executable file
2
src/gui/core/interpolators.cc → src/gui/animation/interpolators.cc
Normal file → Executable file
@ -1,4 +1,4 @@
|
|||||||
#include <interpolators.h>
|
#include <animation/interpolators.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
#if 0
|
#if 0
|
0
src/gui/core/interpolators.h → src/gui/animation/interpolators.h
Normal file → Executable file
0
src/gui/core/interpolators.h → src/gui/animation/interpolators.h
Normal file → Executable file
@ -3,7 +3,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <widget/viewgroup.h>
|
#include <widget/viewgroup.h>
|
||||||
#include <interpolators.h>
|
|
||||||
#include <animation/animator.h>
|
#include <animation/animator.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef __SCALEANIMATION_H__
|
#ifndef __SCALEANIMATION_H__
|
||||||
#define __SCALEANIMATION_H__
|
#define __SCALEANIMATION_H__
|
||||||
#include <animation/animation.h>
|
#include <animation/animation.h>
|
||||||
#include <typedvalue.h>
|
#include <core/typedvalue.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
class ScaleAnimation:public Animation{
|
class ScaleAnimation:public Animation{
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#ifndef __TRANSFORMATION_H__
|
#ifndef __TRANSFORMATION_H__
|
||||||
#define __TRANSFORMATION_H__
|
#define __TRANSFORMATION_H__
|
||||||
#include <rect.h>
|
#include <core/rect.h>
|
||||||
#include <cairomm/matrix.h>
|
#include <cairomm/matrix.h>
|
||||||
#include <interpolators.h>
|
#include <animation/interpolators.h>
|
||||||
#include <attributeset.h>
|
#include <core/attributeset.h>
|
||||||
|
|
||||||
typedef Cairo::Matrix Matrix;
|
typedef Cairo::Matrix Matrix;
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
#include <alooper.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/eventfd.h>
|
|
||||||
#include <cdtypes.h>
|
|
||||||
#include <cdlog.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
namespace alooper{
|
|
||||||
|
|
||||||
static constexpr int EPOLL_SIZE_HINT = 8;
|
|
||||||
// Maximum number of file descriptors for which to retrieve poll events each iteration.
|
|
||||||
static constexpr int EPOLL_MAX_EVENTS = 16;
|
|
||||||
|
|
||||||
void Looper::Looper::Request::initEventItem(struct epoll_event* eventItem) const{
|
|
||||||
}
|
|
||||||
|
|
||||||
Looper::Looper(bool allowNonCallbacks) :
|
|
||||||
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
|
|
||||||
mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
|
|
||||||
mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LONG_MAX) {
|
|
||||||
//mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
|
|
||||||
//LOGE_IF(mWakeEventFd < 0, "Could not make wake event fd: %s",strerror(errno));
|
|
||||||
//AutoMutex _l(mLock);
|
|
||||||
rebuildEpollLocked();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Looper::rebuildEpollLocked() {
|
|
||||||
// Close old epoll instance if we have one.
|
|
||||||
if (mEpollFd >= 0) {
|
|
||||||
LOGV("%p ~ rebuildEpollLocked - rebuilding epoll set", this);
|
|
||||||
close(mEpollFd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate the new epoll instance and register the wake pipe.
|
|
||||||
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
|
|
||||||
LOGE_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
|
|
||||||
|
|
||||||
struct epoll_event eventItem;
|
|
||||||
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
|
|
||||||
eventItem.events = EPOLLIN;
|
|
||||||
eventItem.data.fd = mWakeEventFd;
|
|
||||||
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
|
|
||||||
LOGE_IF(result != 0, "Could not add wake event fd to epoll instance: %s",strerror(errno));
|
|
||||||
|
|
||||||
for (auto it=mRequests.begin();it!=mRequests.end(); it++) {
|
|
||||||
const Request& request = it->second;
|
|
||||||
struct epoll_event eventItem;
|
|
||||||
request.initEventItem(&eventItem);
|
|
||||||
|
|
||||||
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
|
|
||||||
if (epollResult < 0) {
|
|
||||||
LOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",request.fd, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,7 +16,6 @@
|
|||||||
#include <cdinput.h>
|
#include <cdinput.h>
|
||||||
#include <inputeventsource.h>
|
#include <inputeventsource.h>
|
||||||
#include <uieventsource.h>
|
#include <uieventsource.h>
|
||||||
#include <looper/GenericSignalSource.h>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
@ -76,13 +75,10 @@ App::App(int argc,const char*argv[],const struct option*extoptions){
|
|||||||
|
|
||||||
setOpacity(getArgAsInt("alpha",255));
|
setOpacity(getArgAsInt("alpha",255));
|
||||||
InputEventSource*inputsource=new InputEventSource(getArg("record",""));
|
InputEventSource*inputsource=new InputEventSource(getArg("record",""));
|
||||||
addEventSource(inputsource,[](EventSource&s){
|
addEventHandler(inputsource);
|
||||||
((InputEventSource&)s).processKey();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
inputsource->playback(getArg("monkey",""));
|
inputsource->playback(getArg("monkey",""));
|
||||||
|
|
||||||
SignalSource*sigsource=new GenericSignalSource(false);
|
/*SignalSource*sigsource=new GenericSignalSource(false);
|
||||||
addEventSource(sigsource,[this](EventSource&s){
|
addEventSource(sigsource,[this](EventSource&s){
|
||||||
LOGI("Sig interrupt %d",((SignalSource&)s).signo);
|
LOGI("Sig interrupt %d",((SignalSource&)s).signo);
|
||||||
this->exit(((SignalSource&)s).signo);
|
this->exit(((SignalSource&)s).signo);
|
||||||
@ -91,7 +87,7 @@ App::App(int argc,const char*argv[],const struct option*extoptions){
|
|||||||
sigsource->add(SIGABRT);
|
sigsource->add(SIGABRT);
|
||||||
sigsource->add(SIGINT);
|
sigsource->add(SIGINT);
|
||||||
sigsource->add(SIGTERM);
|
sigsource->add(SIGTERM);
|
||||||
sigsource->add(SIGKILL);
|
sigsource->add(SIGKILL);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
App::~App(){
|
App::~App(){
|
||||||
@ -157,20 +153,20 @@ const std::string App::getAssetsPath(){
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
int App::addEventSource(EventSource *source, EventHandler handler){
|
void App::addEventHandler(const EventHandler*handler){
|
||||||
return Looper::getDefault()->add_event_source(source,handler);
|
Looper::getDefault()->addEventHandler(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
int App::removeEventSource(EventSource*source){
|
void App::removeEventHandler(const EventHandler*handler){
|
||||||
return Looper::getDefault()->remove_event_source(source);
|
//Looper::getDefault()->remove_event_source(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
int App::exec(){
|
int App::exec(){
|
||||||
return Looper::getDefault()->run();
|
while(1)Looper::getDefault()->pollAll(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::exit(int code){
|
void App::exit(int code){
|
||||||
Looper::getDefault()->quit(code);
|
//Looper::getDefault()->quit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::setName(const std::string&appname){
|
void App::setName(const std::string&appname){
|
||||||
|
10
src/gui/core/app.h
Normal file → Executable file
10
src/gui/core/app.h
Normal file → Executable file
@ -4,9 +4,9 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <cairomm/surface.h>
|
#include <cairomm/surface.h>
|
||||||
#include <looper/looper.h>
|
#include <core/looper.h>
|
||||||
#include <context.h>
|
#include <core/context.h>
|
||||||
#include <assets.h>
|
#include <core/assets.h>
|
||||||
struct option;
|
struct option;
|
||||||
using namespace Cairo;
|
using namespace Cairo;
|
||||||
|
|
||||||
@ -32,8 +32,8 @@ public:
|
|||||||
virtual const std::string&getArg(const std::string&key,const std::string&def="")const;
|
virtual const std::string&getArg(const std::string&key,const std::string&def="")const;
|
||||||
|
|
||||||
virtual int getArgAsInt(const std::string&key,int def)const;
|
virtual int getArgAsInt(const std::string&key,int def)const;
|
||||||
virtual int addEventSource(EventSource *source, EventHandler handler);
|
virtual void addEventHandler(const EventHandler* handler);
|
||||||
virtual int removeEventSource(EventSource*source);
|
virtual void removeEventHandler(const EventHandler*handler);
|
||||||
virtual int exec();
|
virtual int exec();
|
||||||
virtual void exit(int code=0);
|
virtual void exit(int code=0);
|
||||||
};
|
};
|
||||||
|
1
src/gui/core/assets.h
Normal file → Executable file
1
src/gui/core/assets.h
Normal file → Executable file
@ -1,6 +1,5 @@
|
|||||||
#ifndef __ASSETS_H__
|
#ifndef __ASSETS_H__
|
||||||
#define __ASSETS_H__
|
#define __ASSETS_H__
|
||||||
#include <context.h>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
#include <asynsource.h>
|
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <future>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
namespace cdroid {
|
|
||||||
|
|
||||||
AsyncEventSource::AsyncEventSource(){
|
|
||||||
int threads=std::thread::hardware_concurrency();
|
|
||||||
for(size_t i = 0; i<threads; ++i)
|
|
||||||
workers.emplace_back(
|
|
||||||
[this] {
|
|
||||||
for(;;) {
|
|
||||||
std::function<void()> task;
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(this->queue_mutex);
|
|
||||||
this->condition.wait(lock,
|
|
||||||
[this] { return this->stop || !this->tasks.empty(); });
|
|
||||||
if(this->stop && this->tasks.empty())
|
|
||||||
return;
|
|
||||||
task = std::move(this->tasks.front());
|
|
||||||
this->tasks.pop();
|
|
||||||
}
|
|
||||||
task();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncEventSource::~AsyncEventSource() {
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(queue_mutex);
|
|
||||||
stop = true;
|
|
||||||
}
|
|
||||||
condition.notify_all();
|
|
||||||
for(std::thread &worker: workers)
|
|
||||||
worker.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AsyncEventSource::prepare(int& max_timeout) {
|
|
||||||
return tasks.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AsyncEventSource::check(){
|
|
||||||
return tasks.size()>0;
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
template<class F, class... Args>
|
|
||||||
auto AsyncEventSource::enqueue(F&& f, Args&&... args)-> std::future<typename std::result_of<F(Args...)>::type>{
|
|
||||||
using return_type = typename std::result_of<F(Args...)>::type;
|
|
||||||
auto task = std::make_shared< std::packaged_task<return_type()> >(
|
|
||||||
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
|
|
||||||
);
|
|
||||||
std::future<return_type> res = task->get_future();
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(queue_mutex);
|
|
||||||
if(stop)// don't allow enqueueing after stopping the pool
|
|
||||||
throw std::runtime_error("enqueue on stopped ThreadPool");
|
|
||||||
tasks.emplace([task]() {
|
|
||||||
(*task)();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
condition.notify_one();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
bool AsyncEventSource::dispatch(EventHandler &func) { return func(*this); }
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
#ifndef __ASYNC_SOURCE_H__
|
|
||||||
#define __ASYNC_SOURCE_H__
|
|
||||||
#include <cdinput.h>
|
|
||||||
#include <looper/looper.h>
|
|
||||||
#include <widget/view.h>
|
|
||||||
#include <future>
|
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <functional>
|
|
||||||
namespace cdroid{
|
|
||||||
|
|
||||||
DECLARE_UIEVENT(void,AsyncEvent,void);
|
|
||||||
|
|
||||||
//template<class F, class... Args>
|
|
||||||
class AsyncEventSource:public EventSource{
|
|
||||||
protected:
|
|
||||||
std::vector< std::thread > workers;
|
|
||||||
// the task queue
|
|
||||||
std::queue< std::function<void()> > tasks;
|
|
||||||
// synchronization
|
|
||||||
std::mutex queue_mutex;
|
|
||||||
std::condition_variable condition;
|
|
||||||
bool stop;
|
|
||||||
public:
|
|
||||||
AsyncEventSource();
|
|
||||||
~AsyncEventSource();
|
|
||||||
bool prepare(int& max_timeout);
|
|
||||||
bool check();
|
|
||||||
bool dispatch(EventHandler &func);
|
|
||||||
bool is_file_source() const override final { return false; }
|
|
||||||
template<class F, class... Args>
|
|
||||||
auto enqueue(F&& f, Args&&... args)-> std::future<typename std::result_of<F(Args...)>::type>{
|
|
||||||
using return_type = typename std::result_of<F(Args...)>::type;
|
|
||||||
auto task = std::make_shared< std::packaged_task<return_type()> >(
|
|
||||||
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
|
|
||||||
);
|
|
||||||
std::future<return_type> res = task->get_future();
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(queue_mutex);
|
|
||||||
if(stop)// don't allow enqueueing after stopping the pool
|
|
||||||
throw std::runtime_error("enqueue on stopped ThreadPool");
|
|
||||||
tasks.emplace([task]() {
|
|
||||||
(*task)();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
condition.notify_one();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -4,7 +4,7 @@
|
|||||||
#include <cdgraph.h>
|
#include <cdgraph.h>
|
||||||
#include <cairomm/context.h>
|
#include <cairomm/context.h>
|
||||||
#include <cairomm/region.h>
|
#include <cairomm/region.h>
|
||||||
#include <graph_device.h>
|
#include <core/graph_device.h>
|
||||||
#include <gui/gui_features.h>
|
#include <gui/gui_features.h>
|
||||||
using namespace Cairo;
|
using namespace Cairo;
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ namespace cdroid{
|
|||||||
CallbackRecord* predecessor = nullptr;
|
CallbackRecord* predecessor = nullptr;
|
||||||
for (CallbackRecord* callback = mHead; callback != nullptr;) {
|
for (CallbackRecord* callback = mHead; callback != nullptr;) {
|
||||||
CallbackRecord* next = callback->next;
|
CallbackRecord* next = callback->next;
|
||||||
if ((action == nullptr || addr_of(callback->action) == addr_of(action))
|
if ((/*action == nullptr ||*/ callback->action.ID == action.ID)
|
||||||
&& (token == 0 || callback->token == token)) {
|
&& (token == 0 || callback->token == token)) {
|
||||||
if (predecessor != nullptr) {
|
if (predecessor != nullptr) {
|
||||||
predecessor->next = next;
|
predecessor->next = next;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#ifndef __CHOREO_GRAPHER_H__
|
#ifndef __CHOREO_GRAPHER_H__
|
||||||
#define __CHOREO_GRAPHER_H__
|
#define __CHOREO_GRAPHER_H__
|
||||||
#include <looper/looper.h>
|
#include <core/looper.h>
|
||||||
#include <drawables/drawable.h>
|
#include <drawables/drawable.h>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
class Choreographer{
|
class Choreographer{
|
||||||
|
@ -9,7 +9,35 @@
|
|||||||
using namespace Cairo;
|
using namespace Cairo;
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
typedef std::function<void()>Runnable;
|
class Runnable{
|
||||||
|
public:
|
||||||
|
int ID;
|
||||||
|
std::function<void()>run;
|
||||||
|
Runnable(){
|
||||||
|
run=nullptr;
|
||||||
|
}
|
||||||
|
Runnable(const std::function<void()>&f){
|
||||||
|
run=f;
|
||||||
|
}
|
||||||
|
void operator=(const std::function<void()>&f){
|
||||||
|
run=f;
|
||||||
|
}
|
||||||
|
void operator=(nullptr_t){
|
||||||
|
run=nullptr;
|
||||||
|
}
|
||||||
|
bool operator==(nullptr_t)const{
|
||||||
|
return run==nullptr;
|
||||||
|
}
|
||||||
|
bool operator!=(nullptr_t)const{
|
||||||
|
return run!=nullptr;
|
||||||
|
}
|
||||||
|
explicit operator bool()const{
|
||||||
|
return run!=nullptr;
|
||||||
|
}
|
||||||
|
void operator()(){
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
};
|
||||||
class Drawable;
|
class Drawable;
|
||||||
class ColorStateList;
|
class ColorStateList;
|
||||||
class Context{
|
class Context{
|
||||||
|
2
src/gui/core/eventcodes.h
Normal file → Executable file
2
src/gui/core/eventcodes.h
Normal file → Executable file
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef _INPUT_EVENT_CODES_H
|
#ifndef _INPUT_EVENT_CODES_H
|
||||||
#define _INPUT_EVENT_CODES_H
|
#define _INPUT_EVENT_CODES_H
|
||||||
#include <keycodes.h>
|
#include <core/keycodes.h>
|
||||||
/*
|
/*
|
||||||
* Device properties and quirks
|
* Device properties and quirks
|
||||||
*/
|
*/
|
||||||
|
2
src/gui/core/graph_device.h
Normal file → Executable file
2
src/gui/core/graph_device.h
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||
#ifndef __GRAPH_DEVICE_H__
|
#ifndef __GRAPH_DEVICE_H__
|
||||||
#define __GRAPH_DEVICE_H__
|
#define __GRAPH_DEVICE_H__
|
||||||
#include <rect.h>
|
#include <core/rect.h>
|
||||||
#include <cairomm/context.h>
|
#include <cairomm/context.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
2
src/gui/core/gravity.h
Normal file → Executable file
2
src/gui/core/gravity.h
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||
#ifndef __GRAVITY_H__
|
#ifndef __GRAVITY_H__
|
||||||
#define __GRAVITY_H__
|
#define __GRAVITY_H__
|
||||||
#include <rect.h>
|
#include <core/rect.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
2
src/gui/core/inputeventlabels.h
Normal file → Executable file
2
src/gui/core/inputeventlabels.h
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
#ifndef __INPUT_EVENT_LABE_H__
|
#ifndef __INPUT_EVENT_LABE_H__
|
||||||
#define __INPUT_EVENT_LABE_H__
|
#define __INPUT_EVENT_LABE_H__
|
||||||
//#include <input.h>
|
//#include <input.h>
|
||||||
#include <keycodes.h>
|
#include <core/keycodes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#define DEFINE_KEYCODE(key) { #key, KEY_##key }
|
#define DEFINE_KEYCODE(key) { #key, KEY_##key }
|
||||||
|
@ -69,29 +69,15 @@ std::shared_ptr<InputDevice>InputEventSource::getdevice(int fd){
|
|||||||
return itr->second;
|
return itr->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputEventSource::prepare(int& max_timeout){
|
int InputEventSource::checkEvents(){
|
||||||
INPUTEVENT es[32];
|
INPUTEVENT es[32];
|
||||||
if(events.size()>0)return TRUE;
|
if(events.size()>0)return TRUE;
|
||||||
int count=InputGetEvents(es,32,1);
|
int count=InputGetEvents(es,32,1);
|
||||||
process(es,count);
|
process(es,count);
|
||||||
return count>0;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int InputEventSource::process(const INPUTEVENT*inevents,int count){
|
int InputEventSource::handleEvents(){
|
||||||
LOGV_IF(count,"%p recv %d events ",this,count);
|
|
||||||
for(int i=0;i<count;i++){
|
|
||||||
const INPUTEVENT*e=inevents+i;
|
|
||||||
std::shared_ptr<InputDevice>dev=getdevice(e->device);
|
|
||||||
if(dev==nullptr){
|
|
||||||
LOGD("%d,%d,%d device=%d ",e->type,e->code,e->value,e->device);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
dev->putrawdata(e);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InputEventSource::processKey(){
|
|
||||||
std::lock_guard<std::mutex> lock(mtxEvents);
|
std::lock_guard<std::mutex> lock(mtxEvents);
|
||||||
if(events.size()==0)return false;
|
if(events.size()==0)return false;
|
||||||
while(events.size()){
|
while(events.size()){
|
||||||
@ -109,8 +95,23 @@ bool InputEventSource::processKey(){
|
|||||||
e->recycle();
|
e->recycle();
|
||||||
events.pop();
|
events.pop();
|
||||||
}
|
}
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int InputEventSource::process(const INPUTEVENT*inevents,int count){
|
||||||
|
LOGV_IF(count,"%p recv %d events ",this,count);
|
||||||
|
for(int i=0;i<count;i++){
|
||||||
|
const INPUTEVENT*e=inevents+i;
|
||||||
|
std::shared_ptr<InputDevice>dev=getdevice(e->device);
|
||||||
|
if(dev==nullptr){
|
||||||
|
LOGD("%d,%d,%d device=%d ",e->type,e->code,e->value,e->device);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dev->putrawdata(e);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int InputEventSource::pushEvent(InputEvent*evt){
|
int InputEventSource::pushEvent(InputEvent*evt){
|
||||||
std::lock_guard<std::mutex> lock(mtxEvents);
|
std::lock_guard<std::mutex> lock(mtxEvents);
|
||||||
events.push(evt);
|
events.push(evt);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef __INPUT_EVENT_SOURCE_H__
|
#ifndef __INPUT_EVENT_SOURCE_H__
|
||||||
#define __INPUT_EVENT_SOURCE_H__
|
#define __INPUT_EVENT_SOURCE_H__
|
||||||
#include <cdinput.h>
|
#include <cdinput.h>
|
||||||
#include <looper/looper.h>
|
#include <core/looper.h>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -18,7 +18,7 @@ namespace GRT{
|
|||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
class InputEventSource:public EventSource{
|
class InputEventSource:public EventHandler{
|
||||||
protected:
|
protected:
|
||||||
std::mutex mtxEvents;
|
std::mutex mtxEvents;
|
||||||
bool isplayback;
|
bool isplayback;
|
||||||
@ -36,12 +36,9 @@ public:
|
|||||||
~InputEventSource();
|
~InputEventSource();
|
||||||
bool initGesture(const std::string&fname);
|
bool initGesture(const std::string&fname);
|
||||||
void playback(const std::string&fname);
|
void playback(const std::string&fname);
|
||||||
bool prepare(int& max_timeout);
|
int checkEvents()override;
|
||||||
bool check(){return events.size()>0;}
|
int handleEvents()override;
|
||||||
bool dispatch(EventHandler &func) { return func(*this); }
|
|
||||||
bool is_file_source() const override final { return false; }
|
|
||||||
int process(const INPUTEVENT*es,int count);
|
int process(const INPUTEVENT*es,int count);
|
||||||
bool processKey();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
2
src/gui/core/layout.h
Normal file → Executable file
2
src/gui/core/layout.h
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||
#ifndef __LAYOUT_H__
|
#ifndef __LAYOUT_H__
|
||||||
#define __LAYOUT_H__
|
#define __LAYOUT_H__
|
||||||
#include <canvas.h>
|
#include <core/canvas.h>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
class Layout{
|
class Layout{
|
||||||
private:
|
private:
|
||||||
|
582
src/gui/core/looper.cc
Executable file
582
src/gui/core/looper.cc
Executable file
@ -0,0 +1,582 @@
|
|||||||
|
#include <looper.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#include <cdtypes.h>
|
||||||
|
#include <cdlog.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <systemclock.h>
|
||||||
|
|
||||||
|
#define DEBUG_POLL_AND_WAKE 0
|
||||||
|
#define DEBUG_CALLBACKS 0
|
||||||
|
|
||||||
|
namespace cdroid{
|
||||||
|
|
||||||
|
static constexpr int EPOLL_SIZE_HINT = 8;
|
||||||
|
// Maximum number of file descriptors for which to retrieve poll events each iteration.
|
||||||
|
static constexpr int EPOLL_MAX_EVENTS = 16;
|
||||||
|
#define toMillisecondTimeoutDelay(n,p) ((n)-(p))
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
static const void * addr_of(T &&obj) noexcept{
|
||||||
|
struct A {};
|
||||||
|
return &reinterpret_cast<const A &>(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::Looper::Request::initEventItem(struct epoll_event* eventItem) const{
|
||||||
|
int epollEvents = 0;
|
||||||
|
if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
|
||||||
|
if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
|
||||||
|
|
||||||
|
memset(eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
|
||||||
|
eventItem->events = epollEvents;
|
||||||
|
eventItem->data.fd = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
Looper::Looper(bool allowNonCallbacks) :
|
||||||
|
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
|
||||||
|
mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
|
||||||
|
mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LONG_MAX) {
|
||||||
|
mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
|
||||||
|
LOGE_IF(mWakeEventFd < 0, "Could not make wake event fd: %s",strerror(errno));
|
||||||
|
std::lock_guard<std::mutex>_l(mLock);
|
||||||
|
rebuildEpollLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
Looper::~Looper() {
|
||||||
|
close(mWakeEventFd);
|
||||||
|
mWakeEventFd = -1;
|
||||||
|
if (mEpollFd >= 0) {
|
||||||
|
close(mEpollFd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Looper*Looper::mInst=nullptr;
|
||||||
|
Looper*Looper::getDefault(){
|
||||||
|
if(mInst==nullptr)mInst=new Looper(false);
|
||||||
|
return mInst;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Looper::getAllowNonCallbacks() const {
|
||||||
|
return mAllowNonCallbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::rebuildEpollLocked() {
|
||||||
|
// Close old epoll instance if we have one.
|
||||||
|
if (mEpollFd >= 0) {
|
||||||
|
LOGV("%p ~ rebuildEpollLocked - rebuilding epoll set", this);
|
||||||
|
close(mEpollFd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the new epoll instance and register the wake pipe.
|
||||||
|
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
|
||||||
|
LOGE_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
|
||||||
|
|
||||||
|
struct epoll_event eventItem;
|
||||||
|
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
|
||||||
|
eventItem.events = EPOLLIN;
|
||||||
|
eventItem.data.fd = mWakeEventFd;
|
||||||
|
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
|
||||||
|
LOGE_IF(result != 0, "Could not add wake event fd to epoll instance: %s",strerror(errno));
|
||||||
|
|
||||||
|
for (auto it=mRequests.begin();it!=mRequests.end(); it++) {
|
||||||
|
const Request& request = it->second;
|
||||||
|
struct epoll_event eventItem;
|
||||||
|
request.initEventItem(&eventItem);
|
||||||
|
|
||||||
|
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);
|
||||||
|
if (epollResult < 0) {
|
||||||
|
LOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",request.fd, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::scheduleEpollRebuildLocked() {
|
||||||
|
if (!mEpollRebuildRequired) {
|
||||||
|
LOGD_IF(DEBUG_CALLBACKS,"%p scheduleEpollRebuildLocked - scheduling epoll set rebuild", this);
|
||||||
|
mEpollRebuildRequired = true;
|
||||||
|
wake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
|
||||||
|
int result = 0;
|
||||||
|
for (;;) {
|
||||||
|
while (mResponseIndex < mResponses.size()) {
|
||||||
|
const Response& response = mResponses.at(mResponseIndex++);
|
||||||
|
int ident = response.request.ident;
|
||||||
|
if (ident >= 0) {
|
||||||
|
int fd = response.request.fd;
|
||||||
|
int events = response.events;
|
||||||
|
void* data = response.request.data;
|
||||||
|
LOGD_IF(DEBUG_POLL_AND_WAKE,"%p pollOnce - returning signalled identifier %d: fd=%d, events=0x%x, data=%p", this, ident, fd, events, data);
|
||||||
|
if (outFd != NULL) *outFd = fd;
|
||||||
|
if (outEvents != NULL) *outEvents = events;
|
||||||
|
if (outData != NULL) *outData = data;
|
||||||
|
return ident;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != 0) {
|
||||||
|
LOGD_IF(DEBUG_POLL_AND_WAKE,"%p pollOnce - returning result %d", this, result);
|
||||||
|
if (outFd != NULL) *outFd = 0;
|
||||||
|
if (outEvents != NULL) *outEvents = 0;
|
||||||
|
if (outData != NULL) *outData = NULL;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = pollInner(timeoutMillis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Looper::pollInner(int timeoutMillis) {
|
||||||
|
LOGD_IF(DEBUG_POLL_AND_WAKE,"%p pollOnce - waiting: timeoutMillis=%d mNextMessageUptime=%lld", this, timeoutMillis,mNextMessageUptime);
|
||||||
|
|
||||||
|
// Adjust the timeout based on when the next message is due.
|
||||||
|
if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
|
||||||
|
nsecs_t now = SystemClock::uptimeMillis();//systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
|
int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
|
||||||
|
if (messageTimeoutMillis >= 0
|
||||||
|
&& (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
|
||||||
|
timeoutMillis = messageTimeoutMillis;
|
||||||
|
}
|
||||||
|
LOGD_IF(DEBUG_POLL_AND_WAKE,"%p pollOnce - next message in %lld ns, adjusted timeout: timeoutMillis=%d",this, mNextMessageUptime - now, timeoutMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Poll.
|
||||||
|
int result = POLL_WAKE;
|
||||||
|
mResponses.clear();
|
||||||
|
mResponseIndex = 0;
|
||||||
|
|
||||||
|
for(auto it=mEventHandlers.begin();it!=mEventHandlers.end();it++){
|
||||||
|
EventHandler*es=(*it);
|
||||||
|
if(es&&(es->mRemoved==0)&&(es->checkEvents()>0)){
|
||||||
|
es->handleEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeEventHandlers();
|
||||||
|
// We are about to idle.
|
||||||
|
mPolling = true;
|
||||||
|
|
||||||
|
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
|
||||||
|
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
|
||||||
|
|
||||||
|
// No longer idling.
|
||||||
|
mPolling = false;
|
||||||
|
|
||||||
|
// Acquire lock.
|
||||||
|
mLock.lock();
|
||||||
|
|
||||||
|
// Rebuild epoll set if needed.
|
||||||
|
if (mEpollRebuildRequired) {
|
||||||
|
mEpollRebuildRequired = false;
|
||||||
|
rebuildEpollLocked();
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for poll error.
|
||||||
|
if (eventCount < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
LOGW("Poll failed with an unexpected error: %s", strerror(errno));
|
||||||
|
result = POLL_ERROR;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for poll timeout.
|
||||||
|
if (eventCount == 0) {
|
||||||
|
LOGD_IF(DEBUG_POLL_AND_WAKE,"%p pollOnce - timeout", this);
|
||||||
|
result = POLL_TIMEOUT;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle all events.
|
||||||
|
LOGD_IF(DEBUG_POLL_AND_WAKE,"%p pollOnce - handling events from %d fds", this, eventCount);
|
||||||
|
|
||||||
|
for (int i = 0; i < eventCount; i++) {
|
||||||
|
int fd = eventItems[i].data.fd;
|
||||||
|
uint32_t epollEvents = eventItems[i].events;
|
||||||
|
if (fd == mWakeEventFd) {
|
||||||
|
if (epollEvents & EPOLLIN) {
|
||||||
|
awoken();
|
||||||
|
} else {
|
||||||
|
LOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto it= mRequests.find(fd);//indexOfKey(fd);
|
||||||
|
if (it!=mRequests.end()){//requestIndex >= 0) {
|
||||||
|
int events = 0;
|
||||||
|
if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
|
||||||
|
if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
|
||||||
|
if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
|
||||||
|
if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
|
||||||
|
pushResponse(events, it->second);//mRequests.at(requestIndex));
|
||||||
|
} else {
|
||||||
|
LOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
|
||||||
|
"no longer registered.", epollEvents, fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Done: ;
|
||||||
|
|
||||||
|
// Invoke pending message callbacks.
|
||||||
|
mNextMessageUptime = LLONG_MAX;
|
||||||
|
LOGD_IF(DEBUG_CALLBACKS,"mMessageEnvelopes.size=%d",mMessageEnvelopes.size());
|
||||||
|
while (mMessageEnvelopes.size() != 0) {
|
||||||
|
nsecs_t now = SystemClock::uptimeMillis();//systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
|
const MessageEnvelope& messageEnvelope = mMessageEnvelopes.front();
|
||||||
|
if (messageEnvelope.uptime <= now) {
|
||||||
|
// Remove the envelope from the list.
|
||||||
|
// We keep a strong reference to the handler until the call to handleMessage
|
||||||
|
// finishes. Then we drop it so that the handler can be deleted *before*
|
||||||
|
// we reacquire our lock.
|
||||||
|
{ // obtain handler
|
||||||
|
MessageHandler* handler = messageEnvelope.handler;
|
||||||
|
Message message = messageEnvelope.message;
|
||||||
|
mMessageEnvelopes.erase(mMessageEnvelopes.begin());//removeAt(0);
|
||||||
|
mSendingMessage = true;
|
||||||
|
mLock.unlock();
|
||||||
|
|
||||||
|
LOGD_IF(DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS,"%p pollOnce - sending message: handler=%p, what=%d", this, handler, message.what);
|
||||||
|
handler->handleMessage(message);
|
||||||
|
} // release handler
|
||||||
|
|
||||||
|
mLock.lock();
|
||||||
|
mSendingMessage = false;
|
||||||
|
result = POLL_CALLBACK;
|
||||||
|
} else {
|
||||||
|
// The last message left at the head of the queue determines the next wakeup time.
|
||||||
|
mNextMessageUptime = messageEnvelope.uptime;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release lock.
|
||||||
|
mLock.unlock();
|
||||||
|
|
||||||
|
// Invoke all response callbacks.
|
||||||
|
for (size_t i = 0; i < mResponses.size(); i++) {
|
||||||
|
Response& response = mResponses.at(i);
|
||||||
|
if (response.request.ident == POLL_CALLBACK) {
|
||||||
|
int fd = response.request.fd;
|
||||||
|
int events = response.events;
|
||||||
|
void* data = response.request.data;
|
||||||
|
LOGD_IF(DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS,"%p pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
|
||||||
|
this, response.request.callback, fd, events, data);
|
||||||
|
|
||||||
|
// Invoke the callback. Note that the file descriptor may be closed by
|
||||||
|
// the callback (and potentially even reused) before the function returns so
|
||||||
|
// we need to be a little careful when removing the file descriptor afterwards.
|
||||||
|
int callbackResult = response.request.callback->handleEvent(fd, events, data);
|
||||||
|
if (callbackResult == 0) {
|
||||||
|
removeFd(fd, response.request.seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the callback reference in the response structure promptly because we
|
||||||
|
// will not clear the response vector itself until the next poll.
|
||||||
|
//response.request.callback.clear();
|
||||||
|
result = POLL_CALLBACK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
|
||||||
|
if (timeoutMillis <= 0) {
|
||||||
|
int result;
|
||||||
|
do {
|
||||||
|
result = pollOnce(timeoutMillis, outFd, outEvents, outData);
|
||||||
|
} while (result == POLL_CALLBACK);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
nsecs_t endTime =SystemClock::uptimeMillis()+timeoutMillis;// systemTime(SYSTEM_TIME_MONOTONIC) + milliseconds_to_nanoseconds(timeoutMillis);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
|
||||||
|
if (result != POLL_CALLBACK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsecs_t now = SystemClock::uptimeMillis();//systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
|
timeoutMillis = toMillisecondTimeoutDelay(now, endTime);
|
||||||
|
if (timeoutMillis == 0) {
|
||||||
|
return POLL_TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TEMP_FAILURE_RETRY defined in <unistd.h>
|
||||||
|
void Looper::wake() {
|
||||||
|
LOGD_IF(DEBUG_POLL_AND_WAKE,"%p wake", this);
|
||||||
|
|
||||||
|
uint64_t inc = 1;
|
||||||
|
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
|
||||||
|
if (nWrite != sizeof(uint64_t)) {
|
||||||
|
LOGE_IF(errno!=EAGAIN,"Could not write wake signal to fd %d: %s",mWakeEventFd, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::awoken() {
|
||||||
|
LOGD_IF(DEBUG_POLL_AND_WAKE,"%p awoken", this);
|
||||||
|
|
||||||
|
uint64_t counter;
|
||||||
|
TEMP_FAILURE_RETRY(read(mWakeEventFd, &counter, sizeof(uint64_t)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::pushResponse(int events, const Request& request) {
|
||||||
|
Response response;
|
||||||
|
response.events = events;
|
||||||
|
response.request = request;
|
||||||
|
mResponses.push_back(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) {
|
||||||
|
return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Looper::addFd(int fd, int ident, int events,const LooperCallback* callback, void* data) {
|
||||||
|
LOGD_IF(DEBUG_CALLBACKS,"%p addFd - fd=%d, ident=%d, events=0x%x, callback=%p, data=%p", this, fd, ident, events, callback, data);
|
||||||
|
|
||||||
|
if (callback==nullptr) {
|
||||||
|
if (! mAllowNonCallbacks) {
|
||||||
|
LOGE("Invalid attempt to set NULL callback but not allowed for this looper.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ident < 0) {
|
||||||
|
LOGE("Invalid attempt to set NULL callback with ident < 0.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ident = POLL_CALLBACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // acquire lock
|
||||||
|
std::lock_guard<std::mutex> _l(mLock);
|
||||||
|
|
||||||
|
Request request;
|
||||||
|
request.fd = fd;
|
||||||
|
request.ident = ident;
|
||||||
|
request.events = events;
|
||||||
|
request.seq = mNextRequestSeq++;
|
||||||
|
request.callback = (LooperCallback*)callback;
|
||||||
|
request.data = data;
|
||||||
|
if (mNextRequestSeq == -1) mNextRequestSeq = 0; // reserve sequence number -1
|
||||||
|
|
||||||
|
struct epoll_event eventItem;
|
||||||
|
request.initEventItem(&eventItem);
|
||||||
|
|
||||||
|
auto itfd = mRequests.find(fd);//indexOfKey(fd);
|
||||||
|
if (itfd==mRequests.end()) {
|
||||||
|
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
|
||||||
|
if (epollResult < 0) {
|
||||||
|
LOGE("Error adding epoll events for fd %d: %s", fd, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mRequests[fd]=request;//.add(fd, request);
|
||||||
|
} else {
|
||||||
|
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
|
||||||
|
if (epollResult < 0) {
|
||||||
|
if (errno == ENOENT) {
|
||||||
|
// Tolerate ENOENT because it means that an older file descriptor was
|
||||||
|
// closed before its callback was unregistered and meanwhile a new
|
||||||
|
// file descriptor with the same number has been created and is now
|
||||||
|
// being registered for the first time. This error may occur naturally
|
||||||
|
// when a callback has the side-effect of closing the file descriptor
|
||||||
|
// before returning and unregistering itself. Callback sequence number
|
||||||
|
// checks further ensure that the race is benign.
|
||||||
|
//
|
||||||
|
// Unfortunately due to kernel limitations we need to rebuild the epoll
|
||||||
|
// set from scratch because it may contain an old file handle that we are
|
||||||
|
// now unable to remove since its file descriptor is no longer valid.
|
||||||
|
// No such problem would have occurred if we were using the poll system
|
||||||
|
// call instead, but that approach carries others disadvantages.
|
||||||
|
LOGD_IF(DEBUG_CALLBACKS,"%p addFd - EPOLL_CTL_MOD failed due to file descriptor "
|
||||||
|
"being recycled, falling back on EPOLL_CTL_ADD: %s", this, strerror(errno));
|
||||||
|
epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
|
||||||
|
if (epollResult < 0) {
|
||||||
|
LOGE("Error modifying or adding epoll events for fd %d: %s", fd, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
scheduleEpollRebuildLocked();
|
||||||
|
} else {
|
||||||
|
LOGE("Error modifying epoll events for fd %d: %s", fd, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
itfd->second=request;//mRequests.replaceValueAt(requestIndex, request);
|
||||||
|
}
|
||||||
|
} // release lock
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Looper::removeFd(int fd) {
|
||||||
|
return removeFd(fd, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Looper::removeFd(int fd, int seq) {
|
||||||
|
LOGD_IF(DEBUG_CALLBACKS,"%p removeFd - fd=%d, seq=%d", this, fd, seq);
|
||||||
|
|
||||||
|
{ // acquire lock
|
||||||
|
std::lock_guard<std::mutex> _l(mLock);
|
||||||
|
auto itr= mRequests.find(fd);//indexOfKey(fd);
|
||||||
|
if (itr==mRequests.end()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the sequence number if one was given.
|
||||||
|
if (seq != -1 && itr->second.seq != seq) {
|
||||||
|
LOGD_IF(DEBUG_CALLBACKS,"%p removeFd - sequence number mismatch, oldSeq=%d", this, itr->second.seq);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always remove the FD from the request map even if an error occurs while
|
||||||
|
// updating the epoll set so that we avoid accidentally leaking callbacks.
|
||||||
|
mRequests.erase(itr);//removeItemsAt(requestIndex);
|
||||||
|
|
||||||
|
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_DEL, fd, NULL);
|
||||||
|
if (epollResult < 0) {
|
||||||
|
if (seq != -1 && (errno == EBADF || errno == ENOENT)) {
|
||||||
|
// Tolerate EBADF or ENOENT when the sequence number is known because it
|
||||||
|
// means that the file descriptor was closed before its callback was
|
||||||
|
// unregistered. This error may occur naturally when a callback has the
|
||||||
|
// side-effect of closing the file descriptor before returning and
|
||||||
|
// unregistering itself.
|
||||||
|
//
|
||||||
|
// Unfortunately due to kernel limitations we need to rebuild the epoll
|
||||||
|
// set from scratch because it may contain an old file handle that we are
|
||||||
|
// now unable to remove since its file descriptor is no longer valid.
|
||||||
|
// No such problem would have occurred if we were using the poll system
|
||||||
|
// call instead, but that approach carries others disadvantages.
|
||||||
|
LOGD_IF(DEBUG_CALLBACKS,"%p removeFd - EPOLL_CTL_DEL failed due to file descriptor "
|
||||||
|
"being closed: %s", this, strerror(errno));
|
||||||
|
scheduleEpollRebuildLocked();
|
||||||
|
} else {
|
||||||
|
// Some other error occurred. This is really weird because it means
|
||||||
|
// our list of callbacks got out of sync with the epoll set somehow.
|
||||||
|
// We defensively rebuild the epoll set to avoid getting spurious
|
||||||
|
// notifications with nowhere to go.
|
||||||
|
LOGE("Error removing epoll events for fd %d: %s", fd, strerror(errno));
|
||||||
|
scheduleEpollRebuildLocked();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // release lock
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::sendMessage(const MessageHandler* handler, const Message& message) {
|
||||||
|
nsecs_t now = SystemClock::uptimeMillis();//systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
|
sendMessageAtTime(now, handler, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::sendMessageDelayed(nsecs_t uptimeDelay, const MessageHandler* handler,
|
||||||
|
const Message& message) {
|
||||||
|
nsecs_t now = SystemClock::uptimeMillis();//systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
|
sendMessageAtTime(now + uptimeDelay, handler, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::sendMessageAtTime(nsecs_t uptime, const MessageHandler* handler,
|
||||||
|
const Message& message) {
|
||||||
|
LOGD_IF(DEBUG_CALLBACKS,"%p sendMessageAtTime - uptime=%lld, handler=%p, what=%d", this, uptime, handler, message.what);
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
{ // acquire lock
|
||||||
|
std::lock_guard<std::mutex> _l(mLock);
|
||||||
|
|
||||||
|
std::list<MessageEnvelope>::iterator it;
|
||||||
|
for(it=mMessageEnvelopes.begin();it!=mMessageEnvelopes.end();it++){
|
||||||
|
if(uptime>=it->uptime)break;
|
||||||
|
i+=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageEnvelope messageEnvelope(uptime,(MessageHandler*)handler, message);
|
||||||
|
mMessageEnvelopes.insert(it,messageEnvelope);
|
||||||
|
|
||||||
|
// Optimization: If the Looper is currently sending a message, then we can skip
|
||||||
|
// the call to wake() because the next thing the Looper will do after processing
|
||||||
|
// messages is to decide when the next wakeup time should be. In fact, it does
|
||||||
|
// not even matter whether this code is running on the Looper thread.
|
||||||
|
if (mSendingMessage) return;
|
||||||
|
} // release lock
|
||||||
|
|
||||||
|
// Wake the poll loop only when we enqueue a new message at the head.
|
||||||
|
if (i == 0) wake();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::addEventHandler(const EventHandler*handler){
|
||||||
|
mEventHandlers.insert(mEventHandlers.begin(),(EventHandler*)handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::removeEventHandler(const EventHandler*handler){
|
||||||
|
for(auto it=mEventHandlers.begin();it!=mEventHandlers.end();it++){
|
||||||
|
if((*it)==handler){
|
||||||
|
(*it)->mRemoved=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::removeEventHandlers(){
|
||||||
|
for(auto it=mEventHandlers.begin();it!=mEventHandlers.end();it++){
|
||||||
|
if((*it)->mRemoved){
|
||||||
|
EventHandler*handler=(*it);
|
||||||
|
it=mEventHandlers.erase(it);
|
||||||
|
LOGD(" %p",(*it));
|
||||||
|
delete handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::removeMessages(const MessageHandler* handler) {
|
||||||
|
LOGD_IF(DEBUG_CALLBACKS,"%p removeMessages - handler=%p", this, handler);
|
||||||
|
|
||||||
|
{ // acquire lock
|
||||||
|
std::lock_guard<std::mutex>_l(mLock);
|
||||||
|
|
||||||
|
for( auto it=mMessageEnvelopes.begin();it!=mMessageEnvelopes.end();it++){
|
||||||
|
if(it->handler==handler)
|
||||||
|
it=mMessageEnvelopes.erase(it);
|
||||||
|
}
|
||||||
|
} // release lock
|
||||||
|
}
|
||||||
|
|
||||||
|
void Looper::removeMessages(const MessageHandler* handler, int what) {
|
||||||
|
LOGD_IF(DEBUG_CALLBACKS,"%p removeMessages - handler=%p, what=%d size=%d", this, handler, what,mMessageEnvelopes.size());
|
||||||
|
|
||||||
|
{ // acquire lock
|
||||||
|
std::lock_guard<std::mutex>_l(mLock);
|
||||||
|
for( auto it=mMessageEnvelopes.begin();it!=mMessageEnvelopes.end();it++){
|
||||||
|
LOGD("addr=%p,%p what=%d,%d",addr_of(it->handler),addr_of(handler),it->message.what,what);
|
||||||
|
if((it->handler==handler) && (it->message.what==what)){
|
||||||
|
it=mMessageEnvelopes.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // release lock
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Looper::isPolling() const {
|
||||||
|
return mPolling;
|
||||||
|
}
|
||||||
|
|
||||||
|
LooperCallback::~LooperCallback(){
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleLooperCallback::SimpleLooperCallback(Looper_callbackFunc callback) :
|
||||||
|
mCallback(callback) {
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleLooperCallback::~SimpleLooperCallback() {
|
||||||
|
}
|
||||||
|
|
||||||
|
int SimpleLooperCallback::handleEvent(int fd, int events, void* data) {
|
||||||
|
return mCallback(fd, events, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageHandler::~MessageHandler(){
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandler::~EventHandler(){
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -4,10 +4,13 @@
|
|||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
namespace alooper{
|
#include <mutex>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
namespace cdroid{
|
||||||
|
|
||||||
typedef int64_t nsecs_t;
|
typedef int64_t nsecs_t;
|
||||||
typedef std::function<int(int fd, int events, void* data)>LooperCallback;
|
|
||||||
struct Message {
|
struct Message {
|
||||||
Message() : what(0) { }
|
Message() : what(0) { }
|
||||||
Message(int w) : what(w) { }
|
Message(int w) : what(w) { }
|
||||||
@ -16,15 +19,42 @@ struct Message {
|
|||||||
int what;
|
int what;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef int (*Looper_callbackFunc)(int fd, int events, void* data);
|
||||||
|
|
||||||
|
class LooperCallback{
|
||||||
|
protected:
|
||||||
|
virtual ~LooperCallback();
|
||||||
|
public:
|
||||||
|
virtual int handleEvent(int fd, int events, void* data) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SimpleLooperCallback : public LooperCallback {
|
||||||
|
protected:
|
||||||
|
virtual ~SimpleLooperCallback();
|
||||||
|
public:
|
||||||
|
SimpleLooperCallback(Looper_callbackFunc callback);
|
||||||
|
virtual int handleEvent(int fd, int events, void* data);
|
||||||
|
private:
|
||||||
|
Looper_callbackFunc mCallback;
|
||||||
|
};
|
||||||
|
|
||||||
class MessageHandler{
|
class MessageHandler{
|
||||||
protected:
|
protected:
|
||||||
virtual ~MessageHandler();
|
virtual ~MessageHandler();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Handles a message. */
|
virtual void handleMessage(const Message& message)=0;
|
||||||
virtual void handleMessage(const Message& message) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EventHandler{
|
||||||
|
private:
|
||||||
|
int mRemoved=0;
|
||||||
|
friend class Looper;
|
||||||
|
protected:
|
||||||
|
virtual ~EventHandler();
|
||||||
|
public:
|
||||||
|
virtual int checkEvents()=0;
|
||||||
|
virtual int handleEvents()=0;
|
||||||
|
};
|
||||||
class Looper{
|
class Looper{
|
||||||
private:
|
private:
|
||||||
struct Request {
|
struct Request {
|
||||||
@ -32,7 +62,7 @@ private:
|
|||||||
int ident;
|
int ident;
|
||||||
int events;
|
int events;
|
||||||
int seq;
|
int seq;
|
||||||
LooperCallback callback;
|
LooperCallback* callback;
|
||||||
void* data;
|
void* data;
|
||||||
void initEventItem(struct epoll_event* eventItem) const;
|
void initEventItem(struct epoll_event* eventItem) const;
|
||||||
};
|
};
|
||||||
@ -54,10 +84,11 @@ private:
|
|||||||
bool mAllowNonCallbacks; // immutable
|
bool mAllowNonCallbacks; // immutable
|
||||||
|
|
||||||
int mWakeEventFd; // immutable
|
int mWakeEventFd; // immutable
|
||||||
//Mutex mLock;
|
std::mutex mLock;
|
||||||
|
|
||||||
std::vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
|
std::list<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
|
||||||
bool mSendingMessage; // guarded by mLock
|
bool mSendingMessage; // guarded by mLock
|
||||||
|
std::list<EventHandler*> mEventHandlers;
|
||||||
|
|
||||||
// Whether we are currently waiting for work. Not protected by a lock,
|
// Whether we are currently waiting for work. Not protected by a lock,
|
||||||
// any use of it is racy anyway.
|
// any use of it is racy anyway.
|
||||||
@ -75,14 +106,16 @@ private:
|
|||||||
std::vector<Response> mResponses;
|
std::vector<Response> mResponses;
|
||||||
size_t mResponseIndex;
|
size_t mResponseIndex;
|
||||||
nsecs_t mNextMessageUptime;
|
nsecs_t mNextMessageUptime;
|
||||||
|
static Looper*mInst;
|
||||||
private:
|
private:
|
||||||
int pollInner(int timeoutMillis);
|
int pollInner(int timeoutMillis);
|
||||||
int removeFd(int fd, int seq);
|
int removeFd(int fd, int seq);
|
||||||
void awoken();
|
void awoken();
|
||||||
void pushResponse(int events, const Request& request);
|
void pushResponse(int events, const Request& request);
|
||||||
void rebuildEpollLocked();
|
void rebuildEpollLocked();
|
||||||
|
void scheduleEpollRebuildLocked();
|
||||||
|
void removeEventHandlers();
|
||||||
protected:
|
protected:
|
||||||
virtual ~Looper(){};
|
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
POLL_WAKE = -1,
|
POLL_WAKE = -1,
|
||||||
@ -103,6 +136,8 @@ public:
|
|||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
Looper(bool allowNonCallbacks=false);
|
Looper(bool allowNonCallbacks=false);
|
||||||
|
virtual ~Looper();
|
||||||
|
static Looper*getDefault();
|
||||||
bool getAllowNonCallbacks() const;
|
bool getAllowNonCallbacks() const;
|
||||||
int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
|
int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
|
||||||
inline int pollOnce(int timeoutMillis) {
|
inline int pollOnce(int timeoutMillis) {
|
||||||
@ -113,13 +148,16 @@ public:
|
|||||||
return pollAll(timeoutMillis, NULL, NULL, NULL);
|
return pollAll(timeoutMillis, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
void wake();
|
void wake();
|
||||||
int addFd(int fd, int ident, int events, LooperCallback callback, void* data);
|
int addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data);
|
||||||
|
int addFd(int fd, int ident, int events,const LooperCallback* callback, void* data);
|
||||||
int removeFd(int fd);
|
int removeFd(int fd);
|
||||||
void sendMessage(MessageHandler& handler, const Message& message);
|
void sendMessage(const MessageHandler* handler, const Message& message);
|
||||||
void sendMessageDelayed(nsecs_t uptimeDelay, const MessageHandler& handler,const Message& message);
|
void sendMessageDelayed(nsecs_t uptimeDelay, const MessageHandler* handler,const Message& message);
|
||||||
void sendMessageAtTime(nsecs_t uptime, const MessageHandler& handler,const Message& message);
|
void sendMessageAtTime(nsecs_t uptime, const MessageHandler* handler,const Message& message);
|
||||||
void removeMessages(const MessageHandler& handler);
|
void removeMessages(const MessageHandler* handler);
|
||||||
void removeMessages(const MessageHandler& handler, int what);
|
void removeMessages(const MessageHandler* handler, int what);
|
||||||
|
void addEventHandler(const EventHandler*handler);
|
||||||
|
void removeEventHandler(const EventHandler*handler);
|
||||||
bool isPolling() const;
|
bool isPolling() const;
|
||||||
|
|
||||||
};
|
};
|
14
src/gui/core/scheduler.cc
Normal file → Executable file
14
src/gui/core/scheduler.cc
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||
#include<scheduler.h>
|
#include <core/scheduler.h>
|
||||||
#include<cdtypes.h>
|
#include <cdtypes.h>
|
||||||
#include<cdlog.h>
|
#include <cdlog.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
@ -15,10 +15,6 @@ static void Repeat2(Scheduler* s, Scheduler::Function f,system_clock::time_point
|
|||||||
s->schedule(std::bind(&Repeat2,s,f,t,deltaSeconds),t);
|
s->schedule(std::bind(&Repeat2,s,f,t,deltaSeconds),t);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scheduler::dispatch(EventHandler &func){
|
|
||||||
/*check(),check will be called by looper*/;
|
|
||||||
return func(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scheduler::schedule(Function f,system_clock::time_point t){
|
void Scheduler::schedule(Function f,system_clock::time_point t){
|
||||||
if(t>system_clock::now())
|
if(t>system_clock::now())
|
||||||
@ -63,6 +59,9 @@ void Scheduler::remove(system_clock::time_point t){
|
|||||||
taskQueue.erase(it);
|
taskQueue.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scheduler::handleMessage(const Message&){
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
bool Scheduler::check(){
|
bool Scheduler::check(){
|
||||||
auto task=taskQueue.begin();
|
auto task=taskQueue.begin();
|
||||||
if(taskQueue.size()==0)return 0;
|
if(taskQueue.size()==0)return 0;
|
||||||
@ -76,5 +75,6 @@ bool Scheduler::check(){
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}/*namespace cdroid*/
|
}/*namespace cdroid*/
|
||||||
|
14
src/gui/core/scheduler.h
Normal file → Executable file
14
src/gui/core/scheduler.h
Normal file → Executable file
@ -1,14 +1,14 @@
|
|||||||
#ifndef __SHCEDULE_H__
|
#ifndef __SHCEDULE_H__
|
||||||
#define __SHCEDULE_H__
|
#define __SHCEDULE_H__
|
||||||
#include<chrono>
|
#include <chrono>
|
||||||
#include<functional>
|
#include <functional>
|
||||||
#include<map>
|
#include <map>
|
||||||
#include <looper/looper.h>
|
#include <core/looper.h>
|
||||||
|
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
class Scheduler:public EventSource{
|
class Scheduler:public MessageHandler{
|
||||||
public:
|
public:
|
||||||
typedef std::function<void(void)> Function;
|
typedef std::function<void(void)> Function;
|
||||||
private:
|
private:
|
||||||
@ -22,10 +22,8 @@ public:
|
|||||||
void scheduleDaily(Function f,system_clock::time_point t);
|
void scheduleDaily(Function f,system_clock::time_point t);
|
||||||
void scheduleWeekly(Function f,system_clock::time_point t);
|
void scheduleWeekly(Function f,system_clock::time_point t);
|
||||||
void scheduleMonthly(Function f,system_clock::time_point t);/*TODO*/
|
void scheduleMonthly(Function f,system_clock::time_point t);/*TODO*/
|
||||||
|
|
||||||
virtual void remove(system_clock::time_point t);
|
virtual void remove(system_clock::time_point t);
|
||||||
bool dispatch(EventHandler &func)override;
|
void handleMessage(const Message&)override;
|
||||||
bool check()override;/*check schedulered item*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
4
src/gui/core/scroller.h
Normal file → Executable file
4
src/gui/core/scroller.h
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
#ifndef __SCROLLER_H__
|
#ifndef __SCROLLER_H__
|
||||||
#define __SCROLLER_H__
|
#define __SCROLLER_H__
|
||||||
#include <interpolators.h>
|
#include <animation/interpolators.h>
|
||||||
#include <context.h>
|
#include <core/context.h>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
class Scroller {
|
class Scroller {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#ifndef __NGL_UIEVENTS_H__
|
#ifndef __NGL_UIEVENTS_H__
|
||||||
#define __NGL_UIEVENTS_H__
|
#define __NGL_UIEVENTS_H__
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <eventcodes.h>
|
#include <core/eventcodes.h>
|
||||||
#include <sparsearray.h>
|
#include <core/sparsearray.h>
|
||||||
#include <bitset.h>
|
#include <core/bitset.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
144
src/gui/core/uieventsource.cc
Normal file → Executable file
144
src/gui/core/uieventsource.cc
Normal file → Executable file
@ -8,135 +8,59 @@
|
|||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
bool operator>(const UIMSG&m1,const UIMSG m2){
|
|
||||||
return m1.time>m2.time;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const UIMSG&m1,const UIMSG m2){
|
|
||||||
return m1.msgid==m2.msgid;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
static const void * addr_of(T &&obj) noexcept{
|
|
||||||
struct A {};
|
|
||||||
return &reinterpret_cast<const A &>(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
UIEventSource::UIEventSource(View*v){
|
UIEventSource::UIEventSource(View*v){
|
||||||
mAttachedView=v;
|
mAttachedView=v;
|
||||||
|
mID=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIEventSource::~UIEventSource(){
|
UIEventSource::~UIEventSource(){
|
||||||
}
|
}
|
||||||
|
|
||||||
int UIEventSource::getEvents(){
|
int UIEventSource::checkEvents(){
|
||||||
return normal_msgs.size()||hasDelayedMessage()||(mAttachedView&&mAttachedView->isDirty())||GraphDevice::getInstance().needCompose();
|
int rc= hasDelayedRunners()+(mAttachedView&&mAttachedView->isDirty())+GraphDevice::getInstance().needCompose();
|
||||||
}
|
|
||||||
|
|
||||||
bool UIEventSource::processEvents(){
|
|
||||||
bool rc=popMessage();//called by Dispatch,return false the source will be killed
|
|
||||||
if(GraphDevice::getInstance().needCompose())
|
|
||||||
GraphDevice::getInstance().ComposeSurfaces();
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIEventSource::dispatch(EventHandler &func){
|
int UIEventSource::handleEvents(){
|
||||||
if(func)return func(*this);
|
|
||||||
return processEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIEventSource::reset(){
|
|
||||||
while(!delayed_msgs.empty())delayed_msgs.pop_front();
|
|
||||||
while(!normal_msgs.empty())normal_msgs.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIEventSource::sendMessage(View*v,DWORD msgid,DWORD wp,ULONG lp,DWORD delayedtime){
|
|
||||||
postMessage(v,msgid,wp,lp,nullptr,delayedtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIEventSource::postMessage(View*v,DWORD msgid,DWORD wp,ULONG lp,const Runnable action,DWORD delayedtime){
|
|
||||||
UIMSG msg;
|
|
||||||
msg.view=v;
|
|
||||||
msg.msgid=msgid;
|
|
||||||
msg.wParam=wp;
|
|
||||||
msg.lParam=lp;
|
|
||||||
msg.runnable=action;
|
|
||||||
if(delayedtime!=0||action!=nullptr){
|
|
||||||
msg.time=SystemClock::uptimeMillis()+delayedtime;
|
|
||||||
for(auto itr=delayed_msgs.begin();itr!=delayed_msgs.end();itr++){
|
|
||||||
if(msg.time<itr->time){
|
|
||||||
delayed_msgs.insert(itr,msg);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delayed_msgs.push_back(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
normal_msgs.push_back(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIEventSource::post(View*v,const Runnable run,DWORD delayedtime){
|
|
||||||
postMessage(v,0,0,0,run,delayedtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UIEventSource::removeCallbacks(const Runnable what){
|
|
||||||
normal_msgs.remove_if([&](const UIMSG & m)->bool{
|
|
||||||
return (m.msgid==0) && (addr_of(m.runnable)==addr_of(what));
|
|
||||||
});
|
|
||||||
delayed_msgs.remove_if([&](const UIMSG& m)->bool{
|
|
||||||
return (m.msgid==0) && (addr_of(m.runnable)==addr_of(what));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UIEventSource::hasDelayedMessage(){
|
|
||||||
UIMSG msg;
|
|
||||||
if(delayed_msgs.empty())return false;
|
|
||||||
ULONGLONG nowms=SystemClock::uptimeMillis();
|
|
||||||
msg=delayed_msgs.front();
|
|
||||||
return msg.time<nowms;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UIEventSource::popMessage(){
|
|
||||||
UIMSG msg={0};
|
|
||||||
if(normal_msgs.size()){
|
|
||||||
msg=normal_msgs.front();
|
|
||||||
normal_msgs.pop_front();
|
|
||||||
}else if(hasDelayedMessage()){
|
|
||||||
msg=delayed_msgs.front();
|
|
||||||
delayed_msgs.pop_front();
|
|
||||||
}
|
|
||||||
if (mAttachedView && mAttachedView->isDirty()){
|
if (mAttachedView && mAttachedView->isDirty()){
|
||||||
mAttachedView->draw();
|
mAttachedView->draw();
|
||||||
GraphDevice::getInstance().flip();
|
GraphDevice::getInstance().flip();
|
||||||
}
|
}
|
||||||
if(msg.view){
|
if(GraphDevice::getInstance().needCompose())
|
||||||
msg.view->onMessage(msg.msgid,msg.wParam,msg.lParam);
|
GraphDevice::getInstance().ComposeSurfaces();
|
||||||
|
if(hasDelayedRunners()){
|
||||||
|
size_t old=mRunnables.size();
|
||||||
|
RUNNER runner=mRunnables.front();
|
||||||
|
runner.run();
|
||||||
|
mRunnables.erase(mRunnables.begin());
|
||||||
}
|
}
|
||||||
switch(msg.msgid){
|
return 0;
|
||||||
case View::WM_DESTROY:
|
|
||||||
WindowManager::getInstance().removeWindow(static_cast<Window*>(msg.view));
|
|
||||||
return false;//return false to tell Eventsource::Dispath,and EventLooper will remove the source.
|
|
||||||
case View::WM_ACTIVE:
|
|
||||||
if(msg.wParam)dynamic_cast<Window*>(msg.view)->onActive();
|
|
||||||
else dynamic_cast<Window*>(msg.view)->onDeactive();
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
if(msg.runnable)msg.runnable();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIEventSource::hasMessage(const View*v,DWORD msgid){
|
void UIEventSource::post(Runnable& run,DWORD delayedtime){
|
||||||
const UIMSG msg={(View*)v,msgid};
|
RUNNER runner;
|
||||||
return delayed_msgs.end()==std::find(delayed_msgs.begin(),delayed_msgs.end(),msg);
|
runner.time=SystemClock::uptimeMillis()+delayedtime;
|
||||||
|
runner.run.ID=mID++;
|
||||||
|
runner.run=run;
|
||||||
|
for(auto itr=mRunnables.begin();itr!=mRunnables.end();itr++){
|
||||||
|
if(runner.time<itr->time){
|
||||||
|
mRunnables.insert(itr,runner);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mRunnables.push_back(runner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIEventSource::removeMessage(const View*v,DWORD msgid){
|
bool UIEventSource::hasDelayedRunners()const{
|
||||||
normal_msgs.remove_if([&](const UIMSG& m)->bool{
|
if(mRunnables.empty())return false;
|
||||||
return (m.msgid==msgid)&&(m.view==v);
|
nsecs_t nowms=SystemClock::uptimeMillis();
|
||||||
});
|
RUNNER runner=mRunnables.front();
|
||||||
delayed_msgs.remove_if([&](const UIMSG& m)->bool{
|
return runner.time<nowms;
|
||||||
return m.msgid==msgid&&m.view==v;
|
}
|
||||||
|
|
||||||
|
void UIEventSource::removeCallbacks(const Runnable& what){
|
||||||
|
mRunnables.remove_if([&](const RUNNER& m)->bool{
|
||||||
|
return (m.run.ID==what.ID);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
src/gui/core/uieventsource.h
Normal file → Executable file
42
src/gui/core/uieventsource.h
Normal file → Executable file
@ -1,43 +1,29 @@
|
|||||||
#ifndef __UIEVENT_SOURCE_H__
|
#ifndef __UIEVENT_SOURCE_H__
|
||||||
#define __UIEVENT_SOURCE_H__
|
#define __UIEVENT_SOURCE_H__
|
||||||
#include <looper/looper.h>
|
#include <core/looper.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <widget/view.h>
|
#include <widget/view.h>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
class View;
|
|
||||||
typedef struct{
|
class UIEventSource:public EventHandler{
|
||||||
View*view;
|
|
||||||
DWORD msgid;
|
|
||||||
DWORD wParam;
|
|
||||||
ULONG lParam;
|
|
||||||
Runnable runnable;
|
|
||||||
ULONG time;
|
|
||||||
}UIMSG;
|
|
||||||
class UIEventSource:public EventSource{
|
|
||||||
private:
|
private:
|
||||||
std::list<UIMSG> normal_msgs;
|
int mID;
|
||||||
std::list<UIMSG> delayed_msgs;
|
typedef struct{
|
||||||
bool hasDelayedMessage();
|
nsecs_t time;
|
||||||
|
Runnable run;
|
||||||
|
}RUNNER;
|
||||||
|
std::list<RUNNER>mRunnables;
|
||||||
View*mAttachedView;
|
View*mAttachedView;
|
||||||
bool popMessage();
|
bool hasDelayedRunners()const;
|
||||||
void postMessage(View*,DWORD msgid,DWORD wp,ULONG lp,const Runnable action,DWORD delayedtime=0);
|
|
||||||
public:
|
public:
|
||||||
UIEventSource(View*);
|
UIEventSource(View*);
|
||||||
~UIEventSource();
|
~UIEventSource();
|
||||||
void reset();
|
|
||||||
int getEvents();
|
|
||||||
bool prepare(int&) override { return getEvents();}
|
|
||||||
bool check(){
|
|
||||||
return getEvents();
|
|
||||||
}
|
|
||||||
bool dispatch(EventHandler &func)override;
|
|
||||||
bool processEvents();
|
bool processEvents();
|
||||||
bool hasMessage(const View*,DWORD msgid);
|
int checkEvents()override;
|
||||||
void removeMessage(const View*,DWORD msgid);
|
int handleEvents()override;
|
||||||
void sendMessage(View*,DWORD msgid,DWORD wp,ULONG lp,DWORD delayedtime=0);
|
void post(Runnable& run,DWORD delay=0);
|
||||||
void post(View*v,const Runnable run,DWORD delay=0);
|
void removeCallbacks(const Runnable& what);
|
||||||
void removeCallbacks(const Runnable what);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}//end namespace
|
}//end namespace
|
||||||
|
2
src/gui/core/velocitytracker.h
Normal file → Executable file
2
src/gui/core/velocitytracker.h
Normal file → Executable file
@ -1,8 +1,8 @@
|
|||||||
#ifndef __VELOCITY_TRACKER_H__
|
#ifndef __VELOCITY_TRACKER_H__
|
||||||
#define __VELOCITY_TRACKER_H__
|
#define __VELOCITY_TRACKER_H__
|
||||||
|
|
||||||
#include <uievents.h>
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <core/uievents.h>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
typedef int64_t nsecs_t;
|
typedef int64_t nsecs_t;
|
||||||
class VelocityTrackerStrategy;
|
class VelocityTrackerStrategy;
|
||||||
|
@ -58,12 +58,15 @@ void WindowManager::addWindow(Window*win){
|
|||||||
w->mLayer=w->window_type*10000+(idx-type_idx)*5;
|
w->mLayer=w->window_type*10000+(idx-type_idx)*5;
|
||||||
LOGV("%p window %p[%s] type=%d layer=%d",win,w,w->getText().c_str(),w->window_type,w->mLayer);
|
LOGV("%p window %p[%s] type=%d layer=%d",win,w,w->getText().c_str(),w->window_type,w->mLayer);
|
||||||
}
|
}
|
||||||
if(activeWindow)activeWindow->source->sendMessage(activeWindow,View::WM_ACTIVE,0,0);
|
Runnable onact;
|
||||||
win->source->sendMessage(win,View::WM_ACTIVE,1,0);
|
if(activeWindow){
|
||||||
|
onact=std::bind(&Window::onDeactive,activeWindow);
|
||||||
|
activeWindow->post(onact);
|
||||||
|
}
|
||||||
|
onact=std::bind(&Window::onActive,win);
|
||||||
|
win->post(onact);
|
||||||
activeWindow=win;
|
activeWindow=win;
|
||||||
Looper::getDefault()->add_event_source(win->source,[](EventSource&e)->bool{
|
Looper::getDefault()->addEventHandler(win->source);
|
||||||
return ((UIEventSource&)e).processEvents();
|
|
||||||
});
|
|
||||||
resetVisibleRegion();
|
resetVisibleRegion();
|
||||||
LOGV("win=%p source=%p windows.size=%d",win,win->source,windows.size());
|
LOGV("win=%p source=%p windows.size=%d",win,win->source,windows.size());
|
||||||
}
|
}
|
||||||
@ -76,13 +79,14 @@ void WindowManager::removeWindow(Window*w){
|
|||||||
const RECT wrect=w->getBound();
|
const RECT wrect=w->getBound();
|
||||||
windows.erase(itw);
|
windows.erase(itw);
|
||||||
resetVisibleRegion();
|
resetVisibleRegion();
|
||||||
for(auto itr=windows.begin();itr!=windows.end();itr++){//!=windows.end()){
|
for(auto itr=windows.begin();itr!=windows.end();itr++){
|
||||||
Window*w1=(*itr);
|
Window*w1=(*itr);
|
||||||
RECT rc=w1->getBound();
|
RECT rc=w1->getBound();
|
||||||
rc.intersect(wrect);
|
rc.intersect(wrect);
|
||||||
rc.offset(-w1->getX(),-w1->getY());
|
rc.offset(-w1->getX(),-w1->getY());
|
||||||
w1->invalidate(&rc);
|
w1->invalidate(&rc);
|
||||||
}
|
}
|
||||||
|
Looper::getDefault()->removeEventHandler(w->source);
|
||||||
delete w;
|
delete w;
|
||||||
for(auto it=windows.rbegin();it!=windows.rend();it++){
|
for(auto it=windows.rbegin();it!=windows.rend();it++){
|
||||||
if((*it)->hasFlag(View::FOCUSABLE)&&(*it)->getVisibility()==View::VISIBLE){
|
if((*it)->hasFlag(View::FOCUSABLE)&&(*it)->getVisibility()==View::VISIBLE){
|
||||||
@ -116,7 +120,7 @@ void WindowManager::moveWindow(Window*w,int x,int y){
|
|||||||
|
|
||||||
void WindowManager::broadcast(DWORD msgid,DWORD wParam,ULONG lParam){
|
void WindowManager::broadcast(DWORD msgid,DWORD wParam,ULONG lParam){
|
||||||
for(auto win:windows)
|
for(auto win:windows)
|
||||||
win->sendMessage(msgid,wParam,lParam);
|
;//win->sendMessage(msgid,wParam,lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
int WindowManager::enumWindows(WNDENUMPROC cbk){
|
int WindowManager::enumWindows(WNDENUMPROC cbk){
|
||||||
|
2
src/gui/drawables/colorfilters.h
Normal file → Executable file
2
src/gui/drawables/colorfilters.h
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
#ifndef __COLOR_FILTERS_H__
|
#ifndef __COLOR_FILTERS_H__
|
||||||
#define __COLOR_FILTERS_H__
|
#define __COLOR_FILTERS_H__
|
||||||
#include <drawables/colormatrix.h>
|
#include <drawables/colormatrix.h>
|
||||||
#include <canvas.h>
|
#include <core/canvas.h>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
enum TintMode{
|
enum TintMode{
|
||||||
CLEAR =0,
|
CLEAR =0,
|
||||||
|
4
src/gui/drawables/colorstatelist.h
Normal file → Executable file
4
src/gui/drawables/colorstatelist.h
Normal file → Executable file
@ -2,8 +2,8 @@
|
|||||||
#define __COLOR_STATE_LIST_H__
|
#define __COLOR_STATE_LIST_H__
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <context.h>
|
#include <core/context.h>
|
||||||
#include <attributeset.h>
|
#include <core/attributeset.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
class ComplexColor{
|
class ComplexColor{
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
#ifndef __DRAWABLE_H__
|
#ifndef __DRAWABLE_H__
|
||||||
#define __DRAWABLE_H__
|
#define __DRAWABLE_H__
|
||||||
#include <canvas.h>
|
#include <core/canvas.h>
|
||||||
#include <drawables/stateset.h>
|
#include <drawables/stateset.h>
|
||||||
#include <drawables/colorstatelist.h>
|
#include <drawables/colorstatelist.h>
|
||||||
#include <drawables/colorfilters.h>
|
#include <drawables/colorfilters.h>
|
||||||
#include <attributeset.h>
|
#include <core/attributeset.h>
|
||||||
#include <context.h>
|
#include <core/context.h>
|
||||||
#include <gravity.h>
|
#include <core/gravity.h>
|
||||||
#include <rect.h>
|
#include <core/rect.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
3
src/gui/drawables/shape.h
Normal file → Executable file
3
src/gui/drawables/shape.h
Normal file → Executable file
@ -1,7 +1,6 @@
|
|||||||
#ifndef __SHAPE_H__
|
#ifndef __SHAPE_H__
|
||||||
#define __SHAPE_H__
|
#define __SHAPE_H__
|
||||||
#include <rect.h>
|
#include <core/canvas.h>
|
||||||
#include <canvas.h>
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
class Shape{
|
class Shape{
|
||||||
|
2
src/gui/drawables/stateset.h
Normal file → Executable file
2
src/gui/drawables/stateset.h
Normal file → Executable file
@ -2,7 +2,7 @@
|
|||||||
#define __STATESET_H__
|
#define __STATESET_H__
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <attributeset.h>
|
#include <core/attributeset.h>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
class StateSet{
|
class StateSet{
|
||||||
private:
|
private:
|
||||||
|
@ -1,227 +0,0 @@
|
|||||||
//
|
|
||||||
// Looper.cpp - This file is part of the Looper library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <looper/EventLoop.h>
|
|
||||||
#include <looper/EventSource.h>
|
|
||||||
#include <looper/FileSource.h>
|
|
||||||
#include <looper/IdleSource.h>
|
|
||||||
#include <looper/TimeoutSource.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <poll.h>
|
|
||||||
#include <sys/epoll.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <cdtypes.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace cdroid {
|
|
||||||
|
|
||||||
struct Looper::Private {
|
|
||||||
bool quit;
|
|
||||||
int exit_code;
|
|
||||||
int epoolfd;
|
|
||||||
uint64_t time_last;
|
|
||||||
vector<EventSource*> sources;
|
|
||||||
vector<EventSource*> remove_sources;
|
|
||||||
vector<FileSource*> pollable_sources;
|
|
||||||
vector<struct pollfd> poll_fds;
|
|
||||||
unordered_set<EventSource*> source_set;
|
|
||||||
vector<IdleSource*> idle_sources;
|
|
||||||
vector<TimeoutSource*> timeout_sources;
|
|
||||||
|
|
||||||
Private() : quit(false), exit_code(0) {
|
|
||||||
epoolfd=epoll_create(128);
|
|
||||||
}
|
|
||||||
void add_event_source(EventSource*source) {
|
|
||||||
sources.emplace_back(source);
|
|
||||||
source_set.emplace(source);
|
|
||||||
if (source->is_idle_source())
|
|
||||||
idle_sources.emplace_back(dynamic_cast<IdleSource*>(source));
|
|
||||||
else if (source->is_timeout_source())
|
|
||||||
timeout_sources.emplace_back(dynamic_cast<TimeoutSource*>(source));
|
|
||||||
else if (source->is_file_source())
|
|
||||||
pollable_sources.emplace_back(dynamic_cast<FileSource*>(source));
|
|
||||||
}
|
|
||||||
void remove_event_source(EventSource*source) {
|
|
||||||
if (source->is_idle_source()) {
|
|
||||||
idle_sources.erase(remove(begin(idle_sources),end(idle_sources), source), end(idle_sources));
|
|
||||||
} else if (source->is_timeout_source()) {
|
|
||||||
timeout_sources.erase(remove(begin(timeout_sources),end(timeout_sources), source),end(timeout_sources));
|
|
||||||
} else if (source->is_file_source()) {
|
|
||||||
pollable_sources.erase(remove(begin(pollable_sources),end(pollable_sources), source),end(pollable_sources));
|
|
||||||
}
|
|
||||||
sources.erase(remove(begin(sources),end(sources), source), end(sources));
|
|
||||||
source_set.erase(source);
|
|
||||||
}
|
|
||||||
~Private() {
|
|
||||||
for (auto source : sources)
|
|
||||||
delete source;
|
|
||||||
close(epoolfd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Looper*Looper::mInst=nullptr;
|
|
||||||
Looper*Looper::getDefault(){
|
|
||||||
if(mInst==nullptr)
|
|
||||||
mInst=new Looper();
|
|
||||||
return mInst;
|
|
||||||
}
|
|
||||||
|
|
||||||
Looper::Looper()
|
|
||||||
: impl(make_shared<Private>()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Looper::iteration() {
|
|
||||||
int max_timeout =10;//-1;
|
|
||||||
int n_ready = 0;
|
|
||||||
// prepare and check for already ready event sources
|
|
||||||
for (auto source : impl->sources) {
|
|
||||||
if (source->is_idle_source())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int source_timeout = -1;
|
|
||||||
|
|
||||||
if (source->prepare(source_timeout)) {
|
|
||||||
source->loop_data.ready = true;
|
|
||||||
n_ready++;
|
|
||||||
} else if (source_timeout > 0 && (max_timeout == -1 || source_timeout < max_timeout)) {
|
|
||||||
max_timeout = source_timeout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// poll all of the pollable event sources
|
|
||||||
impl->poll_fds.resize(impl->pollable_sources.size());
|
|
||||||
for (size_t i = 0; i < impl->pollable_sources.size(); i++) {
|
|
||||||
if (! impl->pollable_sources[i]->loop_data.ready && impl->pollable_sources[i]->fd >= 0) {
|
|
||||||
impl->poll_fds[i].fd = impl->pollable_sources[i]->fd;
|
|
||||||
impl->poll_fds[i].events = static_cast<int>(impl->pollable_sources[i]->events);
|
|
||||||
impl->poll_fds[i].revents = impl->pollable_sources[i]->revents = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there's nothing else ready and there are idle event sources, make
|
|
||||||
// poll() return immediately.
|
|
||||||
if (n_ready < 1 && impl->idle_sources.size() > 0)
|
|
||||||
max_timeout = 0;
|
|
||||||
|
|
||||||
if (::poll(impl->poll_fds.data(), impl->poll_fds.size(), max_timeout) >0) {
|
|
||||||
for (size_t i = 0; i < impl->pollable_sources.size(); i++)
|
|
||||||
impl->pollable_sources[i]->revents = impl->poll_fds[i].revents;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now check if any more sources are ready after polling
|
|
||||||
for (auto source : impl->sources) {
|
|
||||||
if (source->is_idle_source())
|
|
||||||
continue;
|
|
||||||
if (! source->loop_data.ready) {
|
|
||||||
if (source->check()) {
|
|
||||||
source->loop_data.ready = true;
|
|
||||||
n_ready++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl->remove_sources.clear();
|
|
||||||
if (n_ready > 0) {
|
|
||||||
// dispatch all ready event sources
|
|
||||||
for (int i=0; i<impl->sources.size(); i++) {
|
|
||||||
EventSource *source=impl->sources[i];
|
|
||||||
if (! source->is_idle_source() && source->loop_data.ready &&
|
|
||||||
source->loop_data.handler) {
|
|
||||||
if (! source->dispatch(source->loop_data.handler))
|
|
||||||
impl->remove_sources.emplace_back(source);
|
|
||||||
source->loop_data.ready = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// nothing else ready, dispatch idle event sources
|
|
||||||
for (auto source : impl->idle_sources) {
|
|
||||||
if (source->loop_data.handler &&
|
|
||||||
! source->dispatch(source->loop_data.handler)) {
|
|
||||||
impl->remove_sources.emplace_back(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// prune event sources which requested to be removed
|
|
||||||
for (auto source : impl->remove_sources)
|
|
||||||
remove_event_source(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Looper::contains_source(EventSource *source) const {
|
|
||||||
return (impl->source_set.count(source) > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Looper::run() {
|
|
||||||
impl->quit = false;
|
|
||||||
impl->exit_code = 0;
|
|
||||||
while (! impl->quit)
|
|
||||||
iteration();
|
|
||||||
return impl->exit_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Looper::quit(int exit_code) {
|
|
||||||
impl->exit_code = exit_code;
|
|
||||||
impl->quit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Looper::add_event_source(EventSource *source, EventHandler handler) {
|
|
||||||
if (contains_source(source))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
source->loop_data.ready = false;
|
|
||||||
source->loop_data.handler = handler ? move(handler) : nullptr;
|
|
||||||
|
|
||||||
impl->add_event_source(source);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Looper::set_source_handler(EventSource *source, EventHandler handler) {
|
|
||||||
if (contains_source(source))
|
|
||||||
source->loop_data.handler = handler;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Looper::remove_event_source(EventSource *source) {
|
|
||||||
if (! contains_source(source))
|
|
||||||
return false;
|
|
||||||
impl->remove_event_source(source);
|
|
||||||
delete source;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventSource *Looper::add_file(int fd, FileEvents events, EventHandler handler) {
|
|
||||||
auto source = new FileSource(fd, events);
|
|
||||||
if (! add_event_source(source, handler)) {
|
|
||||||
delete source;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventSource *Looper::add_idle(EventHandler handler) {
|
|
||||||
auto source = new IdleSource;
|
|
||||||
if (! add_event_source(source, handler)) {
|
|
||||||
delete source;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventSource *Looper::add_timeout(int timeout_ms, EventHandler handler) {
|
|
||||||
auto source = new TimeoutSource(timeout_ms);
|
|
||||||
if (! add_event_source(source, handler)) {
|
|
||||||
delete source;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Looper
|
|
@ -1,61 +0,0 @@
|
|||||||
//
|
|
||||||
// Looper.h - This file is part of the Grinder library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef LOOPER_EVENTLOOP_H
|
|
||||||
#define LOOPER_EVENTLOOP_H
|
|
||||||
|
|
||||||
#include <looper/EventSource.h>
|
|
||||||
#include <looper/FileSource.h>
|
|
||||||
#include <looper/IdleSource.h>
|
|
||||||
#include <looper/TimeoutSource.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
class Looper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Looper();
|
|
||||||
int run();
|
|
||||||
void quit(int exit_code=0);
|
|
||||||
|
|
||||||
template< class T, class... Args >
|
|
||||||
T *emplace_event_source(Args&&... args){
|
|
||||||
auto source = new T(std::forward<Args&&>(args)...);
|
|
||||||
if (! add_event_source(source)) {
|
|
||||||
delete source;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Looper*getDefault();
|
|
||||||
|
|
||||||
bool add_event_source(EventSource *source, EventHandler handler=nullptr);
|
|
||||||
bool set_source_handler(EventSource *source, EventHandler handler);
|
|
||||||
bool remove_event_source(EventSource *source);
|
|
||||||
bool clear_source_handler(EventSource *source){
|
|
||||||
return set_source_handler(source, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
EventSource *add_file(int fd, FileEvents events, EventHandler handler=nullptr);
|
|
||||||
EventSource *add_idle(EventHandler handler=nullptr);
|
|
||||||
EventSource *add_timeout(int timeout_ms, EventHandler handler=nullptr);
|
|
||||||
private:
|
|
||||||
static Looper*mInst;
|
|
||||||
struct Private;
|
|
||||||
std::shared_ptr<Private> impl;
|
|
||||||
void iteration();
|
|
||||||
bool contains_source(EventSource *source) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOP_EVENTLOOP_H
|
|
@ -1,55 +0,0 @@
|
|||||||
//
|
|
||||||
// EventSource.h - This file is part of the Grinder library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef LOOPER_EVENTSOURCE_H
|
|
||||||
#define LOOPER_EVENTSOURCE_H
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
class Looper;
|
|
||||||
class EventSource;
|
|
||||||
|
|
||||||
typedef std::function<bool(EventSource&)> EventHandler;
|
|
||||||
|
|
||||||
class EventSource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~EventSource() {}
|
|
||||||
virtual bool prepare(int& max_timeout)
|
|
||||||
{
|
|
||||||
max_timeout = -1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
virtual bool check() = 0;
|
|
||||||
virtual bool dispatch(EventHandler& func) = 0;
|
|
||||||
virtual bool is_file_source() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
virtual bool is_timeout_source() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
virtual bool is_idle_source() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class Looper;
|
|
||||||
struct {
|
|
||||||
bool ready;
|
|
||||||
EventHandler handler;
|
|
||||||
} loop_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOPER_EVENTSOURCE_H
|
|
@ -1,43 +0,0 @@
|
|||||||
//
|
|
||||||
// FileEvents.h - This file is part of the UI library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef LOOP_FILEEVENTS_H
|
|
||||||
#define LOOP_FILEEVENTS_H
|
|
||||||
|
|
||||||
#include <poll.h>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
enum class FileEvents {
|
|
||||||
NONE = 0,
|
|
||||||
INPUT = POLLIN,
|
|
||||||
OUTPUT = POLLOUT,
|
|
||||||
PRIORITY = POLLPRI,
|
|
||||||
ERROR = POLLERR,
|
|
||||||
HANGUP = POLLHUP,
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
static inline int operator&(cdroid::FileEvents ev1, cdroid::FileEvents ev2)
|
|
||||||
{
|
|
||||||
return static_cast<int>(ev1) & static_cast<int>(ev2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int operator&(int ev1, cdroid::FileEvents ev2)
|
|
||||||
{
|
|
||||||
return ev1 & static_cast<int>(ev2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline cdroid::FileEvents operator|(cdroid::FileEvents ev1, cdroid::FileEvents ev2)
|
|
||||||
{
|
|
||||||
return static_cast<cdroid::FileEvents>(static_cast<int>(ev1) | static_cast<int>(ev2));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // LOOP_FILEEVENTS_H
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
|||||||
//
|
|
||||||
// FileSource.h - This file is part of the Grinder library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef LOOP_FILESOURCE_H
|
|
||||||
#define LOOP_FILESOURCE_H
|
|
||||||
|
|
||||||
#include <looper/EventSource.h>
|
|
||||||
#include <looper/FileEvents.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
class FileSource : public EventSource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int fd, revents;
|
|
||||||
FileEvents events;
|
|
||||||
FileSource(int fd, FileEvents events=FileEvents::NONE)
|
|
||||||
: fd(fd), revents(0), events(events) {}
|
|
||||||
|
|
||||||
bool prepare(int&) override
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool check() override
|
|
||||||
{
|
|
||||||
if (events == FileEvents::NONE || revents == 0)
|
|
||||||
return false;
|
|
||||||
if (((revents & FileEvents::INPUT) && (events & FileEvents::INPUT)) ||
|
|
||||||
((revents & FileEvents::OUTPUT) && (events & FileEvents::OUTPUT)) ||
|
|
||||||
((revents & FileEvents::PRIORITY) && (events & FileEvents::PRIORITY)) ||
|
|
||||||
((revents & FileEvents::ERROR) && (events & FileEvents::ERROR)) ||
|
|
||||||
((revents & FileEvents::HANGUP) && (events & FileEvents::HANGUP))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dispatch(EventHandler &func)
|
|
||||||
{
|
|
||||||
return func(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_file_source() const override final
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOPER_FILESOURCE_H
|
|
@ -1,81 +0,0 @@
|
|||||||
#include <looper/GenericSignalSource.h>
|
|
||||||
#include <looper/FileSource.h>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
static const int SIG_MAX = 128;
|
|
||||||
static const int PIPE_READ = 0;
|
|
||||||
static const int PIPE_WRITE = 1;
|
|
||||||
static int pipe_fds[2] = { -1, -1 };
|
|
||||||
|
|
||||||
static void signal_handler(int signo)
|
|
||||||
{
|
|
||||||
uint32_t usigno = signo;
|
|
||||||
::write(pipe_fds[PIPE_WRITE], &usigno, sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericSignalSource::GenericSignalSource(bool manage_proc_mask)
|
|
||||||
: GenericSignalSource(nullptr, manage_proc_mask)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericSignalSource::GenericSignalSource(const sigset_t *sigs, bool manage_proc_mask)
|
|
||||||
: SignalSource(sigs, manage_proc_mask)
|
|
||||||
{
|
|
||||||
if (pipe_fds[0] == -1 && pipe_fds[1] == -1) {
|
|
||||||
pipe(pipe_fds);
|
|
||||||
fd = pipe_fds[PIPE_READ];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manage_proc_mask)
|
|
||||||
sigprocmask(SIG_UNBLOCK, sigs, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericSignalSource::~GenericSignalSource()
|
|
||||||
{
|
|
||||||
::close(pipe_fds[0]);
|
|
||||||
::close(pipe_fds[1]);
|
|
||||||
pipe_fds[0] = pipe_fds[1] = -1;
|
|
||||||
|
|
||||||
sigset_t fullset;
|
|
||||||
sigfillset(&fullset);
|
|
||||||
for (int i = 0; i < SIG_MAX; i++) {
|
|
||||||
int res = sigismember(&fullset, i);
|
|
||||||
if (res > 0)
|
|
||||||
signal(i, SIG_DFL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GenericSignalSource::dispatch(EventHandler &func)
|
|
||||||
{
|
|
||||||
uint32_t sig = 0;
|
|
||||||
if (::read(fd, &sig, sizeof(uint32_t)) == sizeof(uint32_t)) {
|
|
||||||
signo = sig;
|
|
||||||
return FileSource::dispatch(func);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GenericSignalSource::update_signals(const sigset_t *sigs, bool manage_proc_mask)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < SIG_MAX; i++) {
|
|
||||||
int res = sigismember(sigs, i);
|
|
||||||
if (res > 0)
|
|
||||||
signal(i, signal_handler);
|
|
||||||
else if (res == 0)
|
|
||||||
signal(i, SIG_DFL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manage_proc_mask)
|
|
||||||
sigprocmask(SIG_UNBLOCK, sigs, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
@ -1,23 +0,0 @@
|
|||||||
#ifndef LOOP_GENERICSIGNALSOURCE_H
|
|
||||||
#define LOOP_GENERICSIGNALSOURCE_H
|
|
||||||
|
|
||||||
#include <looper/SignalSource.h>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
class GenericSignalSource : public SignalSource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GenericSignalSource(bool manage_proc_mask=false);
|
|
||||||
GenericSignalSource(const sigset_t *sigs=nullptr, bool manage_proc_mask=false);
|
|
||||||
~GenericSignalSource();
|
|
||||||
bool dispatch(EventHandler &func) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void update_signals(const sigset_t *sigs, bool manage_proc_mask);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOPER_GENERICSIGNALSOURCE_H
|
|
@ -1,39 +0,0 @@
|
|||||||
//
|
|
||||||
// IdleSource.h - This file is part of the UI library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef LOOPIDLESOURCE_H
|
|
||||||
#define LOOPIDLESOURCE_H
|
|
||||||
|
|
||||||
#include <looper/EventSource.h>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
class IdleSource : public EventSource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool prepare(int&) override final
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool check() override final
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool dispatch(EventHandler &func) override
|
|
||||||
{
|
|
||||||
return func(*this);
|
|
||||||
}
|
|
||||||
bool is_idle_source() const override final
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOPER_IDLESOURCE_H
|
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef LOOPER_PLATFORM_H
|
|
||||||
#define LOOPER_PLATFORM_H
|
|
||||||
|
|
||||||
#if defined(__linux) || defined(__linux__)
|
|
||||||
# define LOOPER_LINUX 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // LOOPER_PLATFORM_H
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
|||||||
//
|
|
||||||
// SignalFD.cpp - This file is part of the Grinder library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <looper/SignalFD.h>
|
|
||||||
|
|
||||||
#ifdef LOOPER_LINUX
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/signalfd.h>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
SignalFD::SignalFD(bool manage_proc_mask)
|
|
||||||
: SignalFD(nullptr, manage_proc_mask)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SignalFD::SignalFD(const sigset_t *sigs, bool manage_proc_mask)
|
|
||||||
: SignalSource(sigs, manage_proc_mask)
|
|
||||||
{
|
|
||||||
if (sigs && manage_proc_mask)
|
|
||||||
sigprocmask(SIG_BLOCK, sigs, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SignalFD::dispatch(EventHandler &func)
|
|
||||||
{
|
|
||||||
signalfd_siginfo info;
|
|
||||||
if (read(fd, &info, sizeof(signalfd_siginfo)) == sizeof(signalfd_siginfo)) {
|
|
||||||
signo = info.ssi_signo;
|
|
||||||
return FileSource::dispatch(func);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SignalFD::update_signals(const sigset_t *sigs, bool manage_proc_mask)
|
|
||||||
{
|
|
||||||
fd = signalfd(fd, sigs, SFD_NONBLOCK | SFD_CLOEXEC);
|
|
||||||
if (manage_proc_mask) {
|
|
||||||
sigset_t allset;
|
|
||||||
::sigfillset(&allset);
|
|
||||||
::sigprocmask(SIG_UNBLOCK, &allset, nullptr);
|
|
||||||
::sigprocmask(SIG_BLOCK, sigs, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOPER_LINUX
|
|
@ -1,35 +0,0 @@
|
|||||||
//
|
|
||||||
// SignalFD.h - This file is part of the Grinder library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef LOOPER_LINUX_SIGNALFD_H
|
|
||||||
#define LOOPER_LINUX_SIGNALFD_H
|
|
||||||
|
|
||||||
#include <looper/Platform.h>
|
|
||||||
#ifdef LOOPER_LINUX
|
|
||||||
|
|
||||||
#include <looper/SignalSource.h>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
class SignalFD : public SignalSource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SignalFD(bool manage_proc_mask=false);
|
|
||||||
SignalFD(const sigset_t *sigs, bool manage_proc_mask=false);
|
|
||||||
|
|
||||||
bool dispatch(EventHandler &func) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void update_signals(const sigset_t *sigs, bool manage_proc_mask);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOPER_LINUX
|
|
||||||
|
|
||||||
#endif // LOOPER_LINUX_SIGNALFD_H
|
|
@ -1,66 +0,0 @@
|
|||||||
#include <looper/SignalSource.h>
|
|
||||||
#include <looper/Platform.h>
|
|
||||||
#ifdef LOOPER_LINUX
|
|
||||||
# include <looper/SignalFD.h>
|
|
||||||
#else
|
|
||||||
# include <looper/GenericSignalSource.h>
|
|
||||||
#endif
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
SignalSource::SignalSource(bool manage_proc_mask)
|
|
||||||
: FileSource(-1, FileEvents::INPUT),
|
|
||||||
m_manage_proc_mask(manage_proc_mask)
|
|
||||||
{
|
|
||||||
sigemptyset(&m_sigs);
|
|
||||||
if (m_manage_proc_mask)
|
|
||||||
sigprocmask(SIG_BLOCK, nullptr, &m_old_sigs);
|
|
||||||
}
|
|
||||||
|
|
||||||
SignalSource::SignalSource(const sigset_t *sigs, bool manage_proc_mask)
|
|
||||||
: FileSource(-1, FileEvents::INPUT),
|
|
||||||
m_manage_proc_mask(manage_proc_mask)
|
|
||||||
{
|
|
||||||
if (sigs)
|
|
||||||
m_sigs = *sigs;
|
|
||||||
else
|
|
||||||
sigemptyset(&m_sigs);
|
|
||||||
if (m_manage_proc_mask)
|
|
||||||
sigprocmask(SIG_BLOCK, nullptr, &m_old_sigs);
|
|
||||||
}
|
|
||||||
|
|
||||||
SignalSource::~SignalSource()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (m_manage_proc_mask) {
|
|
||||||
sigset_t ss;
|
|
||||||
sigfillset(&ss);
|
|
||||||
sigprocmask(SIG_UNBLOCK, &ss, nullptr);
|
|
||||||
sigprocmask(SIG_BLOCK, &m_old_sigs, nullptr);
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
} catch (...) {
|
|
||||||
/* pass */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SignalSource::add(int signo)
|
|
||||||
{
|
|
||||||
sigaddset(&m_sigs, signo);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SignalSource::remove(int signo)
|
|
||||||
{
|
|
||||||
sigdelset(&m_sigs, signo);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SignalSource::update()
|
|
||||||
{
|
|
||||||
update_signals(&m_sigs, m_manage_proc_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
@ -1,43 +0,0 @@
|
|||||||
//
|
|
||||||
// SignalSource.h - This file is part of the UI library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef LOOP_SIGNALSOURCE_H
|
|
||||||
#define LOOP_SIGNALSOURCE_H
|
|
||||||
|
|
||||||
#include <looper/FileSource.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
class SignalSource : public FileSource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int signo; // when event is dispatched, contains the signal number
|
|
||||||
virtual ~SignalSource();
|
|
||||||
void add(int signo);
|
|
||||||
void remove(int signo);
|
|
||||||
bool check() override
|
|
||||||
{
|
|
||||||
return (revents & FileEvents::INPUT);
|
|
||||||
}
|
|
||||||
void update();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
SignalSource(bool manage_proc_mask=false);
|
|
||||||
SignalSource(const sigset_t *sigs, bool manage_proc_mask=false);
|
|
||||||
virtual void update_signals(const sigset_t *sigs, bool manage_proc_mask) = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
sigset_t m_sigs;
|
|
||||||
sigset_t m_old_sigs;
|
|
||||||
bool m_manage_proc_mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOP_SIGNALSOURCE_H
|
|
@ -1,46 +0,0 @@
|
|||||||
//
|
|
||||||
// TimeoutSource.cpp - This file is part of the UI library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <looper/TimeoutSource.h>
|
|
||||||
#include <looper/Utility.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
TimeoutSource::TimeoutSource(int timeout)
|
|
||||||
: m_timeout(timeout),
|
|
||||||
m_next_expiry(time_now() + timeout)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TimeoutSource::is_ready(int &max_timeout)
|
|
||||||
{
|
|
||||||
uint64_t now = time_now();
|
|
||||||
if (now >= m_next_expiry) {
|
|
||||||
m_next_expiry = (now + m_timeout) - (now - m_next_expiry);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
max_timeout = m_next_expiry - now;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TimeoutSource::prepare(int &max_timeout)
|
|
||||||
{
|
|
||||||
return is_ready(max_timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TimeoutSource::check()
|
|
||||||
{
|
|
||||||
int unused = 0;
|
|
||||||
return is_ready(unused);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
@ -1,40 +0,0 @@
|
|||||||
//
|
|
||||||
// TimeoutSource.h - This file is part of the UI library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef LOOP_TIMEOUTSOURCE_H
|
|
||||||
#define LOOP_TIMEOUTSOURCE_H
|
|
||||||
|
|
||||||
#include <looper/EventSource.h>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
class TimeoutSource : public EventSource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TimeoutSource(int timeout=-1);
|
|
||||||
bool prepare(int &max_timeout) override;
|
|
||||||
bool check() override;
|
|
||||||
bool dispatch(EventHandler &func) override
|
|
||||||
{
|
|
||||||
return func(*this);
|
|
||||||
}
|
|
||||||
bool is_timeout_source() const override final
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_timeout;
|
|
||||||
std::uint64_t m_next_expiry;
|
|
||||||
bool is_ready(int& max_timeout);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOP_TIMEOUTSOURCE_H
|
|
@ -1,78 +0,0 @@
|
|||||||
//
|
|
||||||
// TimerFD.cpp - This file is part of the Grinder library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <looper/TimerFD.h>
|
|
||||||
|
|
||||||
#ifdef LOOPER_LINUX
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <iostream>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/timerfd.h>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
TimerFD::TimerFD(int timeout_ms, bool one_shot)
|
|
||||||
: FileSource(::timerfd_create(CLOCK_MONOTONIC,
|
|
||||||
TFD_NONBLOCK | TFD_CLOEXEC),
|
|
||||||
FileEvents::INPUT),
|
|
||||||
m_timeout(timeout_ms),
|
|
||||||
m_one_shot(one_shot)
|
|
||||||
{
|
|
||||||
arm();
|
|
||||||
}
|
|
||||||
|
|
||||||
TimerFD::~TimerFD()
|
|
||||||
{
|
|
||||||
if (fd >= 0)
|
|
||||||
::close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void ms_to_timespec(int ms, struct timespec *ts)
|
|
||||||
{
|
|
||||||
ts->tv_sec = ms / 1000;
|
|
||||||
ts->tv_nsec = (ms % 1000) * 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerFD::arm(int timeout)
|
|
||||||
{
|
|
||||||
if (timeout >= 0)
|
|
||||||
m_timeout = timeout;
|
|
||||||
itimerspec its {{0,0},{0,0}};
|
|
||||||
ms_to_timespec(m_timeout, &its.it_value);
|
|
||||||
if (! m_one_shot) {
|
|
||||||
its.it_interval.tv_sec = its.it_value.tv_sec;
|
|
||||||
its.it_interval.tv_nsec = its.it_value.tv_nsec;
|
|
||||||
}
|
|
||||||
::timerfd_settime(fd, 0, &its, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerFD::disarm()
|
|
||||||
{
|
|
||||||
itimerspec its {{0,0},{0,0}};
|
|
||||||
::timerfd_settime(fd, 0, &its, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TimerFD::check()
|
|
||||||
{
|
|
||||||
return (revents & FileEvents::INPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TimerFD::dispatch(EventHandler &func)
|
|
||||||
{
|
|
||||||
uint64_t count = 0;
|
|
||||||
if (::read(fd, &count, sizeof(uint64_t)) == sizeof(uint64_t))
|
|
||||||
return FileSource::dispatch(func);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOPER_LINUX
|
|
@ -1,62 +0,0 @@
|
|||||||
//
|
|
||||||
// TimerFD.h - This file is part of the Grinder library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef LOOPER_LINUX_TIMERFD_H
|
|
||||||
#define LOOPER_LINUX_TIMERFD_H
|
|
||||||
|
|
||||||
#include <looper/Platform.h>
|
|
||||||
#ifdef LOOPER_LINUX
|
|
||||||
|
|
||||||
#include <looper/FileSource.h>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
class TimerFD : public FileSource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TimerFD(int timeout_ms, bool one_shot=false);
|
|
||||||
~TimerFD();
|
|
||||||
|
|
||||||
void arm(int timeout=-1);
|
|
||||||
void disarm();
|
|
||||||
|
|
||||||
bool one_shot() const
|
|
||||||
{
|
|
||||||
return m_one_shot;
|
|
||||||
}
|
|
||||||
void set_one_shot(bool one_shot)
|
|
||||||
{
|
|
||||||
disarm();
|
|
||||||
m_one_shot = one_shot;
|
|
||||||
arm();
|
|
||||||
}
|
|
||||||
|
|
||||||
int timeout() const
|
|
||||||
{
|
|
||||||
return m_timeout;
|
|
||||||
}
|
|
||||||
void set_timeout(int timeout_ms)
|
|
||||||
{
|
|
||||||
disarm();
|
|
||||||
m_timeout = timeout_ms;
|
|
||||||
arm();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool check() override;
|
|
||||||
bool dispatch(EventHandler &func) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
int m_timeout;
|
|
||||||
bool m_one_shot;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOPER_LINUX
|
|
||||||
|
|
||||||
#endif // LOOPER_LINUX_TIMERFD_H
|
|
@ -1,26 +0,0 @@
|
|||||||
//
|
|
||||||
// Utility.h - This file is part of the Grinder library
|
|
||||||
//
|
|
||||||
// Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef LOOPER_UTILITY_H
|
|
||||||
#define LOOPER_UTILITY_H
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace cdroid
|
|
||||||
{
|
|
||||||
|
|
||||||
static inline std::uint64_t time_now()
|
|
||||||
{
|
|
||||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
||||||
std::chrono::system_clock::now().time_since_epoch()).count();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace cdroid
|
|
||||||
|
|
||||||
#endif // LOOPER_UTILITY_H
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
#ifndef __LOOPER_HEADER__
|
|
||||||
#define __LOOPER_HEADER__
|
|
||||||
|
|
||||||
#include <looper/EventLoop.h>
|
|
||||||
#include <looper/EventSource.h>
|
|
||||||
#include <looper/FileEvents.h>
|
|
||||||
#include <looper/FileSource.h>
|
|
||||||
#include <looper/GenericSignalSource.h>
|
|
||||||
#include <looper/IdleSource.h>
|
|
||||||
#include <looper/Platform.h>
|
|
||||||
#include <looper/SignalSource.h>
|
|
||||||
#include <looper/TimeoutSource.h>
|
|
||||||
#include <looper/Utility.h>
|
|
||||||
|
|
||||||
#ifdef LOOPER_LINUX
|
|
||||||
# include <looper/SignalFD.h>
|
|
||||||
# include <looper/TimerFD.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // LOOPER_HEADER__
|
|
6
src/gui/views/toastwindow.cc
Normal file → Executable file
6
src/gui/views/toastwindow.cc
Normal file → Executable file
@ -11,7 +11,7 @@ ToastWindow::ToastWindow(int w,int h):Window(0,0,w,h,TYPE_TOAST){
|
|||||||
timeout_=-1;
|
timeout_=-1;
|
||||||
time_elapsed=0;
|
time_elapsed=0;
|
||||||
setFocusable(false);
|
setFocusable(false);
|
||||||
sendMessage((DWORD)WM_TIMER,(DWORD)TIMER_ID,0,500);
|
//sendMessage((DWORD)WM_TIMER,(DWORD)TIMER_ID,0,500);
|
||||||
toasts_.push_back(this);
|
toasts_.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ ToastWindow::~ToastWindow(){
|
|||||||
toasts_.erase(std::find(toasts_.begin(),toasts_.end(),this));
|
toasts_.erase(std::find(toasts_.begin(),toasts_.end(),this));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ToastWindow::onMessage(DWORD msg,DWORD wp,ULONG lp){
|
/*bool ToastWindow::onMessage(DWORD msg,DWORD wp,ULONG lp){
|
||||||
if(msg==WM_TIMER && wp==TIMER_ID){
|
if(msg==WM_TIMER && wp==TIMER_ID){
|
||||||
time_elapsed+=500;
|
time_elapsed+=500;
|
||||||
if(time_elapsed>=timeout_){
|
if(time_elapsed>=timeout_){
|
||||||
@ -30,7 +30,7 @@ bool ToastWindow::onMessage(DWORD msg,DWORD wp,ULONG lp){
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return Window::onMessage(msg,wp,lp);
|
return Window::onMessage(msg,wp,lp);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
bool ToastWindow::onKeyUp(int keyCode,KeyEvent&evt){
|
bool ToastWindow::onKeyUp(int keyCode,KeyEvent&evt){
|
||||||
time_elapsed=0;
|
time_elapsed=0;
|
||||||
|
1
src/gui/views/toastwindow.h
Normal file → Executable file
1
src/gui/views/toastwindow.h
Normal file → Executable file
@ -13,7 +13,6 @@ DECLARE_UIEVENT(ToastWindow*,OnCreateContentListener);
|
|||||||
public:
|
public:
|
||||||
ToastWindow(int w,int h);
|
ToastWindow(int w,int h);
|
||||||
~ToastWindow();
|
~ToastWindow();
|
||||||
virtual bool onMessage(DWORD msg,DWORD wp,ULONG lp)override;
|
|
||||||
virtual bool onKeyUp(int,KeyEvent&event)override;
|
virtual bool onKeyUp(int,KeyEvent&event)override;
|
||||||
static ToastWindow*makeWindow(OnCreateContentListener oncreate,UINT timeout=LENGTH_SHORT);
|
static ToastWindow*makeWindow(OnCreateContentListener oncreate,UINT timeout=LENGTH_SHORT);
|
||||||
static ToastWindow*makeText(const std::string&txt,UINT timeout=LENGTH_SHORT);
|
static ToastWindow*makeText(const std::string&txt,UINT timeout=LENGTH_SHORT);
|
||||||
|
@ -1246,7 +1246,8 @@ void AbsListView::keyPressed() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (longClickable && !mDataChanged) {
|
if (longClickable && !mDataChanged) {
|
||||||
postDelayed(std::bind(&AbsListView::CheckForKeyLongPress,this),ViewConfiguration::getLongPressTimeout());
|
Runnable mr(std::bind(&AbsListView::CheckForKeyLongPress,this));
|
||||||
|
postDelayed(mr,ViewConfiguration::getLongPressTimeout());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
#ifndef __ABS_LISTVIEW_H__
|
#ifndef __ABS_LISTVIEW_H__
|
||||||
#define __ABS_LISTVIEW_H__
|
#define __ABS_LISTVIEW_H__
|
||||||
#include <sparsearray.h>
|
#include <core/sparsearray.h>
|
||||||
#include <widget/adapterview.h>
|
#include <widget/adapterview.h>
|
||||||
#include <widget/recyclebin.h>
|
#include <widget/recyclebin.h>
|
||||||
#include <widget/overscroller.h>
|
#include <widget/overscroller.h>
|
||||||
#include <widget/edgeeffect.h>
|
#include <widget/edgeeffect.h>
|
||||||
#include <velocitytracker.h>
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
#define OVERSCROLL_LIMIT_DIVISOR 3
|
#define OVERSCROLL_LIMIT_DIVISOR 3
|
||||||
|
2
src/gui/widget/absspinner.h
Normal file → Executable file
2
src/gui/widget/absspinner.h
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
#ifndef __ABS_SPINNER_H__
|
#ifndef __ABS_SPINNER_H__
|
||||||
#define __ABS_SPINNER_H__
|
#define __ABS_SPINNER_H__
|
||||||
#include <widget/adapterview.h>
|
#include <widget/adapterview.h>
|
||||||
#include <sparsearray.h>
|
#include <core/sparsearray.h>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
class AbsSpinner:public AdapterView{
|
class AbsSpinner:public AdapterView{
|
||||||
protected:
|
protected:
|
||||||
|
6
src/gui/widget/adapter.cc
Normal file → Executable file
6
src/gui/widget/adapter.cc
Normal file → Executable file
@ -58,8 +58,8 @@ bool Adapter::isEmpty()const{
|
|||||||
return getCount() == 0;
|
return getCount() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void PagerAdapter::startUpdate(ViewGroup* container){
|
void PagerAdapter::startUpdate(ViewGroup* container){
|
||||||
startUpdate((View*)container);
|
startUpdate((View*)container);
|
||||||
}
|
}
|
||||||
@ -68,10 +68,12 @@ void PagerAdapter::startUpdate(View*container){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void*PagerAdapter::instantiateItem(ViewGroup* container, int position){
|
void*PagerAdapter::instantiateItem(ViewGroup* container, int position){
|
||||||
instantiateItem((View*)container,position);
|
return instantiateItem((View*)container,position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* PagerAdapter::instantiateItem(View* container, int position){
|
void* PagerAdapter::instantiateItem(View* container, int position){
|
||||||
|
throw "Required method instantiateItem was not overridden";
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PagerAdapter::destroyItem(ViewGroup* container, int position, void* object){
|
void PagerAdapter::destroyItem(ViewGroup* container, int position, void* object){
|
||||||
|
8
src/gui/widget/analogclock.cc
Normal file → Executable file
8
src/gui/widget/analogclock.cc
Normal file → Executable file
@ -54,9 +54,9 @@ Drawable*AnalogClock::getClockDrawable(int id){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AnalogClock::onAttached(){
|
void AnalogClock::onAttached(){
|
||||||
sendMessage(WM_TIMER,0,0,1000);
|
//sendMessage(WM_TIMER,0,0,1000);
|
||||||
}
|
}
|
||||||
bool AnalogClock::onMessage(DWORD msg,DWORD wp,ULONG lp){
|
/*bool AnalogClock::onMessage(DWORD msg,DWORD wp,ULONG lp){
|
||||||
if(msg==WM_TIMER){
|
if(msg==WM_TIMER){
|
||||||
std::time_t t = std::time(NULL);
|
std::time_t t = std::time(NULL);
|
||||||
struct std::tm when= *std::localtime(&t);
|
struct std::tm when= *std::localtime(&t);
|
||||||
@ -64,12 +64,12 @@ bool AnalogClock::onMessage(DWORD msg,DWORD wp,ULONG lp){
|
|||||||
mHour=when.tm_hour;
|
mHour=when.tm_hour;
|
||||||
mMinutes=when.tm_min;
|
mMinutes=when.tm_min;
|
||||||
mSeconds=when.tm_sec;
|
mSeconds=when.tm_sec;
|
||||||
sendMessage(msg,wp,lp,1000);
|
//sendMessage(msg,wp,lp,1000);
|
||||||
invalidate(nullptr);
|
invalidate(nullptr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return View::onMessage(msg,wp,lp);
|
return View::onMessage(msg,wp,lp);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
void AnalogClock::onDraw(Canvas&canvas){
|
void AnalogClock::onDraw(Canvas&canvas){
|
||||||
View::onDraw(canvas);
|
View::onDraw(canvas);
|
||||||
|
2
src/gui/widget/analogclock.h
Normal file → Executable file
2
src/gui/widget/analogclock.h
Normal file → Executable file
@ -27,7 +27,7 @@ public:
|
|||||||
AnalogClock(int w,int h);
|
AnalogClock(int w,int h);
|
||||||
void setClockDrawable(Drawable*d,int id);
|
void setClockDrawable(Drawable*d,int id);
|
||||||
Drawable*getClockDrawable(int id);
|
Drawable*getClockDrawable(int id);
|
||||||
bool onMessage(DWORD msg,DWORD wp,ULONG lp);
|
//bool onMessage(DWORD msg,DWORD wp,ULONG lp);
|
||||||
};
|
};
|
||||||
|
|
||||||
}//namespace
|
}//namespace
|
||||||
|
6
src/gui/widget/edgeeffect.h
Normal file → Executable file
6
src/gui/widget/edgeeffect.h
Normal file → Executable file
@ -1,8 +1,8 @@
|
|||||||
#ifndef __EDGE_EFFECT_H__
|
#ifndef __EDGE_EFFECT_H__
|
||||||
#define __EDGE_EFFECT_H__
|
#define __EDGE_EFFECT_H__
|
||||||
#include <canvas.h>
|
#include <core/canvas.h>
|
||||||
#include <context.h>
|
#include <core/context.h>
|
||||||
#include <interpolators.h>
|
#include <animation/interpolators.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
|
1
src/gui/widget/horizontalscrollview.h
Normal file → Executable file
1
src/gui/widget/horizontalscrollview.h
Normal file → Executable file
@ -3,7 +3,6 @@
|
|||||||
#include <widget/framelayout.h>
|
#include <widget/framelayout.h>
|
||||||
#include <widget/overscroller.h>
|
#include <widget/overscroller.h>
|
||||||
#include <widget/edgeeffect.h>
|
#include <widget/edgeeffect.h>
|
||||||
#include <velocitytracker.h>
|
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
|
4
src/gui/widget/imageview.cc
Normal file → Executable file
4
src/gui/widget/imageview.cc
Normal file → Executable file
@ -317,7 +317,7 @@ void ImageView::configureBounds(){
|
|||||||
|
|
||||||
|
|
||||||
const bool fits = (dwidth < 0 || vwidth == dwidth) && (dheight < 0 || vheight == dheight);
|
const bool fits = (dwidth < 0 || vwidth == dwidth) && (dheight < 0 || vheight == dheight);
|
||||||
LOGD("drawables.setBounds(%d,%d) fits=%d mScaleType=%d",vwidth,vheight,fits,mScaleType);
|
LOGV("drawables.setBounds(%d,%d) fits=%d mScaleType=%d",vwidth,vheight,fits,mScaleType);
|
||||||
|
|
||||||
mDrawable->setBounds(0, 0, vwidth, vheight);
|
mDrawable->setBounds(0, 0, vwidth, vheight);
|
||||||
|
|
||||||
@ -387,7 +387,7 @@ void ImageView::configureBounds(){
|
|||||||
//mDrawMatrix.setRectToRect(mTempSrc, mTempDst, scaleTypeToScaleToFit(mScaleType));
|
//mDrawMatrix.setRectToRect(mTempSrc, mTempDst, scaleTypeToScaleToFit(mScaleType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOGD("ScaleType=%d DrawMatrix=%.2f,%.2f, %.2f,%.2f, %.2f,%.2f",mScaleType,
|
LOGV("ScaleType=%d DrawMatrix=%.2f,%.2f, %.2f,%.2f, %.2f,%.2f",mScaleType,
|
||||||
mDrawMatrix.xx,mDrawMatrix.yx,mDrawMatrix.xy,mDrawMatrix.yy,mDrawMatrix.x0,mDrawMatrix.y0);
|
mDrawMatrix.xx,mDrawMatrix.yx,mDrawMatrix.xy,mDrawMatrix.yy,mDrawMatrix.x0,mDrawMatrix.y0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <widget/view.h>
|
#include <widget/view.h>
|
||||||
#include <widget/edittext.h>
|
#include <widget/edittext.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <keyboard.h>
|
#include <core/keyboard.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
|
4
src/gui/widget/layoutparams.h
Normal file → Executable file
4
src/gui/widget/layoutparams.h
Normal file → Executable file
@ -1,9 +1,9 @@
|
|||||||
#ifndef __LAYOUT_PARAMS_H__
|
#ifndef __LAYOUT_PARAMS_H__
|
||||||
#define __LAYOUT_PARAMS_H__
|
#define __LAYOUT_PARAMS_H__
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <attributeset.h>
|
|
||||||
#include <context.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <core/attributeset.h>
|
||||||
|
#include <core/context.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
class View;
|
class View;
|
||||||
|
1
src/gui/widget/numberpicker.cc
Normal file → Executable file
1
src/gui/widget/numberpicker.cc
Normal file → Executable file
@ -2,7 +2,6 @@
|
|||||||
#include <color.h>
|
#include <color.h>
|
||||||
#include <textutils.h>
|
#include <textutils.h>
|
||||||
#include <cdlog.h>
|
#include <cdlog.h>
|
||||||
#include <interpolators.h>
|
|
||||||
|
|
||||||
//https://gitee.com/awang/WheelView/blob/master/src/com/wangjie/wheelview/WheelView.java
|
//https://gitee.com/awang/WheelView/blob/master/src/com/wangjie/wheelview/WheelView.java
|
||||||
|
|
||||||
|
5
src/gui/widget/numberpicker.h
Normal file → Executable file
5
src/gui/widget/numberpicker.h
Normal file → Executable file
@ -3,9 +3,8 @@
|
|||||||
#include <widget/linearlayout.h>
|
#include <widget/linearlayout.h>
|
||||||
#include <widget/imagebutton.h>
|
#include <widget/imagebutton.h>
|
||||||
#include <widget/edittext.h>
|
#include <widget/edittext.h>
|
||||||
#include <scroller.h>
|
#include <core/scroller.h>
|
||||||
#include <velocitytracker.h>
|
#include <core/sparsearray.h>
|
||||||
#include <sparsearray.h>
|
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <widget/overscroller.h>
|
#include <widget/overscroller.h>
|
||||||
#include <systemclock.h>
|
#include <core/systemclock.h>
|
||||||
#include <scroller.h>
|
#include <core/scroller.h>
|
||||||
|
#include <core/viewconfiguration.h>
|
||||||
#include <cdlog.h>
|
#include <cdlog.h>
|
||||||
|
|
||||||
|
|
||||||
@ -53,6 +54,7 @@ OverScroller::SplineOverScroller::SplineOverScroller(Context* context) {
|
|||||||
* 39.37f // inch/meter
|
* 39.37f // inch/meter
|
||||||
* ppi
|
* ppi
|
||||||
* 0.84f; // look and feel tuning
|
* 0.84f; // look and feel tuning
|
||||||
|
mFlingFriction = ViewConfiguration::getScrollFriction();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverScroller::SplineOverScroller::startScroll(int start, int distance, int duration) {
|
void OverScroller::SplineOverScroller::startScroll(int start, int distance, int duration) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef __OVER_SCROLLER_H__
|
#ifndef __OVER_SCROLLER_H__
|
||||||
#define __OVER_SCROLLER_H__
|
#define __OVER_SCROLLER_H__
|
||||||
#include <viewconfiguration.h>
|
#include <core/context.h>
|
||||||
#include <interpolators.h>
|
#include <animation/interpolators.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ public:
|
|||||||
// The allowed overshot distance before boundary is reached.
|
// The allowed overshot distance before boundary is reached.
|
||||||
int mOver;
|
int mOver;
|
||||||
// Fling friction
|
// Fling friction
|
||||||
float mFlingFriction = ViewConfiguration::getScrollFriction();
|
float mFlingFriction;
|
||||||
// Current state of the animation.
|
// Current state of the animation.
|
||||||
int mState = SPLINE;
|
int mState = SPLINE;
|
||||||
// A context-specific coefficient adjusted to physical values.
|
// A context-specific coefficient adjusted to physical values.
|
||||||
|
@ -216,13 +216,15 @@ void ProgressBar::refreshProgress(int id, int progress, bool fromUser,bool anima
|
|||||||
if(!mRefreshIsPosted){
|
if(!mRefreshIsPosted){
|
||||||
LOGD("setprogress %d=%d bools=%d,%d",id,progress,mAttached,mRefreshIsPosted);
|
LOGD("setprogress %d=%d bools=%d,%d",id,progress,mAttached,mRefreshIsPosted);
|
||||||
if(mAttached&&!mRefreshIsPosted){
|
if(mAttached&&!mRefreshIsPosted){
|
||||||
postDelayed([this](){
|
Runnable run;
|
||||||
|
run=[this](){
|
||||||
for(int i=ID_PRIMARY;i<=ID_SECONDARY;i++){
|
for(int i=ID_PRIMARY;i<=ID_SECONDARY;i++){
|
||||||
RefreshData&rd=mData[i];
|
RefreshData&rd=mData[i];
|
||||||
doRefreshProgress(i, rd.progress, rd.fromUser, true, rd.animate);
|
doRefreshProgress(i, rd.progress, rd.fromUser, true, rd.animate);
|
||||||
}
|
}
|
||||||
mRefreshIsPosted=false;
|
mRefreshIsPosted=false;
|
||||||
},10);
|
};
|
||||||
|
postDelayed(run,10);
|
||||||
mRefreshIsPosted=true;
|
mRefreshIsPosted=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,6 +243,7 @@ bool ProgressBar::setProgressInternal(int value, bool fromUser,bool animate){
|
|||||||
void ProgressBar::setProgress(int value){
|
void ProgressBar::setProgress(int value){
|
||||||
setProgressInternal(value,FALSE);
|
setProgressInternal(value,FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProgressBar::setSecondaryProgress(int secondaryProgress) {
|
void ProgressBar::setSecondaryProgress(int secondaryProgress) {
|
||||||
if (mIndeterminate) return;
|
if (mIndeterminate) return;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#ifndef __RECYCLEBIN_H__
|
#ifndef __RECYCLEBIN_H__
|
||||||
#define __RECYCLEBIN_H__
|
#define __RECYCLEBIN_H__
|
||||||
#include <widget/view.h>
|
#include <widget/view.h>
|
||||||
#include <sparsearray.h>
|
#include <core/sparsearray.h>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
class RecycleBin{
|
class RecycleBin{
|
||||||
|
1
src/gui/widget/scrollview.h
Normal file → Executable file
1
src/gui/widget/scrollview.h
Normal file → Executable file
@ -3,7 +3,6 @@
|
|||||||
#include <widget/framelayout.h>
|
#include <widget/framelayout.h>
|
||||||
#include <widget/overscroller.h>
|
#include <widget/overscroller.h>
|
||||||
#include <widget/edgeeffect.h>
|
#include <widget/edgeeffect.h>
|
||||||
#include <velocitytracker.h>
|
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
|
2
src/gui/widget/simplemonthview.h
Normal file → Executable file
2
src/gui/widget/simplemonthview.h
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
#ifndef __SIMPLE_MONTHVIEW_H__
|
#ifndef __SIMPLE_MONTHVIEW_H__
|
||||||
#define __SIMPLE_MONTHVIEW_H__
|
#define __SIMPLE_MONTHVIEW_H__
|
||||||
#include <widget/view.h>
|
#include <widget/view.h>
|
||||||
#include <calendar.h>
|
#include <core/calendar.h>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
class SimpleMonthView:public View{
|
class SimpleMonthView:public View{
|
||||||
|
2
src/gui/widget/tablerow.h
Normal file → Executable file
2
src/gui/widget/tablerow.h
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
#ifndef __TABLE_ROW_H__
|
#ifndef __TABLE_ROW_H__
|
||||||
#define __TABLE_ROW_H__
|
#define __TABLE_ROW_H__
|
||||||
#include <widget/linearlayout.h>
|
#include <widget/linearlayout.h>
|
||||||
#include <sparsearray.h>
|
#include <core/sparsearray.h>
|
||||||
|
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
#define __TEXTVIEW_H__
|
#define __TEXTVIEW_H__
|
||||||
|
|
||||||
#include <widget/view.h>
|
#include <widget/view.h>
|
||||||
#include <gravity.h>
|
#include <core/gravity.h>
|
||||||
#include <layout.h>
|
#include <core/layout.h>
|
||||||
|
|
||||||
namespace cdroid {
|
namespace cdroid {
|
||||||
|
|
||||||
|
@ -165,7 +165,6 @@ void View::initView(){
|
|||||||
mOnFocusChangeListener=nullptr;
|
mOnFocusChangeListener=nullptr;
|
||||||
mOnScrollChangeListener=nullptr;
|
mOnScrollChangeListener=nullptr;
|
||||||
mOverScrollMode=OVER_SCROLL_NEVER;
|
mOverScrollMode=OVER_SCROLL_NEVER;
|
||||||
mOnMessage=nullptr;
|
|
||||||
mVerticalScrollbarPosition=0;
|
mVerticalScrollbarPosition=0;
|
||||||
mUserPaddingLeft=mUserPaddingRight=0;
|
mUserPaddingLeft=mUserPaddingRight=0;
|
||||||
mUserPaddingTop=mUserPaddingBottom=0;
|
mUserPaddingTop=mUserPaddingBottom=0;
|
||||||
@ -532,7 +531,7 @@ void View::setFadingEdgeLength(int length){
|
|||||||
}
|
}
|
||||||
void View::transformFromViewToWindowSpace(int*inOutLocation){
|
void View::transformFromViewToWindowSpace(int*inOutLocation){
|
||||||
View* view = this;
|
View* view = this;
|
||||||
double position[2]={inOutLocation[0],inOutLocation[1]};
|
double position[2]={(double)inOutLocation[0],(double)inOutLocation[1]};
|
||||||
if(!hasIdentityMatrix()){
|
if(!hasIdentityMatrix()){
|
||||||
mMatrix.transform_point(position[0],position[1]);
|
mMatrix.transform_point(position[0],position[1]);
|
||||||
}
|
}
|
||||||
@ -1225,10 +1224,6 @@ void View::setOnScrollChangeListener(OnScrollChangeListener l){
|
|||||||
mOnScrollChangeListener=l;
|
mOnScrollChangeListener=l;
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::setMessageListener(MessageListener ls){
|
|
||||||
mOnMessage=ls;
|
|
||||||
}
|
|
||||||
|
|
||||||
void View::clip(RefPtr<Region>rgn){
|
void View::clip(RefPtr<Region>rgn){
|
||||||
if(mParent){//clip sliblings
|
if(mParent){//clip sliblings
|
||||||
BOOL afterthis=FALSE;
|
BOOL afterthis=FALSE;
|
||||||
@ -2595,7 +2590,9 @@ void View::invalidate(int l,int t,int w,int h){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void View::postInvalidate(){
|
void View::postInvalidate(){
|
||||||
postDelayed([this](){ invalidate(nullptr);},30);
|
Runnable r;
|
||||||
|
r=[this](){ invalidate(nullptr);};
|
||||||
|
postDelayed(r,30);
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::postInvalidateOnAnimation(){
|
void View::postInvalidateOnAnimation(){
|
||||||
@ -3311,7 +3308,7 @@ void View::checkForLongClick(int delayOffset,int x,int y){
|
|||||||
mHasPerformedLongPress = false;
|
mHasPerformedLongPress = false;
|
||||||
mOriginalPressedState=isPressed();
|
mOriginalPressedState=isPressed();
|
||||||
mPendingCheckForLongPress=std::bind(&View::checkLongPressCallback,this,x,y);
|
mPendingCheckForLongPress=std::bind(&View::checkLongPressCallback,this,x,y);
|
||||||
post(this,mPendingCheckForLongPress,ViewConfiguration::getLongPressTimeout()-delayOffset);
|
postDelayed(mPendingCheckForLongPress,ViewConfiguration::getLongPressTimeout()-delayOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3427,52 +3424,27 @@ bool View::onTouchEvent(MotionEvent& mt){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::sendMessage(View*v,DWORD msgid,DWORD wParam,ULONG lParam,DWORD delayedtime){
|
|
||||||
View*root=getRootView();
|
|
||||||
if(root!=this)
|
|
||||||
root->sendMessage(v,msgid,wParam,lParam,delayedtime);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void View::sendMessage(DWORD msgid,DWORD wParam,ULONG lParam,DWORD delayedtime){
|
|
||||||
sendMessage(this,msgid,wParam,lParam,delayedtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void View::postOnAnimation(Runnable action){
|
void View::postOnAnimation(Runnable action){
|
||||||
post(this,action,10);
|
postDelayed(action,10);
|
||||||
}
|
}
|
||||||
void View::postOnAnimationDelayed(Runnable action, long delayMillis){
|
void View::postOnAnimationDelayed(Runnable action, long delayMillis){
|
||||||
post(this,action,delayMillis);
|
postDelayed(action,delayMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::post(View*v,const Runnable what,DWORD delay){
|
void View::post(Runnable& what){
|
||||||
View*root=getRootView();
|
|
||||||
if(root!=this)root->post(v,what,delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
void View::post(const Runnable what){
|
|
||||||
postDelayed(what,0);
|
postDelayed(what,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::postDelayed(const Runnable what,DWORD delay){
|
void View::postDelayed(Runnable& what,uint32_t delay){
|
||||||
View*root=getRootView();
|
View*root=getRootView();
|
||||||
if(root&&(root!=this))root->post(this,what,delay);
|
if(root&&(root!=this))root->postDelayed(what,delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::removeCallbacks(const Runnable what){
|
void View::removeCallbacks(const Runnable& what){
|
||||||
View*root=getRootView();
|
View*root=getRootView();
|
||||||
if(root&&(root!=this))root->removeCallbacks(what);
|
if(root&&(root!=this))root->removeCallbacks(what);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool View::onMessage(DWORD msgid,DWORD wParam,ULONG lParam){
|
|
||||||
RECT r;
|
|
||||||
switch(msgid){
|
|
||||||
default:
|
|
||||||
if(mOnMessage)return mOnMessage(*this,msgid,wParam,lParam);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
// For Layout support
|
// For Layout support
|
||||||
|
|
||||||
@ -3667,7 +3639,7 @@ Matrix View::getInverseMatrix() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float View::getRotation(){
|
float View::getRotation(){
|
||||||
|
return .0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::setRotation(float rotation){
|
void View::setRotation(float rotation){
|
||||||
@ -3675,7 +3647,7 @@ void View::setRotation(float rotation){
|
|||||||
}
|
}
|
||||||
|
|
||||||
float View::getRotationX(){
|
float View::getRotationX(){
|
||||||
|
return .0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void View::setRotationX(float){
|
void View::setRotationX(float){
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#ifndef __NGL_VIEW_H__
|
#ifndef __NGL_VIEW_H__
|
||||||
#define __NGL_VIEW_H__
|
#define __NGL_VIEW_H__
|
||||||
#include <eventcodes.h>
|
#include <core/eventcodes.h>
|
||||||
#include <uievents.h>
|
#include <core/uievents.h>
|
||||||
#include <canvas.h>
|
#include <core/canvas.h>
|
||||||
#include <viewconfiguration.h>
|
#include <core/viewconfiguration.h>
|
||||||
#include <systemclock.h>
|
#include <core/systemclock.h>
|
||||||
#include <widget/layoutparams.h>
|
#include <widget/layoutparams.h>
|
||||||
#include <widget/measurespec.h>
|
#include <widget/measurespec.h>
|
||||||
#include <animation/animation.h>
|
#include <animation/animation.h>
|
||||||
@ -12,10 +12,12 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <rect.h>
|
#include <core/rect.h>
|
||||||
#include <drawables.h>
|
#include <drawables.h>
|
||||||
#include <attributeset.h>
|
#include <core/gravity.h>
|
||||||
#include <context.h>
|
#include <core/attributeset.h>
|
||||||
|
#include <core/context.h>
|
||||||
|
#include <core/velocitytracker.h>
|
||||||
|
|
||||||
#ifndef _GLIBCXX_FUNCTIONAL
|
#ifndef _GLIBCXX_FUNCTIONAL
|
||||||
#define DECLARE_UIEVENT(type,name,...) typedef type(*name)(__VA_ARGS__)
|
#define DECLARE_UIEVENT(type,name,...) typedef type(*name)(__VA_ARGS__)
|
||||||
@ -238,7 +240,6 @@ public:
|
|||||||
};
|
};
|
||||||
DECLARE_UIEVENT(void,OnClickListener,View&);
|
DECLARE_UIEVENT(void,OnClickListener,View&);
|
||||||
DECLARE_UIEVENT(bool,OnLongClickListener,View&);
|
DECLARE_UIEVENT(bool,OnLongClickListener,View&);
|
||||||
DECLARE_UIEVENT(bool,MessageListener,View&,DWORD,DWORD,ULONG);
|
|
||||||
DECLARE_UIEVENT(void,OnFocusChangeListener,View&,bool);
|
DECLARE_UIEVENT(void,OnFocusChangeListener,View&,bool);
|
||||||
DECLARE_UIEVENT(void,OnScrollChangeListener,View& v, int, int, int, int);
|
DECLARE_UIEVENT(void,OnScrollChangeListener,View& v, int, int, int, int);
|
||||||
DECLARE_UIEVENT(void,OnLayoutChangeListener,View* v, int left, int top, int width, int height,
|
DECLARE_UIEVENT(void,OnLayoutChangeListener,View* v, int left, int top, int width, int height,
|
||||||
@ -323,7 +324,6 @@ protected:
|
|||||||
OnFocusChangeListener mOnFocusChangeListener;
|
OnFocusChangeListener mOnFocusChangeListener;
|
||||||
std::vector<OnLayoutChangeListener> mOnLayoutChangeListeners;
|
std::vector<OnLayoutChangeListener> mOnLayoutChangeListeners;
|
||||||
OnScrollChangeListener mOnScrollChangeListener;
|
OnScrollChangeListener mOnScrollChangeListener;
|
||||||
MessageListener mOnMessage;
|
|
||||||
|
|
||||||
bool hasIdentityMatrix();
|
bool hasIdentityMatrix();
|
||||||
void computeOpaqueFlags();
|
void computeOpaqueFlags();
|
||||||
@ -356,7 +356,6 @@ protected:
|
|||||||
|
|
||||||
void postOnAnimation(Runnable action);
|
void postOnAnimation(Runnable action);
|
||||||
void postOnAnimationDelayed(Runnable action, long delayMillis);
|
void postOnAnimationDelayed(Runnable action, long delayMillis);
|
||||||
virtual void post(View*v,const Runnable what,DWORD delay=0);
|
|
||||||
virtual void onSizeChanged(int w,int h,int oldw,int oldh);
|
virtual void onSizeChanged(int w,int h,int oldw,int oldh);
|
||||||
virtual void onScrollChanged(int l, int t, int oldl, int oldt);
|
virtual void onScrollChanged(int l, int t, int oldl, int oldt);
|
||||||
virtual void onLayout(bool ,int,int,int,int);
|
virtual void onLayout(bool ,int,int,int,int);
|
||||||
@ -520,7 +519,6 @@ public:
|
|||||||
virtual void setOnLongClickListener(OnLongClickListener l);
|
virtual void setOnLongClickListener(OnLongClickListener l);
|
||||||
virtual void setOnFocusChangeListener(OnFocusChangeListener listtener);
|
virtual void setOnFocusChangeListener(OnFocusChangeListener listtener);
|
||||||
virtual void setOnScrollChangeListener(OnScrollChangeListener l);
|
virtual void setOnScrollChangeListener(OnScrollChangeListener l);
|
||||||
virtual void setMessageListener(MessageListener ls);
|
|
||||||
void addOnLayoutChangeListener(OnLayoutChangeListener listener);
|
void addOnLayoutChangeListener(OnLayoutChangeListener listener);
|
||||||
void removeOnLayoutChangeListener(OnLayoutChangeListener listener);
|
void removeOnLayoutChangeListener(OnLayoutChangeListener listener);
|
||||||
virtual bool performClick();
|
virtual bool performClick();
|
||||||
@ -680,12 +678,10 @@ public:
|
|||||||
virtual bool onHoverEvent(MotionEvent& evt);
|
virtual bool onHoverEvent(MotionEvent& evt);
|
||||||
virtual bool onGenericMotionEvent(MotionEvent& event);
|
virtual bool onGenericMotionEvent(MotionEvent& event);
|
||||||
virtual void onHoverChanged(bool hovered);
|
virtual void onHoverChanged(bool hovered);
|
||||||
virtual void sendMessage(DWORD msgid,DWORD wParam,ULONG lParam,DWORD delayedtime=0);
|
|
||||||
virtual void sendMessage(View*view,DWORD msgid,DWORD wParam,ULONG lParam,DWORD delayedtime=0);
|
virtual void postDelayed(Runnable& what,uint32_t delay=0);
|
||||||
virtual bool onMessage(DWORD msgid,DWORD wParam,ULONG lParam);
|
void post(Runnable& what);
|
||||||
virtual void removeCallbacks(const Runnable what);
|
virtual void removeCallbacks(const Runnable& what);
|
||||||
virtual void post(const Runnable what);
|
|
||||||
virtual void postDelayed(const Runnable what,DWORD delay=0);
|
|
||||||
|
|
||||||
virtual int getBaseline();
|
virtual int getBaseline();
|
||||||
static bool isLayoutModeOptical(View*);
|
static bool isLayoutModeOptical(View*);
|
||||||
|
@ -85,9 +85,6 @@ ViewGroup::ViewGroup(int x,int y,int w,int h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ViewGroup::initGroup(){
|
void ViewGroup::initGroup(){
|
||||||
focusRectSrc.set(0,0,0,0);
|
|
||||||
focusRectDest.set(0,0,0,0);
|
|
||||||
focusRect.set(0,0,0,0);
|
|
||||||
mFocused=nullptr;
|
mFocused=nullptr;
|
||||||
mDefaultFocus=nullptr;
|
mDefaultFocus=nullptr;
|
||||||
mFocusedInCluster=nullptr;
|
mFocusedInCluster=nullptr;
|
||||||
@ -1470,20 +1467,6 @@ bool ViewGroup::isTransformedTouchPointInView(int x,int y, View& child,POINT*out
|
|||||||
return isInView;
|
return isInView;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewGroup::onDraw(Canvas& canvas) {
|
|
||||||
// Draw the background color, if enabled
|
|
||||||
View::onDraw(canvas);
|
|
||||||
canvas.save();
|
|
||||||
onDrawFocusRect(canvas,focusRect);
|
|
||||||
canvas.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewGroup::onDrawFocusRect(Canvas&canvas,const RECT&r){
|
|
||||||
canvas.set_source_rgba(1,0,0,.5);
|
|
||||||
canvas.rectangle(r.x,r.y,r.width,r.height);
|
|
||||||
canvas.fill();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewGroup::onSizeChanged(int w,int h,int ow,int oh){
|
void ViewGroup::onSizeChanged(int w,int h,int ow,int oh){
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1770,25 +1753,6 @@ static int isExcludedKeys(int key){
|
|||||||
return key==KEY_MENU||key==KEY_ESCAPE;//||key==KEY_EXIT;
|
return key==KEY_MENU||key==KEY_ESCAPE;//||key==KEY_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewGroup::moveFocusTo(const RECT&r){
|
|
||||||
focusRectSrc=focusRectDest;
|
|
||||||
focusRectDest=r;
|
|
||||||
time_lastframe=SystemClock::uptimeMillis();
|
|
||||||
|
|
||||||
if(hasFlag(ATTR_ANIMATE_FOCUS))
|
|
||||||
sendMessage(WM_TIMER,0,0,10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewGroup::invalidateChildrenInFocusRect(){
|
|
||||||
for(int i=0;i<getChildCount();i++){
|
|
||||||
View*v=getChildAt(i);
|
|
||||||
RECT r;
|
|
||||||
if(!r.intersect(v->getBound(),focusRect))continue;
|
|
||||||
r.offset(-v->getX(),-v->getY());
|
|
||||||
v->invalidate(&r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewGroup::drawableStateChanged(){
|
void ViewGroup::drawableStateChanged(){
|
||||||
View::drawableStateChanged();
|
View::drawableStateChanged();
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#define __NGLUI_GROUPVIEW_H__
|
#define __NGLUI_GROUPVIEW_H__
|
||||||
|
|
||||||
#include <widget/view.h>
|
#include <widget/view.h>
|
||||||
#include <scroller.h>
|
#include <core/scroller.h>
|
||||||
|
|
||||||
namespace cdroid {
|
namespace cdroid {
|
||||||
|
|
||||||
@ -80,9 +80,6 @@ private:
|
|||||||
std::vector<View*>mVisibilityChangingChildren;
|
std::vector<View*>mVisibilityChangingChildren;
|
||||||
int mChildCountWithTransientState;
|
int mChildCountWithTransientState;
|
||||||
class TouchTarget* mFirstTouchTarget;
|
class TouchTarget* mFirstTouchTarget;
|
||||||
RECT focusRectSrc;
|
|
||||||
RECT focusRectDest;
|
|
||||||
RECT focusRect;
|
|
||||||
POINT animateTo;//save window boundray while animating
|
POINT animateTo;//save window boundray while animating
|
||||||
POINT animateFrom;//window animate from boundary
|
POINT animateFrom;//window animate from boundary
|
||||||
Transformation* mChildTransformation;
|
Transformation* mChildTransformation;
|
||||||
@ -104,8 +101,6 @@ private:
|
|||||||
bool dispatchTransformedGenericPointerEvent(MotionEvent& event, View* child);
|
bool dispatchTransformedGenericPointerEvent(MotionEvent& event, View* child);
|
||||||
|
|
||||||
void setTouchscreenBlocksFocusNoRefocus(bool touchscreenBlocksFocus);
|
void setTouchscreenBlocksFocusNoRefocus(bool touchscreenBlocksFocus);
|
||||||
void moveFocusTo(const RECT&r);
|
|
||||||
void invalidateChildrenInFocusRect();
|
|
||||||
void addInArray(View* child, int index);
|
void addInArray(View* child, int index);
|
||||||
bool removeViewInternal(View* view);
|
bool removeViewInternal(View* view);
|
||||||
void removeViewInternal(int index, View* view);
|
void removeViewInternal(int index, View* view);
|
||||||
@ -161,7 +156,6 @@ protected:
|
|||||||
|
|
||||||
void drawableStateChanged()override;
|
void drawableStateChanged()override;
|
||||||
std::vector<int> onCreateDrawableState()const override;
|
std::vector<int> onCreateDrawableState()const override;
|
||||||
virtual void onDraw(Canvas& canvas) override;
|
|
||||||
void dispatchSetPressed(bool pressed)override;
|
void dispatchSetPressed(bool pressed)override;
|
||||||
virtual int getChildDrawingOrder(int childCount, int i);
|
virtual int getChildDrawingOrder(int childCount, int i);
|
||||||
|
|
||||||
@ -257,7 +251,6 @@ public:
|
|||||||
bool dispatchUnhandledMove(View* focused, int direction)override;
|
bool dispatchUnhandledMove(View* focused, int direction)override;
|
||||||
bool dispatchTouchEvent(MotionEvent& event)override;
|
bool dispatchTouchEvent(MotionEvent& event)override;
|
||||||
bool onInterceptTouchEvent(MotionEvent& evt);
|
bool onInterceptTouchEvent(MotionEvent& evt);
|
||||||
virtual void onDrawFocusRect(Canvas&,const RECT&);
|
|
||||||
|
|
||||||
void jumpDrawablesToCurrentState()override;
|
void jumpDrawablesToCurrentState()override;
|
||||||
void setAddStatesFromChildren(bool addsStates);
|
void setAddStatesFromChildren(bool addsStates);
|
||||||
|
@ -1144,7 +1144,9 @@ void ViewPager::completeScroll(bool postEvents){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (needPopulate) {
|
if (needPopulate) {
|
||||||
if (postEvents) postOnAnimation([this](){setScrollState(SCROLL_STATE_IDLE);populate();});//mEndScrollRunnable);
|
Runnable r;
|
||||||
|
r=[this](){setScrollState(SCROLL_STATE_IDLE);populate();};
|
||||||
|
if (postEvents) postOnAnimation(r);//mEndScrollRunnable);
|
||||||
else {
|
else {
|
||||||
setScrollState(SCROLL_STATE_IDLE);
|
setScrollState(SCROLL_STATE_IDLE);
|
||||||
populate();
|
populate();
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include <widget/viewgroup.h>
|
#include <widget/viewgroup.h>
|
||||||
#include <widget/adapter.h>
|
#include <widget/adapter.h>
|
||||||
#include <widget/edgeeffect.h>
|
#include <widget/edgeeffect.h>
|
||||||
#include <velocitytracker.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
namespace cdroid{
|
namespace cdroid{
|
||||||
@ -121,7 +120,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Determines speed during touch scrolling
|
* Determines speed during touch scrolling
|
||||||
*/
|
*/
|
||||||
VelocityTracker* mVelocityTracker;
|
class VelocityTracker* mVelocityTracker;
|
||||||
int mMinimumVelocity;
|
int mMinimumVelocity;
|
||||||
int mMaximumVelocity;
|
int mMaximumVelocity;
|
||||||
int mFlingDistance;
|
int mFlingDistance;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user