Android: Made popup and menu windows work, fixed Fl::wait() recursion,

fixed incompatible Fl::wait() behavior.

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12793 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2018-03-24 13:06:59 +00:00
parent db55dfbbd6
commit 79b31708de
6 changed files with 252 additions and 158 deletions

View File

@ -90,143 +90,193 @@ int main(int argc, char **argv)
#elif 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Value_Slider.H>
#include <FL/Fl_Hor_Value_Slider.H>
#include <FL/Fl_Toggle_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_Pixmap.H>
#include <FL/fl_draw.H>
int N = 0;
#define W 70
#define H 70
#define ROWS 7
#define COLS 6
#include "/Users/matt/dev/fltk-1.4.svn/test/pixmaps/blast.xpm"
Fl_Toggle_Button *imageb, *imageovertextb, *imagenexttotextb, *imagebackdropb;
Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*clipb,*wrapb;
Fl_Box *text;
Fl_Input *input;
Fl_Hor_Value_Slider *fonts;
Fl_Hor_Value_Slider *sizes;
Fl_Double_Window *window;
Fl_Value_Slider *orientation;
Fl_Value_Slider *size;
Fl_Pixmap *img;
void slider_cb(Fl_Widget *, void *) {
static char buf[80];
int val = (int)orientation->value();
int sze = (int)size->value();
for (int i = window->children(); i--; ) { // all window children
Fl_Widget *wc = window->child(i);
const char *l = (const char *)(wc->user_data());
if ( l && *l == '@' ) { // all children with '@'
l ++;
if ( wc->box() == FL_NO_BOX ) { // ascii legend?
if (val&&sze) sprintf(buf, "@@%+d%d%s", sze, val, l);
else if (val) sprintf(buf, "@@%d%s", val, l);
else if (sze) sprintf(buf, "@@%+d%s", sze, l);
else sprintf(buf, "@@%s", l);
} else { // box with symbol
if (val&&sze) sprintf(buf, "@%+d%d%s", sze, val, l);
else if (val) sprintf(buf, "@%d%s", val, l);
else if (sze) sprintf(buf, "@%+d%s", sze, l);
else sprintf(buf, "@%s", l);
}
wc->copy_label(buf);
}
void button_cb(Fl_Widget *,void *) {
int i = 0;
if (leftb->value()) i |= FL_ALIGN_LEFT;
if (rightb->value()) i |= FL_ALIGN_RIGHT;
if (topb->value()) i |= FL_ALIGN_TOP;
if (bottomb->value()) i |= FL_ALIGN_BOTTOM;
if (insideb->value()) i |= FL_ALIGN_INSIDE;
if (clipb->value()) i |= FL_ALIGN_CLIP;
if (wrapb->value()) i |= FL_ALIGN_WRAP;
if (imageovertextb->value()) i |= FL_ALIGN_TEXT_OVER_IMAGE;
if (imagenexttotextb->value()) i |= FL_ALIGN_IMAGE_NEXT_TO_TEXT;
if (imagebackdropb->value()) i |= FL_ALIGN_IMAGE_BACKDROP;
text->align(i);
window->redraw();
}
void image_cb(Fl_Widget *,void *) {
if (imageb->value())
text->image(img);
else
text->image(0);
window->redraw();
}
void font_cb(Fl_Widget *,void *) {
text->labelfont(int(fonts->value()));
window->redraw();
}
void size_cb(Fl_Widget *,void *) {
text->labelsize(int(sizes->value()));
window->redraw();
}
void input_cb(Fl_Widget *,void *) {
text->label(input->value());
window->redraw();
}
void normal_cb(Fl_Widget *,void *) {
text->labeltype(FL_NORMAL_LABEL);
window->redraw();
}
void symbol_cb(Fl_Widget *,void *) {
text->labeltype(FL_SYMBOL_LABEL);
if (input->value()[0] != '@') {
input->static_value("@->");
text->label("@->");
}
window->redraw();
}
void bt(const char *name) {
int x = N%COLS;
int y = N/COLS;
char buf[255];
N++;
x = x*W+10;
y = y*H+10;
sprintf(buf, "@%s", name);
Fl_Box *a = new Fl_Box(x,y,W-20,H-20);
a->box(FL_NO_BOX);
a->copy_label(buf);
a->align(FL_ALIGN_BOTTOM);
a->labelsize(11);
a->user_data((void *)name);
Fl_Box *b = new Fl_Box(x,y,W-20,H-20);
b->box(FL_UP_BOX);
b->copy_label(name);
b->labelcolor(FL_DARK3);
b->user_data((void *)name);
void shadow_cb(Fl_Widget *,void *) {
text->labeltype(FL_SHADOW_LABEL);
window->redraw();
}
int main(int argc, char ** argv) {
window = new Fl_Double_Window(COLS*W,ROWS*H+60);
bt("@->");
bt("@>");
bt("@>>");
bt("@>|");
bt("@>[]");
bt("@|>");
bt("@<-");
bt("@<");
bt("@<<");
bt("@|<");
bt("@[]<");
bt("@<|");
bt("@<->");
bt("@-->");
bt("@+");
bt("@->|");
bt("@||");
bt("@<|");
bt("@<->");
bt("@-->");
bt("@+");
bt("@->|");
bt("@||");
bt("@arrow");
bt("@returnarrow");
bt("@square");
bt("@circle");
bt("@line");
bt("@menu");
bt("@UpArrow");
bt("@DnArrow");
bt("@search");
bt("@FLTK");
bt("@filenew");
bt("@fileopen");
bt("@filesave");
bt("@filesaveas");
bt("@fileprint");
bt("@refresh");
bt("@reload");
bt("@undo");
bt("@redo");
void embossed_cb(Fl_Widget *,void *) {
text->labeltype(FL_EMBOSSED_LABEL);
window->redraw();
}
orientation = new Fl_Value_Slider(
(int)(window->w()*.05+.5), window->h()-40,
(int)(window->w()*.42+.5), 16, "Orientation");
orientation->type(FL_HORIZONTAL);
orientation->range(0.0, 9.0);
orientation->value(0.0);
orientation->step(1);
orientation->callback(slider_cb, 0);
void engraved_cb(Fl_Widget *,void *) {
text->labeltype(FL_ENGRAVED_LABEL);
window->redraw();
}
size = new Fl_Value_Slider(
(int)(window->w()*.53+.5), window->h()-40,
(int)(window->w()*.42+.5), 16, "Size");
size->type(FL_HORIZONTAL);
size->range(-3.0, 9.0);
size->value(0.0);
size->step(1);
size->callback(slider_cb, 0);
Fl_Menu_Item choices[] = {
{"FL_NORMAL_LABEL",0,normal_cb},
{"FL_SYMBOL_LABEL",0,symbol_cb},
{"FL_SHADOW_LABEL",0,shadow_cb},
{"FL_ENGRAVED_LABEL",0,engraved_cb},
{"FL_EMBOSSED_LABEL",0,embossed_cb},
{0}};
window->resizable(window);
int main(int argc, char **argv) {
img = new Fl_Pixmap(blast_xpm);
window = new Fl_Double_Window(440,420);
input = new Fl_Input(70,375,350,25,"Label:");
input->static_value("The quick brown fox jumped over the lazy dog.");
input->when(FL_WHEN_CHANGED);
input->callback(input_cb);
input->tooltip("label text");
sizes= new Fl_Hor_Value_Slider(70,350,350,25,"Size:");
sizes->align(FL_ALIGN_LEFT);
sizes->bounds(1,64);
sizes->step(1);
sizes->value(14);
sizes->callback(size_cb);
fonts=new Fl_Hor_Value_Slider(70,325,350,25,"Font:");
fonts->align(FL_ALIGN_LEFT);
fonts->bounds(0,15);
fonts->step(1);
fonts->value(0);
fonts->callback(font_cb);
Fl_Group *g = new Fl_Group(70,275,350,50);
imageb = new Fl_Toggle_Button(70,275,50,25,"image");
imageb->callback(image_cb);
imageb->tooltip("show image");
imageovertextb = new Fl_Toggle_Button(120,275,50,25,"T o I");
imageovertextb->callback(button_cb);
imageovertextb->tooltip("FL_ALIGN_TEXT_OVER_IMAGE");
imagenexttotextb = new Fl_Toggle_Button(170,275,50,25,"I | T");
imagenexttotextb->callback(button_cb);
imagenexttotextb->tooltip("FL_ALIGN_IMAGE_NEXT_TO_TEXT");
imagebackdropb = new Fl_Toggle_Button(220,275,50,25,"back");
imagebackdropb->callback(button_cb);
imagebackdropb->tooltip("FL_ALIGN_IMAGE_BACKDROP");
leftb = new Fl_Toggle_Button(70,300,50,25,"left");
leftb->callback(button_cb);
leftb->tooltip("FL_ALIGN_LEFT");
rightb = new Fl_Toggle_Button(120,300,50,25,"right");
rightb->callback(button_cb);
rightb->tooltip("FL_ALIGN_RIGHT");
topb = new Fl_Toggle_Button(170,300,50,25,"top");
topb->callback(button_cb);
topb->tooltip("FL_ALIGN_TOP");
bottomb = new Fl_Toggle_Button(220,300,50,25,"bottom");
bottomb->callback(button_cb);
bottomb->tooltip("FL_ALIGN_BOTTOM");
insideb = new Fl_Toggle_Button(270,300,50,25,"inside");
insideb->callback(button_cb);
insideb->tooltip("FL_ALIGN_INSIDE");
wrapb = new Fl_Toggle_Button(320,300,50,25,"wrap");
wrapb->callback(button_cb);
wrapb->tooltip("FL_ALIGN_WRAP");
clipb = new Fl_Toggle_Button(370,300,50,25,"clip");
clipb->callback(button_cb);
clipb->tooltip("FL_ALIGN_CLIP");
g->resizable(insideb);
g->end();
Fl_Choice *c = new Fl_Choice(70,250,200,25);
c->menu(choices);
text = new Fl_Box(FL_FRAME_BOX,120,75,200,100,input->value());
text->align(FL_ALIGN_CENTER);
window->resizable(text);
window->end();
window->show(argc,argv);
return Fl::run();
}
#else
#include <src/drivers/Android/Fl_Android_Application.H>
@ -384,7 +434,7 @@ test/connect.cxx test/shape.cxx
test/cube.cxx test/subwindow.cxx
test/cursor.cxx test/sudoku.cxx
test/curve.cxx
* test/symbols.cxx : !! working this out: implement circle drawing
* test/symbols.cxx : + 'symbols' working as expected
test/demo.cxx test/table.cxx
test/device.cxx test/threads.cxx
test/doublebuffer.cxx test/tile.cxx
@ -406,6 +456,6 @@ test/image.cxx test/unittest_viewport.cxx
test/input.cxx test/unittests.cxx
test/input_choice.cxx test/utf8.cxx
test/keyboard.cxx test/windowfocus.cxx
test/label.cxx
* test/label.cxx : - pop menu locks, pixmap, keyboard events
*/

View File

@ -892,10 +892,10 @@ void Fl_Android_Graphics_Driver::pie_unscaled(float xi, float yi, float w, float
* FIXME: these do not draw rotated ellipses correctly!
* */
void Fl_Android_Graphics_Driver::ellipse_unscaled(double xt, double yt, double rx, double ry) {
double llx = xt-rx;
double w = xt+rx-llx;
double lly = yt-ry;
double h = yt+ry-lly;
float llx = xt-rx;
float w = xt+rx-llx;
float lly = yt-ry;
float h = yt+ry-lly;
if (what==POLYGON)
pie_unscaled(llx, lly, w, h, 0.0, 360.0);

View File

@ -43,7 +43,7 @@ private:
int handle_app_command();
int handle_input_event();
int handle_keyboard_event(AInputEvent*);
int handle_mouse_event(AInputEvent*);
int handle_mouse_event(AInputQueue*, AInputEvent*);
public:
Fl_Android_Screen_Driver() : Fl_Screen_Driver(), pScreenContentChanged(false) { }

View File

@ -95,16 +95,18 @@ int Fl_Android_Screen_Driver::handle_input_event()
switch (AInputEvent_getType(event)) {
case AINPUT_EVENT_TYPE_KEY:
consumed = handle_keyboard_event(event);
AInputQueue_finishEvent(queue, event, consumed);
break;
case AINPUT_EVENT_TYPE_MOTION:
consumed = handle_mouse_event(event);
consumed = handle_mouse_event(queue, event);
break;
default:
// don't do anything. There may be additional event types in the future
AInputQueue_finishEvent(queue, event, consumed);
break;
}
// TODO: handle all events here
AInputQueue_finishEvent(queue, event, consumed);
// AInputQueue_finishEvent(queue, event, consumed);
}
}
return 0;
@ -119,7 +121,8 @@ int Fl_Android_Screen_Driver::handle_keyboard_event(AInputEvent *event)
return 0;
}
int Fl_Android_Screen_Driver::handle_mouse_event(AInputEvent *event)
int Fl_Android_Screen_Driver::handle_mouse_event(AInputQueue *queue, AInputEvent *event)
{
int ex = Fl::e_x_root = (int)(AMotionEvent_getX(event, 0) * 600 /
ANativeWindow_getWidth(Fl_Android_Application::native_window()));
@ -130,14 +133,19 @@ int Fl_Android_Screen_Driver::handle_mouse_event(AInputEvent *event)
Fl_Window *win = Fl::grab();
if (!win) {
win = Fl::first_window();
while (win) {
if (ex >= win->x() && ex < win->x() + win->w() && ey >= win->y() &&
ey < win->y() + win->h())
break;
win = Fl::next_window(win);
if (win && !win->modal()) {
while (win) {
if (ex >= win->x() && ex < win->x() + win->w() && ey >= win->y() &&
ey < win->y() + win->h())
break;
win = Fl::next_window(win);
}
}
}
if (!win) return 0;
if (!win) {
AInputQueue_finishEvent(queue, event, 0);
return 0;
}
if (win) {
Fl::e_x = ex-win->x();
@ -150,14 +158,19 @@ int Fl_Android_Screen_Driver::handle_mouse_event(AInputEvent *event)
Fl::e_state = FL_BUTTON1;
Fl::e_keysym = FL_Button + 1;
if (AMotionEvent_getAction(event) == AMOTION_EVENT_ACTION_DOWN) {
AInputQueue_finishEvent(queue, event, 1);
Fl::e_is_click = 1;
if (win) Fl::handle(FL_PUSH, win); // do NOT send a push event into the "Desktop"
Fl_Android_Application::log_i("Mouse push %d at %d, %d", Fl::event_button(), Fl::event_x(), Fl::event_y());
} else if (AMotionEvent_getAction(event) == AMOTION_EVENT_ACTION_MOVE) {
AInputQueue_finishEvent(queue, event, 1);
Fl::handle(FL_DRAG, win);
} else if (AMotionEvent_getAction(event) == AMOTION_EVENT_ACTION_UP) {
AInputQueue_finishEvent(queue, event, 1);
Fl::e_state = 0;
Fl::handle(FL_RELEASE, win);
} else {
AInputQueue_finishEvent(queue, event, 0);
}
return 1;
}
@ -176,29 +189,47 @@ int Fl_Android_Screen_Driver::handle_queued_events(double time_to_wait)
// Read all pending events.
int ident;
int events;
struct android_poll_source *source;
for (;;) {
ident = ALooper_pollAll(Fl::damage() ? 0 : -1, nullptr, &events, (void **) &source);
switch (ident) {
// FIXME: ALOOPER_POLL_WAKE = -1, ALOOPER_POLL_CALLBACK = -2, ALOOPER_POLL_TIMEOUT = -3, ALOOPER_POLL_ERROR = -4
case Fl_Android_Application::LOOPER_ID_MAIN:
ret = handle_app_command();
break;
case Fl_Android_Application::LOOPER_ID_INPUT:
ret = handle_input_event();
break;
case Fl_Android_Application::LOOPER_ID_TIMER:
timer_do_callback(Fl_Android_Application::receive_timer_index());
break;
case -3: return ret;
default: return ret;
}
ident = ALooper_pollAll(Fl::damage() ? 0 : -1, nullptr, &events, nullptr);
switch (ident) {
case Fl_Android_Application::LOOPER_ID_MAIN:
ret = handle_app_command();
break;
case Fl_Android_Application::LOOPER_ID_INPUT:
ret = handle_input_event();
break;
case Fl_Android_Application::LOOPER_ID_TIMER:
timer_do_callback(Fl_Android_Application::receive_timer_index());
break;
case ALOOPER_POLL_WAKE:
Fl_Android_Application::log_e("Someone woke up ALooper_pollAll.");
break;
case ALOOPER_POLL_CALLBACK:
Fl_Android_Application::log_e(
"Someone added a callback to ALooper_pollAll.");
break;
case ALOOPER_POLL_TIMEOUT:
// timer expired
break;
case ALOOPER_POLL_ERROR:
Fl_Android_Application::log_e(
"Something caused an ERROR in ALooper_pollAll.");
break;
default:
Fl_Android_Application::log_e(
"Unknown return value from ALooper_pollAll.");
break;
}
return ret;
}
/**
* Wait for a maximum of `time_to_wait` until something happens.
* @param time_to_wait in seconds
* @return We really do not know; check other platforms to see what is
* consistent here.
* FIXME: return the remaining time to reach 'time_to_wait'
*/
double Fl_Android_Screen_Driver::wait(double time_to_wait)
{
Fl::run_checks();
@ -229,7 +260,7 @@ double Fl_Android_Screen_Driver::wait(double time_to_wait)
fl_lock_function();
}
return 0.0; // FIXME: return the remaining time to reach 'time_to_wait'
return 0.0;
}

View File

@ -71,12 +71,17 @@ private:
#endif
public:
Fl_Android_Window_Driver(Fl_Window *w) : Fl_Window_Driver(w) {}
~Fl_Android_Window_Driver() {}
static inline Fl_Android_Window_Driver* driver(Fl_Window *w) {
return (Fl_Android_Window_Driver*)w->driver();
}
Fl_Android_Window_Driver(Fl_Window *w) : Fl_Window_Driver(w) {}
virtual ~Fl_Android_Window_Driver() override {}
virtual void make_current() override;
virtual void show() override;
virtual void hide() override;
#if 0
HDC private_dc; // used for OpenGL
RECT border_width_title_bar_height(int &bx, int &by, int &bt);
@ -103,13 +108,8 @@ public:
virtual void flush_double();
virtual void flush_overlay();
virtual void draw_begin();
#endif
virtual void make_current();
virtual void show();
#if 0
virtual void label(const char *name,const char *iname);
virtual void resize(int X,int Y,int W,int H);
virtual void hide();
virtual void map();
virtual void unmap();
virtual void fullscreen_on();
@ -136,8 +136,6 @@ public:
void wait_for_expose() { wait_for_expose_value = 1; }
static void expose_all();
// Leuwer: 0171 473 1850
};

View File

@ -76,10 +76,25 @@ void Fl_Android_Window_Driver::show()
}
} else {
// bring window to front
Fl::first_window(pWindow); // TODO: does this really work?
expose_all();
}
}
void Fl_Android_Window_Driver::hide()
{
Fl_X* ip = Fl_X::i(pWindow);
if (hide_common()) return;
if (ip->region) {
delete ip->region;
ip->region = nullptr;
}
delete ip;
expose_all();
}
void Fl_Android_Window_Driver::expose_all()
{
for (Fl_X *x = Fl_X::first; x; x = x->next) {