#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <FL/Fl.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>

class Fl_Touchscreen : public Fl_Scroll {
	private:
		int _y, _x, _oy, _ox;
		void bbox(int& X, int& Y, int& W, int& H) {
			X = x()+Fl::box_dx(box());
			Y = y()+Fl::box_dy(box());
			W = w()-Fl::box_dw(box());
			H = h()-Fl::box_dh(box());
			if (scrollbar.visible()) {
				W -= scrollbar.w();
				if (scrollbar.align() & FL_ALIGN_LEFT) X += scrollbar.w();
			}
			if (hscrollbar.visible()) {
				H -= hscrollbar.h();
				if (scrollbar.align() & FL_ALIGN_TOP) Y += hscrollbar.h();
			}
		}
	public:
		Fl_Touchscreen(int x, int y, int w, int h, const char *L = 0):Fl_Scroll(x,y,w,h,L){
			type(0);
		}
		int handle(int event){
			if (event == FL_PUSH){
				_ox = _x = Fl::event_x();
				_oy = _y = Fl::event_y();
				return 1;
			}
			else if (event == FL_RELEASE){
				if (abs(Fl::event_x()-_ox) <= (w()/50) && abs(Fl::event_y()-_oy) <= (h()/50)){
					Fl_Group::handle(FL_PUSH);
					Fl::flush();
					usleep(200000);
					return Fl_Group::handle(FL_RELEASE);
				}
				return 1;
			}
			else if (event == FL_DRAG){
				// accumulate bounding box of children:
				int l; int r; int t; int b;

				l = t = 99999;
				r = b = 0;
				Fl_Widget*const* a = array();
				for (int i=children()-2; i--;) {
					Fl_Object* o = *a++;
					if (o->x() < l) l = o->x();
					if (o->y() < t) t = o->y();
					if (o->x()+o->w() > r) r = o->x()+o->w();
					if (o->y()+o->h() > b) b = o->y()+o->h();
				}
				position(xposition()-(Fl::event_x()-_x), yposition()-(Fl::event_y()-_y));
				if (xposition() < 0)
					position(0, yposition());
				if (yposition() < 0)
					position(xposition(), 0);
				if (xposition() > (r-l)-w())
					position((r-l)-w(), yposition());
				if (yposition() > (b-t)-h())
					position(xposition(), (b-t)-h());
				_x = Fl::event_x();
				_y = Fl::event_y();
				return 0;
			}
			return Fl_Group::handle(event);
		}
};

void callback(Fl_Widget *w, void *p){
	printf((char *)p);
}

int main(){
	Fl_Window *w;
	Fl_Touchscreen *s;
	Fl_Button *b;

	w = new Fl_Window(0,0,Fl::w(), Fl::h(), "Scroll Test");
	s = new Fl_Touchscreen(0,0,w->w(),w->h());
	b = new Fl_Button(0,0,s->w(),100,"Button");
	b->callback(callback, strdup("Top\n"));
	b = new Fl_Button(0,s->h()/2,s->w(),100,"Scroll down");
	b->box(FL_NO_BOX);
	b = new Fl_Button(0,s->h()*1.5,s->w(),100,"Scroll down");
	b->box(FL_NO_BOX);
	b = new Fl_Button(0,s->h()*2,s->w(),100,"Button");
	b->callback(callback, strdup("Bottom\n"));
	s->end();
	w->end();
	w->resizable(w);
	w->show();
	return Fl::run();
}
