Adding crude Android native screen driver
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12695 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
9e29ea8a00
commit
b19efed409
38
FL/android.H
Normal file
38
FL/android.H
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// "$Id: android.H 12643 2018-01-31 22:49:52Z AlbrechtS $"
|
||||
//
|
||||
// Template header file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2016-2018 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
// Do not directly include this file, instead use <FL/android.H>.
|
||||
|
||||
// These types and variables give access to internal, platform-specific data through the public API.
|
||||
// They require to include platform.H (in contrast to types defined in platform_types.h)
|
||||
|
||||
#if !defined(FL_PLATFORM_H)
|
||||
# error "Never use <FL/android.H> directly; include <FL/platform.H> instead."
|
||||
#endif // !FL_PLATFORM_H
|
||||
|
||||
typedef void *Window; // used by fl_find(), fl_xid() and class Fl_X
|
||||
|
||||
/* Reference to the current device context
|
||||
For back-compatibility only. The preferred procedure to get this reference is
|
||||
Fl_Surface_Device::surface()->driver()->gc().
|
||||
*/
|
||||
extern void *fl_gc;
|
||||
|
||||
//
|
||||
// End of "$Id: android.H 12643 2018-01-31 22:49:52Z AlbrechtS $".
|
||||
//
|
@ -45,6 +45,8 @@ class Fl_Window;
|
||||
# elif defined(FL_PORTING)
|
||||
# pragma message "FL_PORTING: write a header file based on this file, win32.H, or mac.H to define the FLTK core internals"
|
||||
# include "porting.H"
|
||||
# elif defined(__ANDROID__)
|
||||
# include "android.H"
|
||||
# else // X11
|
||||
# include <FL/fl_types.h>
|
||||
# include <FL/Enumerations.H>
|
||||
|
252
src/drivers/Android/Fl_Android_Graphics_Driver.H
Normal file
252
src/drivers/Android/Fl_Android_Graphics_Driver.H
Normal file
@ -0,0 +1,252 @@
|
||||
//
|
||||
// "$Id: Fl_Android_Graphics_Driver.H 12656 2018-02-09 16:59:34Z manolo $"
|
||||
//
|
||||
// Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2018 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_GDI_Graphics_Driver.H
|
||||
\brief Definition of Windows GDI graphics driver.
|
||||
*/
|
||||
|
||||
#ifndef FL_GDI_GRAPHICS_DRIVER_H
|
||||
#define FL_GDI_GRAPHICS_DRIVER_H
|
||||
|
||||
#include <FL/Fl_Graphics_Driver.H>
|
||||
//#include <windows.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if 0
|
||||
// clipping
|
||||
// 1: rect
|
||||
// Draw only the part of any element that fits inside the rect
|
||||
// 2: region
|
||||
// A rect that contains the entire region
|
||||
// A sorted list of rows that contains fitting parts of the region
|
||||
// A sorted list of rects for each row
|
||||
|
||||
class AFl_Rect
|
||||
{
|
||||
int pX1, pY1, pX2, pY2;
|
||||
public:
|
||||
const int int_max = INT_MAX;
|
||||
const int int_min = INT_MIN;
|
||||
AFl_Rect(int x1, y1, x2, y2) : pX1(x1), pY1(y1), pX2(x2), pY2(y2) { }
|
||||
AFl_Rect() : pX1(int_min), pY1(int_min), pX2(int_max), pY2(int_max) { }
|
||||
void x1(int x) { pX1 = x; }
|
||||
void y1(int y) { pY1 = y; }
|
||||
void x2(int x) { pX2 = x; }
|
||||
void y2(int y) { pY2 = y; }
|
||||
void w(int w) { pX2 = x1+w; }
|
||||
void h(int h) { pY2 = y1+w; }
|
||||
int x1() { return pX1; }
|
||||
int y1() { return pY1; }
|
||||
int x2() { return pX2; }
|
||||
int y2() { return pY2; }
|
||||
int w() { return pX2-pX1; }
|
||||
int h() { return pY2-pY1; }
|
||||
};
|
||||
|
||||
class AFl_Row
|
||||
{
|
||||
int nRect, NRect;
|
||||
AFl_Rect *pRect;
|
||||
AFl_rect pBounds;
|
||||
public:
|
||||
AFl_Row(int y1, int y2) : nRect(0), NRect(0), pRect(0), pY1(y1), pY2(y2) { }
|
||||
~AFl_Row() { /* TODO: delete all rects */ }
|
||||
void y1(int y) { pY1 = y; }
|
||||
void y2(int y) { pY2 = y; }
|
||||
AFl_Rect *first(int &i) { i=0; return (pRect && nRect>i) ? nRect[i] : 0L; }
|
||||
AFl_Rect *next(int &i) { i++; return (pRect && nRect>i) ? nRect[i] : 0L; }
|
||||
void add(AFl_Rect *r) { /* TODO: implement! */ }
|
||||
void subtract(AFl_Rect *r) { /* TODO: implement! */ }
|
||||
void clear() { /* TODO: implement! */ }
|
||||
};
|
||||
|
||||
class AFl_Region
|
||||
{
|
||||
int nRow, NRow;
|
||||
AFl_Row *pRow;
|
||||
AFl_rect pBounds;
|
||||
public:
|
||||
AFl_Region() : nRow(0), NRow(0), pRow(0) { }
|
||||
~AFl_Region() { /* TODO: delete all rows */ }
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
\brief The Windows-specific graphics driver class.
|
||||
|
||||
This class is implemented only on the Windows platform.
|
||||
*/
|
||||
class FL_EXPORT Fl_Android_Graphics_Driver : public Fl_Scalable_Graphics_Driver {
|
||||
|
||||
#if 0
|
||||
private:
|
||||
BOOL alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch);
|
||||
int depth; // to support translation
|
||||
POINT *origins; // to support translation
|
||||
void set_current_();
|
||||
protected:
|
||||
HDC gc_;
|
||||
int numcount;
|
||||
int counts[20];
|
||||
uchar **mask_bitmap_;
|
||||
uchar **mask_bitmap() {return mask_bitmap_;}
|
||||
void mask_bitmap(uchar **value) { mask_bitmap_ = value; }
|
||||
int p_size;
|
||||
POINT *p;
|
||||
public:
|
||||
Fl_GDI_Graphics_Driver() {mask_bitmap_ = NULL; gc_ = NULL; p_size = 0; p = NULL; depth = -1; origins = NULL;}
|
||||
virtual ~Fl_GDI_Graphics_Driver() { if (p) free(p); delete[] origins;}
|
||||
virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
|
||||
char can_do_alpha_blending();
|
||||
virtual void gc(void *ctxt) { gc_ = (HDC)ctxt; global_gc(); }
|
||||
virtual void *gc() {return gc_;}
|
||||
|
||||
// --- bitmap stuff
|
||||
Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
|
||||
void delete_bitmask(Fl_Bitmask bm);
|
||||
#endif
|
||||
virtual void draw_unscaled(const char* str, int n, int x, int y);
|
||||
#if 0
|
||||
virtual void draw_unscaled(int angle, const char *str, int n, int x, int y);
|
||||
virtual void rtl_draw_unscaled(const char* str, int n, int x, int y);
|
||||
virtual void font_unscaled(Fl_Font face, Fl_Fontsize size);
|
||||
void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void draw_unscaled(Fl_Bitmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void draw_unscaled(Fl_RGB_Image *img, float s, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP);
|
||||
virtual void draw_image_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
|
||||
virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
|
||||
virtual void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
|
||||
virtual void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
|
||||
fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array);
|
||||
virtual void uncache_pixmap(fl_uintptr_t p);
|
||||
fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array);
|
||||
void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
|
||||
virtual double width_unscaled(const char *str, int n);
|
||||
virtual double width_unscaled(unsigned int c);
|
||||
void text_extents_unscaled(const char*, int n, int& dx, int& dy, int& w, int& h);
|
||||
int height_unscaled();
|
||||
int descent_unscaled();
|
||||
Fl_Fontsize size_unscaled();
|
||||
#if ! defined(FL_DOXYGEN)
|
||||
void copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy);
|
||||
#endif
|
||||
virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
|
||||
void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
|
||||
Fl_Region XRectangleRegion(int x, int y, int w, int h);
|
||||
void XDestroyRegion(Fl_Region r);
|
||||
void translate_all(int x, int y);
|
||||
void untranslate_all(void);
|
||||
static HRGN scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr);
|
||||
virtual void scale(float f);
|
||||
protected:
|
||||
void transformed_vertex0(float x, float y);
|
||||
void fixloop();
|
||||
// --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/gdi_rect.cxx
|
||||
virtual void point_unscaled(float x, float y);
|
||||
void rect_unscaled(float x, float y, float w, float h);
|
||||
void focus_rect(int x, int y, int w, int h);
|
||||
#endif
|
||||
void rectf_unscaled(float x, float y, float w, float h);
|
||||
#if 0
|
||||
virtual void line_unscaled(float x, float y, float x1, float y1);
|
||||
virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2);
|
||||
#endif
|
||||
virtual void xyline_unscaled(float x, float y, float x1);
|
||||
virtual void yxline_unscaled(float x, float y, float y1);
|
||||
#if 0
|
||||
virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
|
||||
virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
|
||||
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
|
||||
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
|
||||
// --- clipping
|
||||
void push_clip(int x, int y, int w, int h);
|
||||
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
|
||||
int not_clipped(int x, int y, int w, int h);
|
||||
void push_no_clip();
|
||||
void pop_clip();
|
||||
void restore_clip();
|
||||
virtual Fl_Region scale_clip(float f);
|
||||
// --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
|
||||
void begin_complex_polygon();
|
||||
void end_points();
|
||||
void end_line();
|
||||
void end_loop();
|
||||
void end_polygon();
|
||||
void end_complex_polygon();
|
||||
void gap();
|
||||
virtual void ellipse_unscaled(double xt, double yt, double rx, double ry);
|
||||
// --- implementation is in src/fl_arc.cxx which includes src/cfg_gfx/xxx_arc.cxx if needed
|
||||
// using void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end);
|
||||
// --- implementation is in src/fl_arci.cxx which includes src/cfg_gfx/xxx_arci.cxx
|
||||
virtual void arc_unscaled(float x, float y, float w, float h, double a1, double a2);
|
||||
virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2);
|
||||
// --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
|
||||
virtual void line_style_unscaled(int style, float width, char* dashes);
|
||||
// --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
|
||||
void color(Fl_Color c);
|
||||
void color(uchar r, uchar g, uchar b);
|
||||
Fl_Color color() { return color_; }
|
||||
void set_color(Fl_Color i, unsigned int c);
|
||||
void free_color(Fl_Color i, int overlay);
|
||||
void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win);
|
||||
void reset_spot();
|
||||
virtual Fl_Font set_fonts(const char *name);
|
||||
virtual int get_font_sizes(Fl_Font fnum, int*& sizep);
|
||||
virtual const char* get_font_name(Fl_Font fnum, int* ap);
|
||||
virtual const char *font_name(int num);
|
||||
virtual void font_name(int num, const char *name);
|
||||
void global_gc();
|
||||
virtual void overlay_rect(int x, int y, int w , int h);
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
The graphics driver used when printing on Windows.
|
||||
|
||||
This class is implemented only on the Windows platform.
|
||||
It is extremely similar to Fl_GDI_Graphics_Driver.
|
||||
*/
|
||||
class FL_EXPORT Fl_Android_Printer_Graphics_Driver : public Fl_Android_Graphics_Driver {
|
||||
|
||||
#if 0
|
||||
|
||||
private:
|
||||
typedef BOOL (WINAPI* transparent_f_type) (HDC,int,int,int,int,HDC,int,int,int,int,UINT);
|
||||
transparent_f_type TransparentBlt();
|
||||
public:
|
||||
virtual int has_feature(driver_feature mask) { return mask & (NATIVE | PRINTER); }
|
||||
void draw_unscaled(Fl_Pixmap *pxm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
void draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP);
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_GDI_GRAPHICS_DRIVER_H
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Android_Graphics_Driver.H 12656 2018-02-09 16:59:34Z manolo $".
|
||||
//
|
492
src/drivers/Android/Fl_Android_Graphics_Driver.cxx
Normal file
492
src/drivers/Android/Fl_Android_Graphics_Driver.cxx
Normal file
@ -0,0 +1,492 @@
|
||||
//
|
||||
// "$Id: Fl_Android_Graphics_Driver.cxx 12655 2018-02-09 14:39:42Z AlbrechtS $"
|
||||
//
|
||||
// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2018 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
|
||||
#include "../../config_lib.h"
|
||||
#include "Fl_Android_Graphics_Driver.h"
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/platform.H>
|
||||
#include <errno.h>
|
||||
|
||||
#include "Fl_Android_Screen_Driver.H"
|
||||
#include <android/log.h>
|
||||
|
||||
extern ANativeWindow_Buffer* gAGraphicsBuffer;
|
||||
|
||||
#define LOG_TAG "libplasma"
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
||||
|
||||
|
||||
/*
|
||||
* By linking this module, the following static method will instantiate the
|
||||
* Windows GDI Graphics driver as the main display driver.
|
||||
*/
|
||||
Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
|
||||
{
|
||||
return new Fl_Android_Graphics_Driver();
|
||||
}
|
||||
|
||||
|
||||
static uint16_t make565(int red, int green, int blue)
|
||||
{
|
||||
return (uint16_t)( ((red << 8) & 0xf800) |
|
||||
((green << 3) & 0x07e0) |
|
||||
((blue >> 3) & 0x001f) );
|
||||
}
|
||||
|
||||
extern unsigned fl_cmap[256];
|
||||
|
||||
static uint16_t make565(Fl_Color crgba)
|
||||
{
|
||||
if (crgba<0x00000100) crgba = fl_cmap[crgba];
|
||||
return (uint16_t)( ((crgba >>16) & 0xf800) |
|
||||
((crgba >>13) & 0x07e0) |
|
||||
((crgba >>11) & 0x001f) );
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Graphics_Driver::rectf_unscaled(float x, float y, float w, float h) {
|
||||
if (w<=0 || h<=0) return;
|
||||
|
||||
// TODO: clip the rectangle to the window outline
|
||||
// TODO: clip the rectangle to all parts of the window region
|
||||
// TODo: clip the rectangle to all parts of the current clipping region
|
||||
|
||||
uint16_t cc = make565(color());
|
||||
uint32_t ss = gAGraphicsBuffer->stride;
|
||||
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
|
||||
uint32_t xx = (uint32_t)x;
|
||||
uint32_t yy = (uint32_t)y;
|
||||
uint32_t ww = (uint32_t)w;
|
||||
uint32_t hh = (uint32_t)h;
|
||||
for (uint32_t iy = yy; iy<hh; ++iy) {
|
||||
uint16_t *d = bits + iy*ss + xx;
|
||||
for (uint32_t ix = ww; ix>0; --ix) {
|
||||
*d++ = cc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Android_Graphics_Driver::xyline_unscaled(float x, float y, float x1)
|
||||
{
|
||||
uint16_t cc = make565(color());
|
||||
float w;
|
||||
if (x1>x) {
|
||||
w = x1-x;
|
||||
} else {
|
||||
w = x-x1;
|
||||
x = x1;
|
||||
}
|
||||
uint32_t ss = gAGraphicsBuffer->stride;
|
||||
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
|
||||
uint32_t xx = (uint32_t)x;
|
||||
uint32_t yy = (uint32_t)y;
|
||||
uint32_t ww = (uint32_t)w;
|
||||
uint16_t *d = bits + yy*ss + xx;
|
||||
for (uint32_t ix = ww; ix>0; --ix) {
|
||||
*d++ = cc;
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Android_Graphics_Driver::yxline_unscaled(float x, float y, float y1)
|
||||
{
|
||||
uint16_t cc = make565(color());
|
||||
float h;
|
||||
if (y1>y) {
|
||||
h = y1-y;
|
||||
} else {
|
||||
h = y-y1;
|
||||
y = y1;
|
||||
}
|
||||
uint32_t ss = gAGraphicsBuffer->stride;
|
||||
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
|
||||
uint32_t xx = (uint32_t)x;
|
||||
uint32_t yy = (uint32_t)y;
|
||||
uint32_t hh = (uint32_t)h;
|
||||
uint16_t *d = bits + yy*ss + xx;
|
||||
for (uint32_t iy = hh; iy>0; --iy) {
|
||||
*d = cc;
|
||||
d += ss;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -- fun with text rendering
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
|
||||
#include "stb_truetype.h"
|
||||
|
||||
unsigned char ttf_buffer[1<<25];
|
||||
|
||||
static int render_letter(int xx, int yy, uint32_t c)
|
||||
{
|
||||
static bool once = 0;
|
||||
static stbtt_fontinfo font;
|
||||
unsigned char *bitmap;
|
||||
int w,h,i,j, size = 30;
|
||||
int dx, dy;
|
||||
|
||||
LOGE("Render letter %c", c);
|
||||
if (once==0) {
|
||||
once = 1;
|
||||
FILE *f = fopen("/system/fonts/DroidSans.ttf", "rb");
|
||||
if (f==NULL) {
|
||||
LOGE("ERROR reading font %d!", errno);
|
||||
return 0;
|
||||
}
|
||||
fread(ttf_buffer, 1, 1<<25, f);
|
||||
|
||||
stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
|
||||
}
|
||||
|
||||
#if 0
|
||||
scale = stbtt_ScaleForPixelHeight(&font, 15);
|
||||
stbtt_GetFontVMetrics(&font, &ascent,0,0);
|
||||
baseline = (int) (ascent*scale);
|
||||
|
||||
while (text[ch]) {
|
||||
int advance,lsb,x0,y0,x1,y1;
|
||||
float x_shift = xpos - (float) floor(xpos);
|
||||
stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
|
||||
stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
|
||||
stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
|
||||
// note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
|
||||
// because this API is really for baking character bitmaps into textures. if you want to render
|
||||
// a sequence of characters, you really need to render each bitmap to a temp buffer, then
|
||||
// "alpha blend" that into the working buffer
|
||||
xpos += (advance * scale);
|
||||
if (text[ch+1])
|
||||
xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
|
||||
++ch;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, size), c, &w, &h, &dx, &dy);
|
||||
|
||||
// rrrr.rggg.gggb.bbbb
|
||||
xx += dx; yy += dy;
|
||||
uint16_t cc = make565(fl_color()), cc12 = (cc&0xf7de)>>1, cc14 = (cc12&0xf7de)>>1, cc34 = cc12+cc14;
|
||||
uint32_t ss = gAGraphicsBuffer->stride;
|
||||
uint16_t *bits = (uint16_t*)gAGraphicsBuffer->bits;
|
||||
uint32_t ww = w;
|
||||
uint32_t hh = h;
|
||||
unsigned char *s = bitmap;
|
||||
for (uint32_t iy = 0; iy<hh; ++iy) {
|
||||
uint16_t *d = bits + (yy+iy)*ss + xx;
|
||||
for (uint32_t ix = 0; ix<ww; ++ix) {
|
||||
#if 1
|
||||
// 5 step antialiasing
|
||||
unsigned char v = *s++;
|
||||
if (v>200) { // 100% black
|
||||
*d = cc;
|
||||
} else if (v<50) { // 0%
|
||||
} else if (v>150) { // 75%
|
||||
uint16_t nn = *d, nn14 = (nn&0xe79c)>>2;
|
||||
*d = nn14 + cc34;
|
||||
} else if (v<100) { // 25%
|
||||
uint16_t nn = *d, nn12 = (nn&0xf7de)>>1, nn14 = (nn12&0xf7de)>>1, nn34 = nn12+nn14;
|
||||
*d = nn34 + cc14;
|
||||
} else { // 50%
|
||||
uint16_t nn = *d, nn12 = (nn&0xf7de)>>1;
|
||||
*d = nn12 + cc12;
|
||||
}
|
||||
#else
|
||||
// pure black and white
|
||||
if (*s++ > 128)
|
||||
*d = cc;
|
||||
#endif
|
||||
d++;
|
||||
}
|
||||
}
|
||||
stbtt_FreeBitmap(bitmap, 0L);
|
||||
int advance,lsb;
|
||||
stbtt_GetCodepointHMetrics(&font, c, &advance, &lsb);
|
||||
float scale = stbtt_ScaleForPixelHeight(&font, size);
|
||||
return xx+advance*scale;
|
||||
}
|
||||
|
||||
void Fl_Android_Graphics_Driver::draw_unscaled(const char* str, int n, int x, int y)
|
||||
{
|
||||
if (str) {
|
||||
x = x+16*(-n/2);
|
||||
for (int i=0; i<n; i++)
|
||||
x = render_letter(x, y+5, str[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
// Code used to switch output to an off-screen window. See macros in
|
||||
// win32.H which save the old state in local variables.
|
||||
|
||||
typedef struct { BYTE a; BYTE b; BYTE c; BYTE d; } FL_BLENDFUNCTION;
|
||||
typedef BOOL (WINAPI* fl_alpha_blend_func)
|
||||
(HDC,int,int,int,int,HDC,int,int,int,int,FL_BLENDFUNCTION);
|
||||
static fl_alpha_blend_func fl_alpha_blend = NULL;
|
||||
static FL_BLENDFUNCTION blendfunc = { 0, 0, 255, 1};
|
||||
|
||||
/* Reference to the current device context
|
||||
For back-compatibility only. The preferred procedure to get this reference is
|
||||
Fl_Surface_Device::surface()->driver()->gc().
|
||||
*/
|
||||
HDC fl_gc = 0;
|
||||
|
||||
void Fl_GDI_Graphics_Driver::global_gc()
|
||||
{
|
||||
fl_gc = (HDC)gc();
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks if the version of Windows that we
|
||||
* curently run on supports alpha blending for bitmap transfers
|
||||
* and finds the required function if so.
|
||||
*/
|
||||
char Fl_GDI_Graphics_Driver::can_do_alpha_blending() {
|
||||
static char been_here = 0;
|
||||
static char can_do = 0;
|
||||
// do this test only once
|
||||
if (been_here) return can_do;
|
||||
been_here = 1;
|
||||
// load the library that implements alpha blending
|
||||
HMODULE hMod = LoadLibrary("MSIMG32.DLL");
|
||||
// give up if that doesn't exist (Win95?)
|
||||
if (!hMod) return 0;
|
||||
// now find the blending function inside that dll
|
||||
fl_alpha_blend = (fl_alpha_blend_func)GetProcAddress(hMod, "AlphaBlend");
|
||||
// give up if we can't find it (Win95)
|
||||
if (!fl_alpha_blend) return 0;
|
||||
// we have the call, but does our display support alpha blending?
|
||||
// get the desktop's device context
|
||||
HDC dc = GetDC(0L);
|
||||
if (!dc) return 0;
|
||||
// check the device capabilities flags. However GetDeviceCaps
|
||||
// does not return anything useful, so we have to do it manually:
|
||||
|
||||
HBITMAP bm = CreateCompatibleBitmap(dc, 1, 1);
|
||||
HDC new_gc = CreateCompatibleDC(dc);
|
||||
int save = SaveDC(new_gc);
|
||||
SelectObject(new_gc, bm);
|
||||
/*COLORREF set = */ SetPixel(new_gc, 0, 0, 0x01010101);
|
||||
BOOL alpha_ok = fl_alpha_blend(dc, 0, 0, 1, 1, new_gc, 0, 0, 1, 1, blendfunc);
|
||||
RestoreDC(new_gc, save);
|
||||
DeleteDC(new_gc);
|
||||
DeleteObject(bm);
|
||||
ReleaseDC(0L, dc);
|
||||
|
||||
if (alpha_ok) can_do = 1;
|
||||
return can_do;
|
||||
}
|
||||
|
||||
HDC fl_makeDC(HBITMAP bitmap) {
|
||||
HDC new_gc = CreateCompatibleDC((HDC)Fl_Graphics_Driver::default_driver().gc());
|
||||
SetTextAlign(new_gc, TA_BASELINE|TA_LEFT);
|
||||
SetBkMode(new_gc, TRANSPARENT);
|
||||
#if USE_COLORMAP
|
||||
if (fl_palette) SelectPalette(new_gc, fl_palette, FALSE);
|
||||
#endif
|
||||
SelectObject(new_gc, bitmap);
|
||||
return new_gc;
|
||||
}
|
||||
|
||||
void Fl_GDI_Graphics_Driver::copy_offscreen(int x, int y, int w, int h, Fl_Offscreen bitmap, int srcx, int srcy) {
|
||||
HDC new_gc = CreateCompatibleDC(gc_);
|
||||
int save = SaveDC(new_gc);
|
||||
SelectObject(new_gc, bitmap);
|
||||
BitBlt(gc_, x*scale_, y*scale_, w*scale_, h*scale_, new_gc, srcx*scale_, srcy*scale_, SRCCOPY);
|
||||
RestoreDC(new_gc, save);
|
||||
DeleteDC(new_gc);
|
||||
}
|
||||
|
||||
BOOL Fl_GDI_Graphics_Driver::alpha_blend_(int x, int y, int w, int h, HDC src_gc, int srcx, int srcy, int srcw, int srch) {
|
||||
return fl_alpha_blend(gc_, x, y, w, h, src_gc, srcx, srcy, srcw, srch, blendfunc);
|
||||
}
|
||||
|
||||
#if ! defined(FL_DOXYGEN)
|
||||
void Fl_GDI_Graphics_Driver::copy_offscreen_with_alpha(int x,int y,int w,int h,HBITMAP bitmap,int srcx,int srcy) {
|
||||
HDC new_gc = CreateCompatibleDC(gc_);
|
||||
int save = SaveDC(new_gc);
|
||||
SelectObject(new_gc, bitmap);
|
||||
BOOL alpha_ok = 0;
|
||||
// first try to alpha blend
|
||||
if ( can_do_alpha_blending() ) {
|
||||
alpha_ok = alpha_blend_(x, y, w, h, new_gc, srcx, srcy, w, h);
|
||||
}
|
||||
// if that failed (it shouldn't), still copy the bitmap over, but now alpha is 1
|
||||
if (!alpha_ok) {
|
||||
BitBlt(gc_, x, y, w, h, new_gc, srcx, srcy, SRCCOPY);
|
||||
}
|
||||
RestoreDC(new_gc, save);
|
||||
DeleteDC(new_gc);
|
||||
}
|
||||
|
||||
void Fl_GDI_Graphics_Driver::translate_all(int x, int y) {
|
||||
const int stack_height = 10;
|
||||
if (depth == -1) {
|
||||
origins = new POINT[stack_height];
|
||||
depth = 0;
|
||||
}
|
||||
if (depth >= stack_height) {
|
||||
Fl::warning("Fl_Copy/Image_Surface: translate stack overflow!");
|
||||
depth = stack_height - 1;
|
||||
}
|
||||
GetWindowOrgEx((HDC)gc(), origins+depth);
|
||||
SetWindowOrgEx((HDC)gc(), origins[depth].x - x*scale_, origins[depth].y - y*scale_, NULL);
|
||||
depth++;
|
||||
}
|
||||
|
||||
void Fl_GDI_Graphics_Driver::untranslate_all() {
|
||||
if (depth > 0) depth--;
|
||||
SetWindowOrgEx((HDC)gc(), origins[depth].x, origins[depth].y, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Fl_GDI_Graphics_Driver::add_rectangle_to_region(Fl_Region r, int X, int Y, int W, int H) {
|
||||
Fl_Region R = XRectangleRegion(X, Y, W, H);
|
||||
CombineRgn(r, r, R, RGN_OR);
|
||||
XDestroyRegion(R);
|
||||
}
|
||||
|
||||
void Fl_GDI_Graphics_Driver::transformed_vertex0(float x, float y) {
|
||||
if (!n || x != p[n-1].x || y != p[n-1].y) {
|
||||
if (n >= p_size) {
|
||||
p_size = p ? 2*p_size : 16;
|
||||
p = (POINT*)realloc((void*)p, p_size*sizeof(*p));
|
||||
}
|
||||
p[n].x = x;
|
||||
p[n].y = y;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_GDI_Graphics_Driver::fixloop() { // remove equal points from closed path
|
||||
while (n>2 && p[n-1].x == p[0].x && p[n-1].y == p[0].y) n--;
|
||||
}
|
||||
|
||||
Fl_Region Fl_GDI_Graphics_Driver::XRectangleRegion(int x, int y, int w, int h) {
|
||||
if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) return CreateRectRgn(x,y,x+w,y+h);
|
||||
// because rotation may apply, the rectangle becomes a polygon in device coords
|
||||
POINT pt[4] = { {x, y}, {x + w, y}, {x + w, y + h}, {x, y + h} };
|
||||
LPtoDP((HDC)fl_graphics_driver->gc(), pt, 4);
|
||||
return CreatePolygonRgn(pt, 4, ALTERNATE);
|
||||
}
|
||||
|
||||
void Fl_GDI_Graphics_Driver::XDestroyRegion(Fl_Region r) {
|
||||
DeleteObject(r);
|
||||
}
|
||||
|
||||
|
||||
typedef BOOL(WINAPI* flTypeImmAssociateContextEx)(HWND, HIMC, DWORD);
|
||||
extern flTypeImmAssociateContextEx flImmAssociateContextEx;
|
||||
typedef HIMC(WINAPI* flTypeImmGetContext)(HWND);
|
||||
extern flTypeImmGetContext flImmGetContext;
|
||||
typedef BOOL(WINAPI* flTypeImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM);
|
||||
extern flTypeImmSetCompositionWindow flImmSetCompositionWindow;
|
||||
typedef BOOL(WINAPI* flTypeImmReleaseContext)(HWND, HIMC);
|
||||
extern flTypeImmReleaseContext flImmReleaseContext;
|
||||
|
||||
|
||||
void Fl_GDI_Graphics_Driver::reset_spot()
|
||||
{
|
||||
}
|
||||
|
||||
void Fl_GDI_Graphics_Driver::set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win)
|
||||
{
|
||||
if (!win) return;
|
||||
Fl_Window* tw = win;
|
||||
while (tw->parent()) tw = tw->window(); // find top level window
|
||||
|
||||
if (!tw->shown())
|
||||
return;
|
||||
|
||||
HIMC himc = flImmGetContext(fl_xid(tw));
|
||||
|
||||
if (himc) {
|
||||
COMPOSITIONFORM cfs;
|
||||
cfs.dwStyle = CFS_POINT;
|
||||
cfs.ptCurrentPos.x = X;
|
||||
cfs.ptCurrentPos.y = Y - tw->labelsize();
|
||||
MapWindowPoints(fl_xid(win), fl_xid(tw), &cfs.ptCurrentPos, 1);
|
||||
flImmSetCompositionWindow(himc, &cfs);
|
||||
flImmReleaseContext(fl_xid(tw), himc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_GDI_Graphics_Driver::scale(float f) {
|
||||
if (f != scale_) {
|
||||
size_ = 0;
|
||||
scale_ = f;
|
||||
//fprintf(LOG,"set scale to %f\n",f);fflush(LOG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Rescale region r with factor f and returns the scaled region.
|
||||
Region r is returned unchanged if r is null or f is 1.
|
||||
The input region is deleted if dr is null.
|
||||
*/
|
||||
HRGN Fl_GDI_Graphics_Driver::scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr) {
|
||||
if (r && f != 1) {
|
||||
DWORD size = GetRegionData(r, 0, NULL);
|
||||
RGNDATA *pdata = (RGNDATA*)malloc(size);
|
||||
GetRegionData(r, size, pdata);
|
||||
if (!dr) DeleteObject(r);
|
||||
POINT pt = {0, 0};
|
||||
if (dr && dr->depth >= 1) { // account for translation
|
||||
GetWindowOrgEx((HDC)dr->gc(), &pt);
|
||||
pt.x *= (f - 1);
|
||||
pt.y *= (f - 1);
|
||||
}
|
||||
RECT *rects = (RECT*)&(pdata->Buffer);
|
||||
int delta = (f > 1.75 ? 1 : 0) - int(f/2);
|
||||
for (DWORD i = 0; i < pdata->rdh.nCount; i++) {
|
||||
int x = rects[i].left * f + pt.x;
|
||||
int y = rects[i].top * f + pt.y;
|
||||
RECT R2;
|
||||
R2.left = x + delta;
|
||||
R2.top = y + delta;
|
||||
R2.right = int(rects[i].right * f) + pt.x - x + R2.left;
|
||||
R2.bottom = int(rects[i].bottom * f) + pt.y - y + R2.top;
|
||||
rects[i] = R2;
|
||||
}
|
||||
r = ExtCreateRegion(NULL, size, pdata);
|
||||
free(pdata);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
Fl_Region Fl_GDI_Graphics_Driver::scale_clip(float f) {
|
||||
HRGN r = rstack[rstackptr];
|
||||
HRGN r2 = scale_region(r, f, this);
|
||||
return (r == r2 ? NULL : (rstack[rstackptr] = r2, r));
|
||||
}
|
||||
|
||||
void Fl_GDI_Graphics_Driver::set_current_() {
|
||||
restore_clip();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Android_Graphics_Driver.cxx 12655 2018-02-09 14:39:42Z AlbrechtS $".
|
||||
//
|
121
src/drivers/Android/Fl_Android_Image_Surface_Driver.cxx
Normal file
121
src/drivers/Android/Fl_Android_Image_Surface_Driver.cxx
Normal file
@ -0,0 +1,121 @@
|
||||
//
|
||||
// "$Id: Fl_Android_Image_Surface_Driver.cxx 12653 2018-02-09 13:48:22Z manolo $"
|
||||
//
|
||||
// Draw-to-image code for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2018 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
|
||||
#include "../../config_lib.h"
|
||||
|
||||
#include "Fl_Android_Graphics_Driver.H"
|
||||
//#include "../WinAPI/Fl_WinAPI_Screen_Driver.H"
|
||||
#include <FL/Fl_Image_Surface.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/platform.H>
|
||||
//#include <windows.h>
|
||||
|
||||
|
||||
class Fl_Android_Image_Surface_Driver : public Fl_Image_Surface_Driver {
|
||||
#if 0
|
||||
virtual void end_current_(Fl_Surface_Device*);
|
||||
public:
|
||||
Window pre_window;
|
||||
int _savedc;
|
||||
#endif
|
||||
public:
|
||||
Fl_Android_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off)
|
||||
: Fl_Image_Surface_Driver(w, h, high_res, off) {}
|
||||
#if 0
|
||||
~Fl_GDI_Image_Surface_Driver();
|
||||
void set_current();
|
||||
void translate(int x, int y);
|
||||
void untranslate();
|
||||
Fl_RGB_Image *image();
|
||||
POINT origin;
|
||||
#endif
|
||||
};
|
||||
|
||||
Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off)
|
||||
{
|
||||
return new Fl_Android_Image_Surface_Driver(w, h, high_res, off);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
Fl_GDI_Image_Surface_Driver::Fl_GDI_Image_Surface_Driver(int w, int h, int high_res, Fl_Offscreen off) : Fl_Image_Surface_Driver(w, h, high_res, 0) {
|
||||
float d = fl_graphics_driver->scale();
|
||||
if (!off && d != 1 && high_res) {
|
||||
w = int(w*d);
|
||||
h = int(h*d);
|
||||
}
|
||||
HDC gc = (HDC)Fl_Graphics_Driver::default_driver().gc();
|
||||
offscreen = off ? off : CreateCompatibleBitmap( (gc ? gc : fl_GetDC(0) ) , w, h);
|
||||
if (!offscreen) offscreen = CreateCompatibleBitmap(fl_GetDC(0), w, h);
|
||||
driver(new Fl_GDI_Graphics_Driver);
|
||||
if (d != 1 && high_res) ((Fl_GDI_Graphics_Driver*)driver())->scale(d);
|
||||
origin.x = origin.y = 0;
|
||||
}
|
||||
|
||||
|
||||
Fl_GDI_Image_Surface_Driver::~Fl_GDI_Image_Surface_Driver() {
|
||||
if (offscreen) DeleteObject(offscreen);
|
||||
delete driver();
|
||||
}
|
||||
|
||||
|
||||
void Fl_GDI_Image_Surface_Driver::set_current() {
|
||||
HDC gc = fl_makeDC(offscreen);
|
||||
driver()->gc(gc);
|
||||
SetWindowOrgEx(gc, origin.x, origin.y, NULL);
|
||||
Fl_Surface_Device::set_current();
|
||||
pre_window = fl_window;
|
||||
_savedc = SaveDC(gc);
|
||||
fl_window=(HWND)offscreen;
|
||||
}
|
||||
|
||||
|
||||
void Fl_GDI_Image_Surface_Driver::translate(int x, int y) {
|
||||
((Fl_GDI_Graphics_Driver*)driver())->translate_all(x, y);
|
||||
}
|
||||
|
||||
|
||||
void Fl_GDI_Image_Surface_Driver::untranslate() {
|
||||
((Fl_GDI_Graphics_Driver*)driver())->untranslate_all();
|
||||
}
|
||||
|
||||
|
||||
Fl_RGB_Image* Fl_GDI_Image_Surface_Driver::image()
|
||||
{
|
||||
Fl_RGB_Image *image = Fl::screen_driver()->read_win_rectangle( 0, 0, width, height);
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
void Fl_GDI_Image_Surface_Driver::end_current_(Fl_Surface_Device*)
|
||||
{
|
||||
HDC gc = (HDC)driver()->gc();
|
||||
GetWindowOrgEx(gc, &origin);
|
||||
RestoreDC(gc, _savedc);
|
||||
DeleteDC(gc);
|
||||
fl_window = pre_window;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Android_Image_Surface_Driver.cxx 12653 2018-02-09 13:48:22Z manolo $".
|
||||
//
|
477
src/drivers/Android/Fl_Android_Screen_Driver.H
Normal file
477
src/drivers/Android/Fl_Android_Screen_Driver.H
Normal file
@ -0,0 +1,477 @@
|
||||
//
|
||||
// "$Id: Fl_Android_Screen_Driver.H 12655 2018-02-09 14:39:42Z AlbrechtS $"
|
||||
//
|
||||
// Definition of Windows screen interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2018 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_WinAPI_Screen_Driver.H
|
||||
\brief Definition of Windows screen interface.
|
||||
*/
|
||||
|
||||
#ifndef FL_WINAPI_SCREEN_DRIVER_H
|
||||
#define FL_WINAPI_SCREEN_DRIVER_H
|
||||
|
||||
#include <FL/Fl_Screen_Driver.H>
|
||||
//#include <windows.h>
|
||||
|
||||
class Fl_Window;
|
||||
|
||||
|
||||
class FL_EXPORT Fl_Android_Screen_Driver : public Fl_Screen_Driver
|
||||
{
|
||||
|
||||
#if 0
|
||||
|
||||
protected:
|
||||
RECT screens[MAX_SCREENS];
|
||||
RECT work_area[MAX_SCREENS];
|
||||
float dpi[MAX_SCREENS][2];
|
||||
float scale_of_screen[MAX_SCREENS];
|
||||
|
||||
static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM);
|
||||
BOOL screen_cb(HMONITOR mon, HDC, LPRECT r);
|
||||
int get_mouse_unscaled(int &mx, int &my);
|
||||
#ifdef FLTK_HIDPI_SUPPORT
|
||||
void init_screen_scale_factors();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
Fl_Android_Screen_Driver() : Fl_Screen_Driver() { }
|
||||
|
||||
#if 0
|
||||
Fl_WinAPI_Screen_Driver() : Fl_Screen_Driver() {
|
||||
for (int i = 0; i < MAX_SCREENS; i++) scale_of_screen[i] = 1;
|
||||
}
|
||||
// --- display management
|
||||
virtual int visual(int flags);
|
||||
// --- screen configuration
|
||||
virtual void init();
|
||||
virtual int x();
|
||||
virtual int y();
|
||||
virtual int w();
|
||||
virtual int h();
|
||||
virtual void screen_xywh(int &X, int &Y, int &W, int &H, int n);
|
||||
virtual void screen_dpi(float &h, float &v, int n=0);
|
||||
int screen_num_unscaled(int x, int y);
|
||||
virtual void screen_work_area(int &X, int &Y, int &W, int &H, int n);
|
||||
// --- audible output
|
||||
virtual void beep(int type);
|
||||
// --- global events
|
||||
virtual void flush();
|
||||
virtual double wait(double time_to_wait);
|
||||
virtual int ready();
|
||||
virtual void grab(Fl_Window* win);
|
||||
// --- global colors
|
||||
virtual void get_system_colors();
|
||||
virtual const char *get_system_scheme();
|
||||
// --- global timers
|
||||
virtual void add_timeout(double time, Fl_Timeout_Handler cb, void *argp);
|
||||
virtual void repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp);
|
||||
virtual int has_timeout(Fl_Timeout_Handler cb, void *argp);
|
||||
virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp);
|
||||
virtual int dnd(int unused);
|
||||
virtual int compose(int &del);
|
||||
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h);
|
||||
Fl_RGB_Image *read_win_rectangle_unscaled(int X, int Y, int w, int h);
|
||||
virtual int get_mouse(int &x, int &y);
|
||||
virtual void enable_im();
|
||||
virtual void disable_im();
|
||||
virtual void open_display_platform();
|
||||
virtual void offscreen_size(Fl_Offscreen off, int &width, int &height);
|
||||
#if defined(FLTK_HIDPI_SUPPORT)
|
||||
virtual APP_SCALING_CAPABILITY rescalable() {
|
||||
return PER_SCREEN_APP_SCALING;
|
||||
}
|
||||
virtual float scale(int n) {
|
||||
return scale_of_screen[n];
|
||||
}
|
||||
virtual void scale(int n, float f) {
|
||||
scale_of_screen[n] = f;
|
||||
}
|
||||
#else
|
||||
float DWM_scaling_factor();
|
||||
#endif
|
||||
virtual float desktop_scale_factor();
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_NATIVE_APP_GLUE_H
|
||||
#define _ANDROID_NATIVE_APP_GLUE_H
|
||||
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include <android/configuration.h>
|
||||
#include <android/looper.h>
|
||||
#include <android/native_activity.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The native activity interface provided by <android/native_activity.h>
|
||||
* is based on a set of application-provided callbacks that will be called
|
||||
* by the Activity's main thread when certain events occur.
|
||||
*
|
||||
* This means that each one of this callbacks _should_ _not_ block, or they
|
||||
* risk having the system force-close the application. This programming
|
||||
* model is direct, lightweight, but constraining.
|
||||
*
|
||||
* The 'android_native_app_glue' static library is used to provide a different
|
||||
* execution model where the application can implement its own main event
|
||||
* loop in a different thread instead. Here's how it works:
|
||||
*
|
||||
* 1/ The application must provide a function named "android_main()" that
|
||||
* will be called when the activity is created, in a new thread that is
|
||||
* distinct from the activity's main thread.
|
||||
*
|
||||
* 2/ android_main() receives a pointer to a valid "android_app" structure
|
||||
* that contains references to other important objects, e.g. the
|
||||
* ANativeActivity obejct instance the application is running in.
|
||||
*
|
||||
* 3/ the "android_app" object holds an ALooper instance that already
|
||||
* listens to two important things:
|
||||
*
|
||||
* - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
|
||||
* declarations below.
|
||||
*
|
||||
* - input events coming from the AInputQueue attached to the activity.
|
||||
*
|
||||
* Each of these correspond to an ALooper identifier returned by
|
||||
* ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
|
||||
* respectively.
|
||||
*
|
||||
* Your application can use the same ALooper to listen to additional
|
||||
* file-descriptors. They can either be callback based, or with return
|
||||
* identifiers starting with LOOPER_ID_USER.
|
||||
*
|
||||
* 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
|
||||
* the returned data will point to an android_poll_source structure. You
|
||||
* can call the process() function on it, and fill in android_app->onAppCmd
|
||||
* and android_app->onInputEvent to be called for your own processing
|
||||
* of the event.
|
||||
*
|
||||
* Alternatively, you can call the low-level functions to read and process
|
||||
* the data directly... look at the process_cmd() and process_input()
|
||||
* implementations in the glue to see how to do this.
|
||||
*
|
||||
* See the sample named "native-activity" that comes with the NDK with a
|
||||
* full usage example. Also look at the JavaDoc of NativeActivity.
|
||||
*/
|
||||
|
||||
struct android_app;
|
||||
|
||||
/**
|
||||
* Data associated with an ALooper fd that will be returned as the "outData"
|
||||
* when that source has data ready.
|
||||
*/
|
||||
struct android_poll_source {
|
||||
// The identifier of this source. May be LOOPER_ID_MAIN or
|
||||
// LOOPER_ID_INPUT.
|
||||
int32_t id;
|
||||
|
||||
// The android_app this ident is associated with.
|
||||
struct android_app* app;
|
||||
|
||||
// Function to call to perform the standard processing of data from
|
||||
// this source.
|
||||
void (*process)(struct android_app* app, struct android_poll_source* source);
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the interface for the standard glue code of a threaded
|
||||
* application. In this model, the application's code is running
|
||||
* in its own thread separate from the main thread of the process.
|
||||
* It is not required that this thread be associated with the Java
|
||||
* VM, although it will need to be in order to make JNI calls any
|
||||
* Java objects.
|
||||
*/
|
||||
struct android_app {
|
||||
// The application can place a pointer to its own state object
|
||||
// here if it likes.
|
||||
void* userData;
|
||||
|
||||
// Fill this in with the function to process main app commands (APP_CMD_*)
|
||||
void (*onAppCmd)(struct android_app* app, int32_t cmd);
|
||||
|
||||
// Fill this in with the function to process input events. At this point
|
||||
// the event has already been pre-dispatched, and it will be finished upon
|
||||
// return. Return 1 if you have handled the event, 0 for any default
|
||||
// dispatching.
|
||||
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
|
||||
|
||||
// The ANativeActivity object instance that this app is running in.
|
||||
ANativeActivity* activity;
|
||||
|
||||
// The current configuration the app is running in.
|
||||
AConfiguration* config;
|
||||
|
||||
// This is the last instance's saved state, as provided at creation time.
|
||||
// It is NULL if there was no state. You can use this as you need; the
|
||||
// memory will remain around until you call android_app_exec_cmd() for
|
||||
// APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
|
||||
// These variables should only be changed when processing a APP_CMD_SAVE_STATE,
|
||||
// at which point they will be initialized to NULL and you can malloc your
|
||||
// state and place the information here. In that case the memory will be
|
||||
// freed for you later.
|
||||
void* savedState;
|
||||
size_t savedStateSize;
|
||||
|
||||
// The ALooper associated with the app's thread.
|
||||
ALooper* looper;
|
||||
|
||||
// When non-NULL, this is the input queue from which the app will
|
||||
// receive user input events.
|
||||
AInputQueue* inputQueue;
|
||||
|
||||
// When non-NULL, this is the window surface that the app can draw in.
|
||||
ANativeWindow* window;
|
||||
|
||||
// Current content rectangle of the window; this is the area where the
|
||||
// window's content should be placed to be seen by the user.
|
||||
ARect contentRect;
|
||||
|
||||
// Current state of the app's activity. May be either APP_CMD_START,
|
||||
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
|
||||
int activityState;
|
||||
|
||||
// This is non-zero when the application's NativeActivity is being
|
||||
// destroyed and waiting for the app thread to complete.
|
||||
int destroyRequested;
|
||||
|
||||
// -------------------------------------------------
|
||||
// Below are "private" implementation of the glue code.
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
int msgread;
|
||||
int msgwrite;
|
||||
|
||||
pthread_t thread;
|
||||
|
||||
struct android_poll_source cmdPollSource;
|
||||
struct android_poll_source inputPollSource;
|
||||
|
||||
int running;
|
||||
int stateSaved;
|
||||
int destroyed;
|
||||
int redrawNeeded;
|
||||
AInputQueue* pendingInputQueue;
|
||||
ANativeWindow* pendingWindow;
|
||||
ARect pendingContentRect;
|
||||
};
|
||||
|
||||
enum {
|
||||
/**
|
||||
* Looper data ID of commands coming from the app's main thread, which
|
||||
* is returned as an identifier from ALooper_pollOnce(). The data for this
|
||||
* identifier is a pointer to an android_poll_source structure.
|
||||
* These can be retrieved and processed with android_app_read_cmd()
|
||||
* and android_app_exec_cmd().
|
||||
*/
|
||||
LOOPER_ID_MAIN = 1,
|
||||
|
||||
/**
|
||||
* Looper data ID of events coming from the AInputQueue of the
|
||||
* application's window, which is returned as an identifier from
|
||||
* ALooper_pollOnce(). The data for this identifier is a pointer to an
|
||||
* android_poll_source structure. These can be read via the inputQueue
|
||||
* object of android_app.
|
||||
*/
|
||||
LOOPER_ID_INPUT = 2,
|
||||
|
||||
/**
|
||||
* Start of user-defined ALooper identifiers.
|
||||
*/
|
||||
LOOPER_ID_USER = 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
/**
|
||||
* Command from main thread: the AInputQueue has changed. Upon processing
|
||||
* this command, android_app->inputQueue will be updated to the new queue
|
||||
* (or NULL).
|
||||
*/
|
||||
APP_CMD_INPUT_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: a new ANativeWindow is ready for use. Upon
|
||||
* receiving this command, android_app->window will contain the new window
|
||||
* surface.
|
||||
*/
|
||||
APP_CMD_INIT_WINDOW,
|
||||
|
||||
/**
|
||||
* Command from main thread: the existing ANativeWindow needs to be
|
||||
* terminated. Upon receiving this command, android_app->window still
|
||||
* contains the existing window; after calling android_app_exec_cmd
|
||||
* it will be set to NULL.
|
||||
*/
|
||||
APP_CMD_TERM_WINDOW,
|
||||
|
||||
/**
|
||||
* Command from main thread: the current ANativeWindow has been resized.
|
||||
* Please redraw with its new size.
|
||||
*/
|
||||
APP_CMD_WINDOW_RESIZED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the system needs that the current ANativeWindow
|
||||
* be redrawn. You should redraw the window before handing this to
|
||||
* android_app_exec_cmd() in order to avoid transient drawing glitches.
|
||||
*/
|
||||
APP_CMD_WINDOW_REDRAW_NEEDED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the content area of the window has changed,
|
||||
* such as from the soft input window being shown or hidden. You can
|
||||
* find the new content rect in android_app::contentRect.
|
||||
*/
|
||||
APP_CMD_CONTENT_RECT_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity window has gained
|
||||
* input focus.
|
||||
*/
|
||||
APP_CMD_GAINED_FOCUS,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity window has lost
|
||||
* input focus.
|
||||
*/
|
||||
APP_CMD_LOST_FOCUS,
|
||||
|
||||
/**
|
||||
* Command from main thread: the current device configuration has changed.
|
||||
*/
|
||||
APP_CMD_CONFIG_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the system is running low on memory.
|
||||
* Try to reduce your memory use.
|
||||
*/
|
||||
APP_CMD_LOW_MEMORY,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been started.
|
||||
*/
|
||||
APP_CMD_START,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been resumed.
|
||||
*/
|
||||
APP_CMD_RESUME,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app should generate a new saved state
|
||||
* for itself, to restore from later if needed. If you have saved state,
|
||||
* allocate it with malloc and place it in android_app.savedState with
|
||||
* the size in android_app.savedStateSize. The will be freed for you
|
||||
* later.
|
||||
*/
|
||||
APP_CMD_SAVE_STATE,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been paused.
|
||||
*/
|
||||
APP_CMD_PAUSE,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been stopped.
|
||||
*/
|
||||
APP_CMD_STOP,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity is being destroyed,
|
||||
* and waiting for the app thread to clean up and exit before proceeding.
|
||||
*/
|
||||
APP_CMD_DESTROY,
|
||||
};
|
||||
|
||||
/**
|
||||
* Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
|
||||
* app command message.
|
||||
*/
|
||||
int8_t android_app_read_cmd(struct android_app* android_app);
|
||||
|
||||
/**
|
||||
* Call with the command returned by android_app_read_cmd() to do the
|
||||
* initial pre-processing of the given command. You can perform your own
|
||||
* actions for the command after calling this function.
|
||||
*/
|
||||
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
|
||||
|
||||
/**
|
||||
* Call with the command returned by android_app_read_cmd() to do the
|
||||
* final post-processing of the given command. You must have done your own
|
||||
* actions for the command before calling this function.
|
||||
*/
|
||||
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
|
||||
|
||||
/**
|
||||
* Dummy function that used to be used to prevent the linker from stripping app
|
||||
* glue code. No longer necessary, since __attribute__((visibility("default")))
|
||||
* does this for us.
|
||||
*/
|
||||
__attribute__((
|
||||
deprecated("Calls to app_dummy are no longer necessary. See "
|
||||
"https://github.com/android-ndk/ndk/issues/381."))) void
|
||||
app_dummy();
|
||||
|
||||
/**
|
||||
* This is the function that application code must implement, representing
|
||||
* the main entry to the app.
|
||||
*/
|
||||
extern void android_main(struct android_app* app);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ANDROID_NATIVE_APP_GLUE_H */
|
||||
|
||||
|
||||
#endif // FL_WINAPI_SCREEN_DRIVER_H
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Android_Screen_Driver.H 12655 2018-02-09 14:39:42Z AlbrechtS $".
|
||||
//
|
1106
src/drivers/Android/Fl_Android_Screen_Driver.cxx
Normal file
1106
src/drivers/Android/Fl_Android_Screen_Driver.cxx
Normal file
File diff suppressed because it is too large
Load Diff
129
src/drivers/Android/Fl_Android_System_Driver.H
Normal file
129
src/drivers/Android/Fl_Android_System_Driver.H
Normal file
@ -0,0 +1,129 @@
|
||||
//
|
||||
// "$Id: Fl_Android_System_Driver.H 12655 2018-02-09 14:39:42Z AlbrechtS $"
|
||||
//
|
||||
// Definition of Windows system driver for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2018 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_WinAPI_System_Driver.H
|
||||
\brief Definition of Windows system driver.
|
||||
*/
|
||||
|
||||
#ifndef FL_WINAPI_SYSTEM_DRIVER_H
|
||||
#define FL_WINAPI_SYSTEM_DRIVER_H
|
||||
|
||||
#include <FL/Fl_System_Driver.H>
|
||||
#include <stdarg.h>
|
||||
|
||||
/*
|
||||
Move everything here that manages the system interface.
|
||||
|
||||
There is exactly one system driver.
|
||||
|
||||
- filename and pathname management
|
||||
- directory and file access
|
||||
- system time and system timer
|
||||
- multithreading
|
||||
*/
|
||||
|
||||
class Fl_Android_System_Driver : public Fl_System_Driver
|
||||
{
|
||||
#if 0
|
||||
public:
|
||||
static unsigned win_pixmap_bg_color; // the RGB() of the pixmap background color
|
||||
virtual void warning(const char *format, va_list args);
|
||||
virtual void error(const char *format, va_list args);
|
||||
virtual void fatal(const char *format, va_list args);
|
||||
virtual char *utf2mbcs(const char *s);
|
||||
virtual char *getenv(const char *var);
|
||||
virtual int putenv(char *var) {return ::putenv(var);} // *FIXME* needs string conversion
|
||||
virtual int open(const char *fnam, int oflags, int pmode);
|
||||
virtual int open_ext(const char *fnam, int binary, int oflags, int pmode);
|
||||
virtual FILE *fopen(const char *fnam, const char *mode);
|
||||
virtual int system(const char *cmd);
|
||||
virtual int execvp(const char *file, char *const *argv);
|
||||
virtual int chmod(const char *fnam, int mode);
|
||||
virtual int access(const char *fnam, int mode);
|
||||
virtual int stat(const char *fnam, struct stat *b);
|
||||
virtual char *getcwd(char *b, int l);
|
||||
virtual int chdir(const char *path);
|
||||
virtual int unlink(const char *fnam);
|
||||
virtual int mkdir(const char *fnam, int mode);
|
||||
virtual int rmdir(const char *fnam);
|
||||
virtual int rename(const char *fnam, const char *newnam);
|
||||
virtual unsigned utf8towc(const char *src, unsigned srclen, wchar_t* dst, unsigned dstlen);
|
||||
virtual unsigned utf8fromwc(char *dst, unsigned dstlen, const wchar_t* src, unsigned srclen);
|
||||
virtual int utf8locale();
|
||||
virtual unsigned utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen);
|
||||
virtual unsigned utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen);
|
||||
virtual int clocale_printf(FILE *output, const char *format, va_list args);
|
||||
// these 2 are in Fl_get_key_win32.cxx
|
||||
virtual int event_key(int k);
|
||||
virtual int get_key(int k);
|
||||
virtual int filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) );
|
||||
virtual int filename_expand(char *to,int tolen, const char *from);
|
||||
virtual int filename_relative(char *to, int tolen, const char *from, const char *base);
|
||||
virtual int filename_absolute(char *to, int tolen, const char *from);
|
||||
virtual int filename_isdir(const char *n);
|
||||
virtual int filename_isdir_quick(const char *n);
|
||||
virtual const char *filename_ext(const char *buf);
|
||||
virtual int open_uri(const char *uri, char *msg, int msglen);
|
||||
virtual int use_recent_tooltip_fix() {return 1;}
|
||||
virtual int file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon);
|
||||
virtual int file_browser_load_directory(const char *directory, char *filename, size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort);
|
||||
virtual void newUUID(char *uuidBuffer);
|
||||
virtual char *preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
|
||||
const char *application);
|
||||
virtual void *dlopen(const char *filename);
|
||||
virtual void png_extra_rgba_processing(unsigned char *array, int w, int h);
|
||||
virtual const char *next_dir_sep(const char *start);
|
||||
// these 3 are implemented in Fl_lock.cxx
|
||||
virtual void awake(void*);
|
||||
virtual int lock();
|
||||
virtual void unlock();
|
||||
// this one is implemented in Fl_win32.cxx
|
||||
virtual void* thread_message();
|
||||
virtual int file_type(const char *filename);
|
||||
virtual int pixmap_extra_transparent_processing() {return 1;}
|
||||
// this one is implemented in fl_draw_pixmap.cxx
|
||||
virtual void make_unused_color(unsigned char &r, unsigned char &g, unsigned char &b);
|
||||
virtual const char *home_directory_name();
|
||||
virtual const char *filesystems_label() { return "My Computer"; }
|
||||
virtual int backslash_as_slash() {return 1;}
|
||||
virtual int colon_is_drive() {return 1;}
|
||||
virtual int case_insensitive_filenames() {return 1;}
|
||||
// this one is implemented in Fl_win32.cxx
|
||||
virtual const char *filename_name(const char *buf);
|
||||
// this one is implemented in Fl_win32.cxx
|
||||
virtual void copy(const char *stuff, int len, int clipboard, const char *type);
|
||||
// this one is implemented in Fl_win32.cxx
|
||||
virtual void paste(Fl_Widget &receiver, int clipboard, const char *type);
|
||||
// this one is implemented in Fl_win32.cxx
|
||||
virtual int clipboard_contains(const char *type);
|
||||
// this one is implemented in Fl_win32.cxx
|
||||
virtual void clipboard_notify_change();
|
||||
virtual void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0);
|
||||
virtual void add_fd(int fd, Fl_FD_Handler cb, void* = 0);
|
||||
virtual void remove_fd(int, int when);
|
||||
virtual void remove_fd(int);
|
||||
virtual void gettime(time_t *sec, int *usec);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // FL_WINAPI_SYSTEM_DRIVER_H
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Android_System_Driver.H 12655 2018-02-09 14:39:42Z AlbrechtS $".
|
||||
//
|
947
src/drivers/Android/Fl_Android_System_Driver.cxx
Normal file
947
src/drivers/Android/Fl_Android_System_Driver.cxx
Normal file
@ -0,0 +1,947 @@
|
||||
//
|
||||
// "$Id: Fl_Android_System_Driver.cxx 12655 2018-02-09 14:39:42Z AlbrechtS $"
|
||||
//
|
||||
// Definition of Apple Darwin system driver.
|
||||
//
|
||||
// Copyright 1998-2018 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
#include "../../config_lib.h"
|
||||
#include "Fl_Android_System_Driver.H"
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_utf8.h>
|
||||
#include <FL/filename.H>
|
||||
#include <FL/Fl_File_Browser.H>
|
||||
#include <FL/Fl_File_Icon.H>
|
||||
#include "../../flstring.h"
|
||||
|
||||
#if 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windows.h>
|
||||
#include <rpc.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <shellapi.h>
|
||||
#include <wchar.h>
|
||||
#include <process.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
// function pointer for the UuidCreate Function
|
||||
// RPC_STATUS RPC_ENTRY UuidCreate(UUID __RPC_FAR *Uuid);
|
||||
typedef RPC_STATUS (WINAPI *uuid_func)(UUID __RPC_FAR *Uuid);
|
||||
|
||||
// Apparently Borland C++ defines DIRECTORY in <direct.h>, which
|
||||
// interferes with the Fl_File_Icon enumeration of the same name.
|
||||
# ifdef DIRECTORY
|
||||
# undef DIRECTORY
|
||||
# endif // DIRECTORY
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
# include <mntent.h>
|
||||
#endif
|
||||
|
||||
inline int isdirsep(char c) { return c == '/' || c == '\\'; }
|
||||
|
||||
static wchar_t *mbwbuf = NULL;
|
||||
static wchar_t *wbuf = NULL;
|
||||
static wchar_t *wbuf1 = NULL;
|
||||
|
||||
extern "C" {
|
||||
int fl_scandir(const char *dirname, struct dirent ***namelist,
|
||||
int (*select)(struct dirent *),
|
||||
int (*compar)(struct dirent **, struct dirent **));
|
||||
}
|
||||
|
||||
/*
|
||||
Convert a UTF-8 string to Windows wide character encoding (UTF-16).
|
||||
|
||||
This helper function is used throughout this file to convert UTF-8
|
||||
strings to Windows specific UTF-16 encoding for filenames, paths, or
|
||||
other strings to be used by system functions.
|
||||
|
||||
The input string can be a null-terminated string or its length can be
|
||||
provided by the optional argument 'lg'. If 'lg' is omitted or less than 0
|
||||
(default = -1) the string length is determined with strlen(), otherwise
|
||||
'lg' takes precedence. Zero (0) is a valid string length (an empty string).
|
||||
|
||||
The argument 'wbuf' must have been initialized with NULL or a previous
|
||||
call to malloc() or realloc().
|
||||
|
||||
If the converted string doesn't fit into the allocated size of 'wbuf' or if
|
||||
'wbuf' is NULL a new buffer is allocated with realloc(). Hence the pointer
|
||||
'wbuf' can be shared among multiple calls to this function if it has been
|
||||
initialized with NULL (or malloc or realloc) before the first call.
|
||||
Ideally every call to this function has its own static pointer though.
|
||||
|
||||
The return value is either the old value of 'wbuf' (if the string fits)
|
||||
or a pointer at the (re)allocated buffer.
|
||||
|
||||
Pseudo doxygen docs (static function intentionally not documented):
|
||||
|
||||
param[in] utf8 input string (UTF-8)
|
||||
param[in,out] wbuf in: pointer to output string buffer
|
||||
out: new string (the pointer may be changed)
|
||||
param[in] lg optional: input string length (default = -1)
|
||||
|
||||
returns pointer to string buffer
|
||||
*/
|
||||
static wchar_t *utf8_to_wchar(const char *utf8, wchar_t *&wbuf, int lg = -1) {
|
||||
unsigned len = (lg >= 0) ? (unsigned)lg : (unsigned)strlen(utf8);
|
||||
unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 1; // Query length
|
||||
wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * wn);
|
||||
wn = fl_utf8toUtf16(utf8, len, (unsigned short *)wbuf, wn); // Convert string
|
||||
wbuf[wn] = 0;
|
||||
return wbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
Convert a Windows wide character (UTF-16) string to UTF-8 encoding.
|
||||
|
||||
This helper function is used throughout this file to convert Windows
|
||||
wide character strings as returned by system functions to UTF-8
|
||||
encoding for internal usage.
|
||||
|
||||
The argument 'utf8' must have been initialized with NULL or a previous
|
||||
call to malloc() or realloc().
|
||||
|
||||
If the converted string doesn't fit into the allocated size of 'utf8' or if
|
||||
'utf8' is NULL a new buffer is allocated with realloc(). Hence the pointer
|
||||
'utf8' can be shared among multiple calls to this function if it has been
|
||||
initialized with NULL (or malloc or realloc) before the first call.
|
||||
Ideally every call to this function has its own static pointer though.
|
||||
|
||||
The return value is either the old value of 'utf8' (if the string fits)
|
||||
or a pointer at the (re)allocated buffer.
|
||||
|
||||
Pseudo doxygen docs (static function intentionally not documented):
|
||||
|
||||
param[in] wstr input string (wide character, UTF-16)
|
||||
param[in,out] utf8 in: pointer to output string buffer
|
||||
out: new string (pointer may be changed)
|
||||
|
||||
returns pointer to string buffer
|
||||
*/
|
||||
static char *wchar_to_utf8(const wchar_t *wstr, char *&utf8) {
|
||||
unsigned len = (unsigned)wcslen(wstr);
|
||||
unsigned wn = fl_utf8fromwc(NULL, 0, wstr, len) + 1; // query length
|
||||
utf8 = (char *)realloc(utf8, wn);
|
||||
wn = fl_utf8fromwc(utf8, wn, wstr, len); // convert string
|
||||
utf8[wn] = 0;
|
||||
return utf8;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Creates a driver that manages all system related calls.
|
||||
|
||||
This function must be implemented once for every platform.
|
||||
*/
|
||||
Fl_System_Driver *Fl_System_Driver::newSystemDriver()
|
||||
{
|
||||
return new Fl_Android_System_Driver();
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
void Fl_WinAPI_System_Driver::warning(const char *format, va_list args) {
|
||||
// Show nothing for warnings under Windows...
|
||||
}
|
||||
|
||||
void Fl_WinAPI_System_Driver::error(const char *format, va_list args) {
|
||||
|
||||
char buf[1024];
|
||||
vsnprintf(buf, 1024, format, args);
|
||||
MessageBox(0, buf, "Error", MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
|
||||
}
|
||||
|
||||
void Fl_WinAPI_System_Driver::fatal(const char *format, va_list args) {
|
||||
char buf[1024];
|
||||
vsnprintf(buf, 1024, format, args);
|
||||
MessageBox(0, buf, "Error", MB_ICONSTOP | MB_SYSTEMMODAL);
|
||||
::exit(1);
|
||||
}
|
||||
|
||||
char *Fl_WinAPI_System_Driver::utf2mbcs(const char *utf8) {
|
||||
static char *buf = NULL;
|
||||
if (!utf8) return NULL;
|
||||
|
||||
unsigned len = (unsigned)strlen(utf8);
|
||||
|
||||
unsigned wn = fl_utf8toUtf16(utf8, len, NULL, 0) + 7; // Query length
|
||||
mbwbuf = (wchar_t *)realloc(mbwbuf, sizeof(wchar_t) * wn);
|
||||
len = fl_utf8toUtf16(utf8, len, (unsigned short *)mbwbuf, wn); // Convert string
|
||||
mbwbuf[len] = 0;
|
||||
|
||||
buf = (char*)realloc(buf, len * 6 + 1);
|
||||
len = (unsigned)wcstombs(buf, mbwbuf, len * 6);
|
||||
buf[len] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *Fl_WinAPI_System_Driver::getenv(const char *var) {
|
||||
static char *buf = NULL;
|
||||
wchar_t *ret = _wgetenv(utf8_to_wchar(var, wbuf));
|
||||
if (!ret) return NULL;
|
||||
return wchar_to_utf8(ret, buf);
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::open(const char *fnam, int oflags, int pmode) {
|
||||
utf8_to_wchar(fnam, wbuf);
|
||||
if (pmode == -1) return _wopen(wbuf, oflags);
|
||||
else return _wopen(wbuf, oflags, pmode);
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::open_ext(const char *fnam, int binary, int oflags, int pmode) {
|
||||
if (oflags == 0) oflags = _O_RDONLY;
|
||||
oflags |= (binary ? _O_BINARY : _O_TEXT);
|
||||
return open(fnam, oflags, pmode);
|
||||
}
|
||||
|
||||
FILE *Fl_WinAPI_System_Driver::fopen(const char *fnam, const char *mode) {
|
||||
utf8_to_wchar(fnam, wbuf);
|
||||
utf8_to_wchar(mode, wbuf1);
|
||||
return _wfopen(wbuf, wbuf1);
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::system(const char *cmd) {
|
||||
# ifdef __MINGW32__
|
||||
return ::system(fl_utf2mbcs(cmd));
|
||||
# else
|
||||
return _wsystem(utf8_to_wchar(cmd, wbuf));
|
||||
# endif
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::execvp(const char *file, char *const *argv) {
|
||||
# ifdef __MINGW32__
|
||||
return _execvp(fl_utf2mbcs(file), argv);
|
||||
# else
|
||||
wchar_t **ar;
|
||||
utf8_to_wchar(file, wbuf);
|
||||
|
||||
int i = 0, n = 0;
|
||||
while (argv[i]) {i++; n++;}
|
||||
ar = (wchar_t **)malloc(sizeof(wchar_t *) * (n + 1));
|
||||
i = 0;
|
||||
while (i <= n) {
|
||||
unsigned wn;
|
||||
unsigned len = (unsigned)strlen(argv[i]);
|
||||
wn = fl_utf8toUtf16(argv[i], len, NULL, 0) + 1; // Query length
|
||||
ar[i] = (wchar_t *)malloc(sizeof(wchar_t) * wn);
|
||||
wn = fl_utf8toUtf16(argv[i], len, (unsigned short *)ar[i], wn); // Convert string
|
||||
ar[i][wn] = 0;
|
||||
i++;
|
||||
}
|
||||
ar[n] = NULL;
|
||||
_wexecvp(wbuf, ar); // STR #3040
|
||||
i = 0;
|
||||
while (i < n) {
|
||||
free(ar[i]);
|
||||
i++;
|
||||
}
|
||||
free(ar);
|
||||
return -1; // STR #3040
|
||||
#endif
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::chmod(const char *fnam, int mode) {
|
||||
return _wchmod(utf8_to_wchar(fnam, wbuf), mode);
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::access(const char *fnam, int mode) {
|
||||
return _waccess(utf8_to_wchar(fnam, wbuf), mode);
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::stat(const char *fnam, struct stat *b) {
|
||||
|
||||
// remove trailing '/' or '\'
|
||||
unsigned len = (unsigned)strlen(fnam);
|
||||
if (len > 0 && (fnam[len-1] == '/' || fnam[len-1] == '\\'))
|
||||
len--;
|
||||
// convert filename and execute _wstat()
|
||||
return _wstat(utf8_to_wchar(fnam, wbuf, len), (struct _stat *)b);
|
||||
}
|
||||
|
||||
char *Fl_WinAPI_System_Driver::getcwd(char *buf, int len) {
|
||||
|
||||
static wchar_t *wbuf = NULL;
|
||||
wbuf = (wchar_t *)realloc(wbuf, sizeof(wchar_t) * (len + 1));
|
||||
wchar_t *ret = _wgetcwd(wbuf, len);
|
||||
if (!ret) return NULL;
|
||||
|
||||
unsigned dstlen = (unsigned)len;
|
||||
len = (int)wcslen(wbuf);
|
||||
dstlen = fl_utf8fromwc(buf, dstlen, wbuf, (unsigned)len);
|
||||
buf[dstlen] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::chdir(const char *path) {
|
||||
return _wchdir(utf8_to_wchar(path, wbuf));
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::unlink(const char *fnam) {
|
||||
return _wunlink(utf8_to_wchar(fnam, wbuf));
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::mkdir(const char *fnam, int mode) {
|
||||
return _wmkdir(utf8_to_wchar(fnam, wbuf));
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::rmdir(const char *fnam) {
|
||||
return _wrmdir(utf8_to_wchar(fnam, wbuf));
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::rename(const char *fnam, const char *newnam) {
|
||||
utf8_to_wchar(fnam, wbuf);
|
||||
utf8_to_wchar(newnam, wbuf1);
|
||||
return _wrename(wbuf, wbuf1);
|
||||
}
|
||||
|
||||
// Two Windows-specific functions fl_utf8_to_locale() and fl_locale_to_utf8()
|
||||
// from file fl_utf8.cxx are put here for API compatibility
|
||||
|
||||
static char *buf = NULL;
|
||||
static int buf_len = 0;
|
||||
static unsigned short *wbufa = NULL;
|
||||
unsigned int fl_codepage = 0;
|
||||
|
||||
|
||||
// FIXME: This should *maybe* return 'const char *' instead of 'char *'
|
||||
char *fl_utf8_to_locale(const char *s, int len, UINT codepage)
|
||||
{
|
||||
if (!s) return (char *)"";
|
||||
int l = 0;
|
||||
unsigned wn = fl_utf8toUtf16(s, len, NULL, 0); // Query length
|
||||
wn = wn * 2 + 1;
|
||||
if (wn >= (unsigned)buf_len) {
|
||||
buf_len = wn;
|
||||
buf = (char*) realloc(buf, buf_len);
|
||||
wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
|
||||
}
|
||||
if (codepage < 1) codepage = fl_codepage;
|
||||
l = fl_utf8toUtf16(s, len, wbufa, wn); // Convert string
|
||||
wbufa[l] = 0;
|
||||
buf[l] = 0;
|
||||
l = WideCharToMultiByte(codepage, 0, (WCHAR*)wbufa, l, buf, buf_len, NULL, NULL);
|
||||
if (l < 0) l = 0;
|
||||
buf[l] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
// FIXME: This should maybe return 'const char *' instead of 'char *'
|
||||
char *fl_locale_to_utf8(const char *s, int len, UINT codepage)
|
||||
{
|
||||
if (!s) return (char *)"";
|
||||
int l = 0;
|
||||
if (buf_len < len * 5 + 1) {
|
||||
buf_len = len * 5 + 1;
|
||||
buf = (char*) realloc(buf, buf_len);
|
||||
wbufa = (unsigned short*) realloc(wbufa, buf_len * sizeof(short));
|
||||
}
|
||||
if (codepage < 1) codepage = fl_codepage;
|
||||
buf[l] = 0;
|
||||
|
||||
l = MultiByteToWideChar(codepage, 0, s, len, (WCHAR*)wbufa, buf_len);
|
||||
if (l < 0) l = 0;
|
||||
wbufa[l] = 0;
|
||||
l = fl_utf8fromwc(buf, buf_len, (wchar_t*)wbufa, l);
|
||||
buf[l] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
|
||||
unsigned Fl_WinAPI_System_Driver::utf8towc(const char *src, unsigned srclen, wchar_t *dst, unsigned dstlen) {
|
||||
return fl_utf8toUtf16(src, srclen, (unsigned short*)dst, dstlen);
|
||||
}
|
||||
|
||||
unsigned Fl_WinAPI_System_Driver::utf8fromwc(char *dst, unsigned dstlen, const wchar_t *src, unsigned srclen)
|
||||
{
|
||||
unsigned i = 0;
|
||||
unsigned count = 0;
|
||||
if (dstlen) for (;;) {
|
||||
unsigned ucs;
|
||||
if (i >= srclen) {
|
||||
dst[count] = 0;
|
||||
return count;
|
||||
}
|
||||
ucs = src[i++];
|
||||
if (ucs < 0x80U) {
|
||||
dst[count++] = ucs;
|
||||
if (count >= dstlen) {dst[count-1] = 0; break;}
|
||||
} else if (ucs < 0x800U) { /* 2 bytes */
|
||||
if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;}
|
||||
dst[count++] = 0xc0 | (ucs >> 6);
|
||||
dst[count++] = 0x80 | (ucs & 0x3F);
|
||||
} else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen &&
|
||||
src[i] >= 0xdc00 && src[i] <= 0xdfff) {
|
||||
/* surrogate pair */
|
||||
unsigned ucs2 = src[i++];
|
||||
ucs = 0x10000U + ((ucs&0x3ff)<<10) + (ucs2&0x3ff);
|
||||
/* all surrogate pairs turn into 4-byte UTF-8 */
|
||||
if (count+4 >= dstlen) {dst[count] = 0; count += 4; break;}
|
||||
dst[count++] = 0xf0 | (ucs >> 18);
|
||||
dst[count++] = 0x80 | ((ucs >> 12) & 0x3F);
|
||||
dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
|
||||
dst[count++] = 0x80 | (ucs & 0x3F);
|
||||
} else {
|
||||
/* all others are 3 bytes: */
|
||||
if (count+3 >= dstlen) {dst[count] = 0; count += 3; break;}
|
||||
dst[count++] = 0xe0 | (ucs >> 12);
|
||||
dst[count++] = 0x80 | ((ucs >> 6) & 0x3F);
|
||||
dst[count++] = 0x80 | (ucs & 0x3F);
|
||||
}
|
||||
}
|
||||
/* we filled dst, measure the rest: */
|
||||
while (i < srclen) {
|
||||
unsigned ucs = src[i++];
|
||||
if (ucs < 0x80U) {
|
||||
count++;
|
||||
} else if (ucs < 0x800U) { /* 2 bytes */
|
||||
count += 2;
|
||||
} else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen-1 &&
|
||||
src[i+1] >= 0xdc00 && src[i+1] <= 0xdfff) {
|
||||
/* surrogate pair */
|
||||
++i;
|
||||
count += 4;
|
||||
} else {
|
||||
count += 3;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::utf8locale()
|
||||
{
|
||||
static int ret = (GetACP() == CP_UTF8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned Fl_WinAPI_System_Driver::utf8to_mb(const char *src, unsigned srclen, char *dst, unsigned dstlen) {
|
||||
wchar_t lbuf[1024];
|
||||
wchar_t *buf = lbuf;
|
||||
unsigned length = fl_utf8towc(src, srclen, buf, 1024);
|
||||
unsigned ret;
|
||||
if (length >= 1024) {
|
||||
buf = (wchar_t*)(malloc((length+1)*sizeof(wchar_t)));
|
||||
fl_utf8towc(src, srclen, buf, length+1);
|
||||
}
|
||||
if (dstlen) {
|
||||
// apparently this does not null-terminate, even though msdn documentation claims it does:
|
||||
ret =
|
||||
WideCharToMultiByte(GetACP(), 0, buf, length, dst, dstlen, 0, 0);
|
||||
dst[ret] = 0;
|
||||
}
|
||||
// if it overflows or measuring length, get the actual length:
|
||||
if (dstlen==0 || ret >= dstlen-1)
|
||||
ret = WideCharToMultiByte(GetACP(), 0, buf, length, 0, 0, 0, 0);
|
||||
if (buf != lbuf) free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned Fl_WinAPI_System_Driver::utf8from_mb(char *dst, unsigned dstlen, const char *src, unsigned srclen) {
|
||||
wchar_t lbuf[1024];
|
||||
wchar_t *buf = lbuf;
|
||||
unsigned length;
|
||||
unsigned ret;
|
||||
length = MultiByteToWideChar(GetACP(), 0, src, srclen, buf, 1024);
|
||||
if ((length == 0)&&(GetLastError()==ERROR_INSUFFICIENT_BUFFER)) {
|
||||
length = MultiByteToWideChar(GetACP(), 0, src, srclen, 0, 0);
|
||||
buf = (wchar_t*)(malloc(length*sizeof(wchar_t)));
|
||||
MultiByteToWideChar(GetACP(), 0, src, srclen, buf, length);
|
||||
}
|
||||
ret = fl_utf8fromwc(dst, dstlen, buf, length);
|
||||
if (buf != lbuf) free((void*)buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::clocale_printf(FILE *output, const char *format, va_list args) {
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400 /*Visual Studio 2005*/)
|
||||
static _locale_t c_locale = _create_locale(LC_NUMERIC, "C");
|
||||
int retval = _vfprintf_l(output, format, c_locale, args);
|
||||
#else
|
||||
char *saved_locale = setlocale(LC_NUMERIC, NULL);
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
int retval = vfprintf(output, format, args);
|
||||
setlocale(LC_NUMERIC, saved_locale);
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list, int (*sort)(struct dirent **, struct dirent **) ) {
|
||||
// For Windows we have a special scandir implementation that uses
|
||||
// the Win32 "wide" functions for lookup, avoiding the code page mess
|
||||
// entirely. It also fixes up the trailing '/'.
|
||||
return fl_scandir(d, list, 0, sort);
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::filename_expand(char *to, int tolen, const char *from) {
|
||||
char *temp = new char[tolen];
|
||||
strlcpy(temp,from, tolen);
|
||||
char *start = temp;
|
||||
char *end = temp+strlen(temp);
|
||||
int ret = 0;
|
||||
for (char *a=temp; a<end; ) { // for each slash component
|
||||
char *e; for (e=a; e<end && !isdirsep(*e); e++) {/*empty*/} // find next slash
|
||||
const char *value = 0; // this will point at substitute value
|
||||
switch (*a) {
|
||||
case '~': // a home directory name
|
||||
if (e <= a+1) { // current user's directory
|
||||
value = getenv("HOME");
|
||||
}
|
||||
break;
|
||||
case '$': /* an environment variable */
|
||||
{char t = *e; *(char *)e = 0; value = getenv(a+1); *(char *)e = t;}
|
||||
break;
|
||||
}
|
||||
if (value) {
|
||||
// substitutions that start with slash delete everything before them:
|
||||
if (isdirsep(value[0])) start = a;
|
||||
// also if it starts with "A:"
|
||||
if (value[0] && value[1]==':') start = a;
|
||||
int t = (int) strlen(value); if (isdirsep(value[t-1])) t--;
|
||||
if ((end+1-e+t) >= tolen) end += tolen - (end+1-e+t);
|
||||
memmove(a+t, e, end+1-e);
|
||||
end = a+t+(end-e);
|
||||
*end = '\0';
|
||||
memcpy(a, value, t);
|
||||
ret++;
|
||||
} else {
|
||||
a = e+1;
|
||||
if (*e == '\\') {*e = '/'; ret++;} // ha ha!
|
||||
}
|
||||
}
|
||||
strlcpy(to, start, tolen);
|
||||
delete[] temp;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int // O - 0 if no change, 1 if changed
|
||||
Fl_WinAPI_System_Driver::filename_relative(char *to, // O - Relative filename
|
||||
int tolen, // I - Size of "to" buffer
|
||||
const char *from, // I - Absolute filename
|
||||
const char *base) // I - Find path relative to this path
|
||||
{
|
||||
char *newslash; // Directory separator
|
||||
const char *slash; // Directory separator
|
||||
char *cwd = 0L, *cwd_buf = 0L;
|
||||
if (base) cwd = cwd_buf = strdup(base);
|
||||
|
||||
// return if "from" is not an absolute path
|
||||
if (from[0] == '\0' ||
|
||||
(!isdirsep(*from) && !isalpha(*from) && from[1] != ':' &&
|
||||
!isdirsep(from[2]))) {
|
||||
strlcpy(to, from, tolen);
|
||||
if (cwd_buf) free(cwd_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return if "cwd" is not an absolute path
|
||||
if (!cwd || cwd[0] == '\0' ||
|
||||
(!isdirsep(*cwd) && !isalpha(*cwd) && cwd[1] != ':' &&
|
||||
!isdirsep(cwd[2]))) {
|
||||
strlcpy(to, from, tolen);
|
||||
if (cwd_buf) free(cwd_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// convert all backslashes into forward slashes
|
||||
for (newslash = strchr(cwd, '\\'); newslash; newslash = strchr(newslash + 1, '\\'))
|
||||
*newslash = '/';
|
||||
|
||||
// test for the exact same string and return "." if so
|
||||
if (!strcasecmp(from, cwd)) {
|
||||
strlcpy(to, ".", tolen);
|
||||
free(cwd_buf);
|
||||
return (1);
|
||||
}
|
||||
|
||||
// test for the same drive. Return the absolute path if not
|
||||
if (tolower(*from & 255) != tolower(*cwd & 255)) {
|
||||
// Not the same drive...
|
||||
strlcpy(to, from, tolen);
|
||||
free(cwd_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// compare the path name without the drive prefix
|
||||
from += 2; cwd += 2;
|
||||
|
||||
// compare both path names until we find a difference
|
||||
for (slash = from, newslash = cwd;
|
||||
*slash != '\0' && *newslash != '\0';
|
||||
slash ++, newslash ++)
|
||||
if (isdirsep(*slash) && isdirsep(*newslash)) continue;
|
||||
else if (tolower(*slash & 255) != tolower(*newslash & 255)) break;
|
||||
|
||||
// skip over trailing slashes
|
||||
if ( *newslash == '\0' && *slash != '\0' && !isdirsep(*slash)
|
||||
&&(newslash==cwd || !isdirsep(newslash[-1])) )
|
||||
newslash--;
|
||||
|
||||
// now go back to the first character of the first differing paths segment
|
||||
while (!isdirsep(*slash) && slash > from) slash --;
|
||||
if (isdirsep(*slash)) slash ++;
|
||||
|
||||
// do the same for the current dir
|
||||
if (isdirsep(*newslash)) newslash --;
|
||||
if (*newslash != '\0')
|
||||
while (!isdirsep(*newslash) && newslash > cwd) newslash --;
|
||||
|
||||
// prepare the destination buffer
|
||||
to[0] = '\0';
|
||||
to[tolen - 1] = '\0';
|
||||
|
||||
// now add a "previous dir" sequence for every following slash in the cwd
|
||||
while (*newslash != '\0') {
|
||||
if (isdirsep(*newslash)) strlcat(to, "../", tolen);
|
||||
newslash ++;
|
||||
}
|
||||
|
||||
// finally add the differing path from "from"
|
||||
strlcat(to, slash, tolen);
|
||||
|
||||
free(cwd_buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::filename_absolute(char *to, int tolen, const char *from) {
|
||||
if (isdirsep(*from) || *from == '|' || from[1]==':') {
|
||||
strlcpy(to, from, tolen);
|
||||
return 0;
|
||||
}
|
||||
char *a;
|
||||
char *temp = new char[tolen];
|
||||
const char *start = from;
|
||||
a = getcwd(temp, tolen);
|
||||
if (!a) {
|
||||
strlcpy(to, from, tolen);
|
||||
delete[] temp;
|
||||
return 0;
|
||||
}
|
||||
for (a = temp; *a; a++) if (*a=='\\') *a = '/'; // ha ha
|
||||
if (isdirsep(*(a-1))) a--;
|
||||
/* remove intermediate . and .. names: */
|
||||
while (*start == '.') {
|
||||
if (start[1]=='.' && isdirsep(start[2])) {
|
||||
char *b;
|
||||
for (b = a-1; b >= temp && !isdirsep(*b); b--) {/*empty*/}
|
||||
if (b < temp) break;
|
||||
a = b;
|
||||
start += 3;
|
||||
} else if (isdirsep(start[1])) {
|
||||
start += 2;
|
||||
} else if (!start[1]) {
|
||||
start ++; // Skip lone "."
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
*a++ = '/';
|
||||
strlcpy(a,start,tolen - (a - temp));
|
||||
strlcpy(to, temp, tolen);
|
||||
delete[] temp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::filename_isdir(const char *n)
|
||||
{
|
||||
struct _stat s;
|
||||
char fn[FL_PATH_MAX];
|
||||
int length;
|
||||
length = (int) strlen(n);
|
||||
// This workaround brought to you by the fine folks at Microsoft!
|
||||
// (read lots of sarcasm in that...)
|
||||
if (length < (int)(sizeof(fn) - 1)) {
|
||||
if (length < 4 && isalpha(n[0]) && n[1] == ':' &&
|
||||
(isdirsep(n[2]) || !n[2])) {
|
||||
// Always use D:/ for drive letters
|
||||
fn[0] = n[0];
|
||||
strcpy(fn + 1, ":/");
|
||||
n = fn;
|
||||
} else if (length > 0 && isdirsep(n[length - 1])) {
|
||||
// Strip trailing slash from name...
|
||||
length --;
|
||||
memcpy(fn, n, length);
|
||||
fn[length] = '\0';
|
||||
n = fn;
|
||||
}
|
||||
}
|
||||
return !_stat(n, &s) && (s.st_mode & _S_IFDIR);
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::filename_isdir_quick(const char *n)
|
||||
{
|
||||
// Do a quick optimization for filenames with a trailing slash...
|
||||
if (*n && isdirsep(n[strlen(n) - 1])) return 1;
|
||||
return filename_isdir(n);
|
||||
}
|
||||
|
||||
const char *Fl_WinAPI_System_Driver::filename_ext(const char *buf) {
|
||||
const char *q = 0;
|
||||
const char *p = buf;
|
||||
for (p = buf; *p; p++) {
|
||||
if (isdirsep(*p) ) q = 0;
|
||||
else if (*p == '.') q = p;
|
||||
}
|
||||
return q ? q : p;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::open_uri(const char *uri, char *msg, int msglen)
|
||||
{
|
||||
if (msg) snprintf(msg, msglen, "open %s", uri);
|
||||
return (int)(ShellExecute(HWND_DESKTOP, "open", uri, NULL, NULL, SW_SHOW) > (void *)32);
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::file_browser_load_filesystem(Fl_File_Browser *browser, char *filename, int lname, Fl_File_Icon *icon)
|
||||
{
|
||||
int num_files = 0;
|
||||
# ifdef __CYGWIN__
|
||||
//
|
||||
// Cygwin provides an implementation of setmntent() to get the list
|
||||
// of available drives...
|
||||
//
|
||||
FILE *m = setmntent("/-not-used-", "r");
|
||||
struct mntent *p;
|
||||
while ((p = getmntent (m)) != NULL) {
|
||||
browser->add(p->mnt_dir, icon);
|
||||
num_files ++;
|
||||
}
|
||||
endmntent(m);
|
||||
# else
|
||||
//
|
||||
// Normal Windows code uses drive bits...
|
||||
//
|
||||
DWORD drives; // Drive available bits
|
||||
drives = GetLogicalDrives();
|
||||
for (int i = 'A'; i <= 'Z'; i ++, drives >>= 1)
|
||||
if (drives & 1)
|
||||
{
|
||||
sprintf(filename, "%c:/", i);
|
||||
if (i < 'C') // see also: GetDriveType and GetVolumeInformation in Windows
|
||||
browser->add(filename, icon);
|
||||
else
|
||||
browser->add(filename, icon);
|
||||
num_files ++;
|
||||
}
|
||||
# endif // __CYGWIN__
|
||||
return num_files;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::file_browser_load_directory(const char *directory, char *filename,
|
||||
size_t name_size, dirent ***pfiles, Fl_File_Sort_F *sort)
|
||||
{
|
||||
strlcpy(filename, directory, name_size);
|
||||
int i = (int) (strlen(filename) - 1);
|
||||
if (i == 2 && filename[1] == ':' &&
|
||||
(filename[2] == '/' || filename[2] == '\\'))
|
||||
filename[2] = '/';
|
||||
else if (filename[i] != '/' && filename[i] != '\\')
|
||||
strlcat(filename, "/", name_size);
|
||||
return filename_list(filename, pfiles, sort);
|
||||
}
|
||||
|
||||
void Fl_WinAPI_System_Driver::newUUID(char *uuidBuffer)
|
||||
{
|
||||
// First try and use the win API function UuidCreate(), but if that is not
|
||||
// available, fall back to making something up from scratch.
|
||||
// We do not want to link against the Rpcrt4.dll, as we will rarely use it,
|
||||
// so we load the DLL dynamically, if it is available, and work from there.
|
||||
static HMODULE hMod = NULL;
|
||||
UUID ud;
|
||||
UUID *pu = &ud;
|
||||
int got_uuid = 0;
|
||||
|
||||
if (!hMod) { // first time in?
|
||||
hMod = LoadLibrary("Rpcrt4.dll");
|
||||
}
|
||||
|
||||
if (hMod) { // do we have a usable handle to Rpcrt4.dll?
|
||||
uuid_func uuid_crt = (uuid_func)GetProcAddress(hMod, "UuidCreate");
|
||||
if (uuid_crt != NULL) {
|
||||
RPC_STATUS rpc_res = uuid_crt(pu);
|
||||
if ( // is the return status OK for our needs?
|
||||
(rpc_res == RPC_S_OK) || // all is well
|
||||
(rpc_res == RPC_S_UUID_LOCAL_ONLY) || // only unique to this machine
|
||||
(rpc_res == RPC_S_UUID_NO_ADDRESS) // probably only locally unique
|
||||
) {
|
||||
got_uuid = -1;
|
||||
sprintf(uuidBuffer, "%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
pu->Data1, pu->Data2, pu->Data3, pu->Data4[0], pu->Data4[1],
|
||||
pu->Data4[2], pu->Data4[3], pu->Data4[4],
|
||||
pu->Data4[5], pu->Data4[6], pu->Data4[7]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (got_uuid == 0) { // did not make a UUID - use fallback logic
|
||||
unsigned char b[16];
|
||||
time_t t = time(0); // first 4 byte
|
||||
b[0] = (unsigned char)t;
|
||||
b[1] = (unsigned char)(t>>8);
|
||||
b[2] = (unsigned char)(t>>16);
|
||||
b[3] = (unsigned char)(t>>24);
|
||||
int r = rand(); // four more bytes
|
||||
b[4] = (unsigned char)r;
|
||||
b[5] = (unsigned char)(r>>8);
|
||||
b[6] = (unsigned char)(r>>16);
|
||||
b[7] = (unsigned char)(r>>24);
|
||||
// Now we try to find 4 more "random" bytes. We extract the
|
||||
// lower 4 bytes from the address of t - it is created on the
|
||||
// stack so *might* be in a different place each time...
|
||||
// This is now done via a union to make it compile OK on 64-bit systems.
|
||||
union { void *pv; unsigned char a[sizeof(void*)]; } v;
|
||||
v.pv = (void *)(&t);
|
||||
// NOTE: This assume that all WinXX systems are little-endian
|
||||
b[8] = v.a[0];
|
||||
b[9] = v.a[1];
|
||||
b[10] = v.a[2];
|
||||
b[11] = v.a[3];
|
||||
TCHAR name[MAX_COMPUTERNAME_LENGTH + 1]; // only used to make last four bytes
|
||||
DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
|
||||
// GetComputerName() does not depend on any extra libs, and returns something
|
||||
// analogous to gethostname()
|
||||
GetComputerName(name, &nSize);
|
||||
// use the first 4 TCHAR's of the name to create the last 4 bytes of our UUID
|
||||
for (int ii = 0; ii < 4; ii++) {
|
||||
b[12 + ii] = (unsigned char)name[ii];
|
||||
}
|
||||
sprintf(uuidBuffer, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
|
||||
b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]);
|
||||
}
|
||||
}
|
||||
|
||||
char *Fl_WinAPI_System_Driver::preference_rootnode(Fl_Preferences *prefs, Fl_Preferences::Root root, const char *vendor,
|
||||
const char *application)
|
||||
{
|
||||
# define FLPREFS_RESOURCE "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
|
||||
# define FLPREFS_RESOURCEW L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
|
||||
static char filename[ FL_PATH_MAX ];
|
||||
filename[0] = 0;
|
||||
size_t appDataLen = strlen(vendor) + strlen(application) + 8;
|
||||
DWORD type, nn;
|
||||
LONG err;
|
||||
HKEY key;
|
||||
|
||||
switch (root) {
|
||||
case Fl_Preferences::SYSTEM:
|
||||
err = RegOpenKeyW( HKEY_LOCAL_MACHINE, FLPREFS_RESOURCEW, &key );
|
||||
if (err == ERROR_SUCCESS) {
|
||||
nn = (DWORD) (FL_PATH_MAX - appDataLen);
|
||||
err = RegQueryValueExW( key, L"Common AppData", 0L, &type,
|
||||
(BYTE*)filename, &nn );
|
||||
if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) ) {
|
||||
filename[0] = 0;
|
||||
filename[1] = 0;
|
||||
}
|
||||
RegCloseKey(key);
|
||||
}
|
||||
break;
|
||||
case Fl_Preferences::USER:
|
||||
err = RegOpenKeyW( HKEY_CURRENT_USER, FLPREFS_RESOURCEW, &key );
|
||||
if (err == ERROR_SUCCESS) {
|
||||
nn = (DWORD) (FL_PATH_MAX - appDataLen);
|
||||
err = RegQueryValueExW( key, L"AppData", 0L, &type,
|
||||
(BYTE*)filename, &nn );
|
||||
if ( ( err != ERROR_SUCCESS ) && ( type == REG_SZ ) ) {
|
||||
filename[0] = 0;
|
||||
filename[1] = 0;
|
||||
}
|
||||
RegCloseKey(key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!filename[1] && !filename[0]) {
|
||||
strcpy(filename, "C:\\FLTK");
|
||||
} else {
|
||||
#if 0
|
||||
wchar_t *b = (wchar_t*)_wcsdup((wchar_t *)filename);
|
||||
#else
|
||||
// cygwin does not come with _wcsdup. Use malloc + wcscpy.
|
||||
// For implementation of wcsdup functionality See
|
||||
// - http://linenum.info/p/glibc/2.7/wcsmbs/wcsdup.c
|
||||
wchar_t *b = (wchar_t *)malloc((wcslen((wchar_t *)filename) + 1) * sizeof(wchar_t));
|
||||
wcscpy(b, (wchar_t *) filename);
|
||||
#endif
|
||||
// filename[fl_unicode2utf(b, wcslen((wchar_t*)b), filename)] = 0;
|
||||
unsigned len = fl_utf8fromwc(filename, (FL_PATH_MAX-1), b, (unsigned) wcslen(b));
|
||||
filename[len] = 0;
|
||||
free(b);
|
||||
}
|
||||
snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename),
|
||||
"/%s/%s.prefs", vendor, application);
|
||||
for (char *s = filename; *s; s++) if (*s == '\\') *s = '/';
|
||||
return filename;
|
||||
}
|
||||
|
||||
void *Fl_WinAPI_System_Driver::dlopen(const char *filename) {
|
||||
return LoadLibraryW(utf8_to_wchar(filename, wbuf));
|
||||
}
|
||||
|
||||
void Fl_WinAPI_System_Driver::png_extra_rgba_processing(unsigned char *ptr, int w, int h)
|
||||
{
|
||||
// Some Windows graphics drivers don't honor transparency when RGB == white
|
||||
// Convert RGB to 0 when alpha == 0...
|
||||
for (int i = w * h; i > 0; i --, ptr += 4) {
|
||||
if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Fl_WinAPI_System_Driver::next_dir_sep(const char *start)
|
||||
{
|
||||
const char *p = strchr(start, '/');
|
||||
if (!p) p = strchr(start, '\\');
|
||||
return p;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::file_type(const char *filename)
|
||||
{
|
||||
int filetype;
|
||||
if (filename[strlen(filename) - 1] == '/')
|
||||
filetype = Fl_File_Icon::DIRECTORY;
|
||||
else if (filename_isdir(filename))
|
||||
filetype = Fl_File_Icon::DIRECTORY;
|
||||
else
|
||||
filetype = Fl_File_Icon::PLAIN;
|
||||
return filetype;
|
||||
}
|
||||
|
||||
const char *Fl_WinAPI_System_Driver::home_directory_name()
|
||||
{
|
||||
const char *h = getenv("HOME");
|
||||
if (!h) h = getenv("UserProfile");
|
||||
return h;
|
||||
}
|
||||
|
||||
void Fl_WinAPI_System_Driver::gettime(time_t *sec, int *usec) {
|
||||
struct _timeb t;
|
||||
_ftime(&t);
|
||||
*sec = t.time;
|
||||
*usec = t.millitm * 1000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Android_System_Driver.cxx 12655 2018-02-09 14:39:42Z AlbrechtS $".
|
||||
//
|
144
src/drivers/Android/Fl_Android_Window_Driver.H
Normal file
144
src/drivers/Android/Fl_Android_Window_Driver.H
Normal file
@ -0,0 +1,144 @@
|
||||
//
|
||||
// "$Id: Fl_Android_Window_Driver.H 12668 2018-02-16 16:24:32Z manolo $"
|
||||
//
|
||||
// Definition of Apple Cocoa window driver
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2018 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_WinAPI_Window_Driver.H
|
||||
\brief Definition of Windows window driver.
|
||||
*/
|
||||
|
||||
#ifndef FL_WINAPI_WINDOW_DRIVER_H
|
||||
#define FL_WINAPI_WINDOW_DRIVER_H
|
||||
|
||||
#include <FL/Fl_Window_Driver.H>
|
||||
//#include <windows.h>
|
||||
|
||||
/*
|
||||
Move everything here that manages the native window interface.
|
||||
|
||||
There is one window driver for each Fl_Window. Window drivers manage window
|
||||
actions such as resizing, events, decoration, fullscreen modes, etc. . All
|
||||
drawing and rendering is managed by the Surface device and the associated
|
||||
graphics driver.
|
||||
|
||||
- window specific event handling
|
||||
- window types and styles, depth, etc.
|
||||
- decorations
|
||||
|
||||
? where do we handle the interface between OpenGL/DirectX and Cocoa/Windows/Glx?
|
||||
*/
|
||||
|
||||
|
||||
struct Fl_Window_Driver::shape_data_type {
|
||||
int lw_; ///< width of shape image
|
||||
int lh_; ///< height of shape image
|
||||
Fl_Image* shape_; ///< shape image
|
||||
Fl_Bitmap *todelete_; ///< auxiliary bitmap image
|
||||
};
|
||||
|
||||
class FL_EXPORT Fl_Android_Window_Driver : public Fl_Window_Driver
|
||||
{
|
||||
static Fl_Window *sCurrent;
|
||||
#if 0
|
||||
|
||||
friend class Fl_Window;
|
||||
struct icon_data {
|
||||
const void *legacy_icon;
|
||||
Fl_RGB_Image **icons;
|
||||
int count;
|
||||
HICON big_icon;
|
||||
HICON small_icon;
|
||||
};
|
||||
int screen_num_;
|
||||
private:
|
||||
void shape_bitmap_(Fl_Image* b);
|
||||
void shape_alpha_(Fl_Image* img, int offset);
|
||||
#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();
|
||||
}
|
||||
|
||||
#if 0
|
||||
HDC private_dc; // used for OpenGL
|
||||
RECT border_width_title_bar_height(int &bx, int &by, int &bt);
|
||||
virtual void screen_num(int n);
|
||||
virtual int screen_num();
|
||||
|
||||
struct icon_data *icon_;
|
||||
HCURSOR cursor;
|
||||
int custom_cursor;
|
||||
struct type_for_resize_window_between_screens {
|
||||
int screen;
|
||||
bool busy;
|
||||
};
|
||||
static type_for_resize_window_between_screens data_for_resize_window_between_screens_;
|
||||
void set_minmax(LPMINMAXINFO minmax);
|
||||
int fake_X_wm(int &X, int &Y, int &bt,int &bx,int &by);
|
||||
void make_fullscreen(int X, int Y, int W, int H);
|
||||
// --- window data
|
||||
virtual int decorated_w();
|
||||
virtual int decorated_h();
|
||||
|
||||
// --- window management
|
||||
virtual Fl_X *makeWindow();
|
||||
virtual void flush_double();
|
||||
virtual void flush_overlay();
|
||||
virtual void draw_begin();
|
||||
virtual void make_current() { sCurrent = this; }
|
||||
#endif
|
||||
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();
|
||||
virtual void fullscreen_off(int X, int Y, int W, int H);
|
||||
virtual void iconize();
|
||||
virtual void decoration_sizes(int *top, int *left, int *right, int *bottom);
|
||||
// --- window cursor stuff
|
||||
virtual int set_cursor(Fl_Cursor);
|
||||
virtual int set_cursor(const Fl_RGB_Image*, int, int);
|
||||
|
||||
virtual void shape(const Fl_Image* img);
|
||||
virtual void icons(const Fl_RGB_Image *icons[], int count);
|
||||
virtual const void *icon() const;
|
||||
virtual void icon(const void * ic);
|
||||
virtual void free_icons();
|
||||
void set_icons(); // driver-internal support function
|
||||
// this one is implemented in Fl_win32.cxx
|
||||
virtual void capture_titlebar_and_borders(Fl_Shared_Image*& top, Fl_Shared_Image*& left, Fl_Shared_Image*& bottom, Fl_Shared_Image*& right);
|
||||
virtual int scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y,
|
||||
void (*draw_area)(void*, int,int,int,int), void* data);
|
||||
static void resize_after_screen_change(void *data);
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_WINAPI_WINDOW_DRIVER_H
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Android_Window_Driver.H 12668 2018-02-16 16:24:32Z manolo $".
|
||||
//
|
732
src/drivers/Android/Fl_Android_Window_Driver.cxx
Normal file
732
src/drivers/Android/Fl_Android_Window_Driver.cxx
Normal file
@ -0,0 +1,732 @@
|
||||
//
|
||||
// "$Id: Fl_Android_Window_Driver.cxx 12641 2018-01-31 21:17:17Z AlbrechtS $"
|
||||
//
|
||||
// Definition of Apple Cocoa window driver.
|
||||
//
|
||||
// Copyright 1998-2018 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
|
||||
#include "../../config_lib.h"
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Image.H>
|
||||
#include <FL/Fl_Bitmap.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Overlay_Window.H>
|
||||
#include <FL/platform.H>
|
||||
#include "Fl_Android_Window_Driver.H"
|
||||
#include "Fl_Android_Screen_Driver.H"
|
||||
#include "Fl_Android_Graphics_Driver.H"
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
#include <windows.h>
|
||||
#include <math.h> // for ceil()
|
||||
|
||||
#if USE_COLORMAP
|
||||
extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Fl_Window *Fl_Android_Window_Driver::sCurrent = 0L;
|
||||
|
||||
|
||||
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
|
||||
{
|
||||
return new Fl_Android_Window_Driver(w);
|
||||
}
|
||||
|
||||
void Fl_Window_Driver::default_icons(Fl_RGB_Image const**, int) {
|
||||
}
|
||||
|
||||
Window fl_window = 0;
|
||||
|
||||
|
||||
void Fl_Android_Window_Driver::show()
|
||||
{
|
||||
if (!shown()) {
|
||||
// make window
|
||||
fl_open_display();
|
||||
pWindow->set_visible();
|
||||
Fl_X *x = new Fl_X;
|
||||
x->w = pWindow;
|
||||
i(x);
|
||||
x->next = Fl_X::first;
|
||||
Fl_X::first = x;
|
||||
} else {
|
||||
// bring window to front
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
Fl_WinAPI_Window_Driver::Fl_WinAPI_Window_Driver(Fl_Window *win)
|
||||
: Fl_Window_Driver(win)
|
||||
{
|
||||
icon_ = new icon_data;
|
||||
memset(icon_, 0, sizeof(icon_data));
|
||||
cursor = NULL;
|
||||
screen_num_ = -1;
|
||||
}
|
||||
|
||||
|
||||
Fl_WinAPI_Window_Driver::~Fl_WinAPI_Window_Driver()
|
||||
{
|
||||
if (shape_data_) {
|
||||
delete shape_data_->todelete_;
|
||||
delete shape_data_;
|
||||
}
|
||||
delete icon_;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_Window_Driver::screen_num() {
|
||||
if (pWindow->parent()) {
|
||||
screen_num_ = pWindow->top_window()->driver()->screen_num();
|
||||
}
|
||||
return screen_num_ >= 0 ? screen_num_ : 0;
|
||||
}
|
||||
|
||||
//FILE*LOG=fopen("log.log","w");
|
||||
|
||||
void Fl_WinAPI_Window_Driver::screen_num(int n) {
|
||||
//fprintf(LOG, "screen_num setter old=%d new=%d\n",screen_num_, n);fflush(LOG);
|
||||
screen_num_ = n;
|
||||
}
|
||||
|
||||
|
||||
RECT // frame of the decorated window in screen coordinates
|
||||
Fl_WinAPI_Window_Driver::border_width_title_bar_height(
|
||||
int &bx, // left and right border width
|
||||
int &by, // bottom border height (=bx)
|
||||
int &bt // height of window title bar
|
||||
)
|
||||
{
|
||||
Fl_Window *win = pWindow;
|
||||
RECT r = {0,0,0,0};
|
||||
bx = by = bt = 0;
|
||||
if (win->shown() && !win->parent() && win->border() && win->visible()) {
|
||||
static HMODULE dwmapi_dll = LoadLibrary("dwmapi.dll");
|
||||
typedef HRESULT (WINAPI* DwmGetWindowAttribute_type)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
|
||||
static DwmGetWindowAttribute_type DwmGetWindowAttribute = dwmapi_dll ?
|
||||
(DwmGetWindowAttribute_type)GetProcAddress(dwmapi_dll, "DwmGetWindowAttribute") : NULL;
|
||||
int need_r = 1;
|
||||
if (DwmGetWindowAttribute) {
|
||||
const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9;
|
||||
if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) {
|
||||
need_r = 0;
|
||||
}
|
||||
}
|
||||
if (need_r) {
|
||||
GetWindowRect(fl_xid(win), &r);
|
||||
}
|
||||
int width, height;
|
||||
#ifdef FLTK_HIDPI_SUPPORT
|
||||
RECT rc;
|
||||
GetClientRect(fl_xid(win), &rc);
|
||||
width = rc.right;
|
||||
height = rc.bottom;
|
||||
#else
|
||||
float scaling = ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->DWM_scaling_factor();
|
||||
width = int(win->w() * scaling);
|
||||
height = int(win->h() * scaling);
|
||||
#endif
|
||||
bx = (r.right - r.left - width)/2;
|
||||
if (bx < 1) bx = 1;
|
||||
by = bx;
|
||||
bt = r.bottom - r.top - height - 2 * by;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
// --- window data
|
||||
|
||||
int Fl_WinAPI_Window_Driver::decorated_w()
|
||||
{
|
||||
int bt, bx, by;
|
||||
float s = Fl::screen_driver()->scale(screen_num());
|
||||
border_width_title_bar_height(bx, by, bt);
|
||||
int mini_bx = bx/s; if (mini_bx < 1) mini_bx = 1;
|
||||
return w() + 2 * mini_bx;
|
||||
}
|
||||
|
||||
int Fl_WinAPI_Window_Driver::decorated_h()
|
||||
{
|
||||
int bt, bx, by;
|
||||
border_width_title_bar_height(bx, by, bt);
|
||||
#ifdef FLTK_HIDPI_SUPPORT
|
||||
float s = Fl::screen_driver()->scale(screen_num());
|
||||
int mini_by = by/s; if (mini_by < 1) mini_by = 1;
|
||||
return h() + (bt + by)/s + mini_by;
|
||||
#else
|
||||
float scaling = ((Fl_WinAPI_Screen_Driver*)Fl::screen_driver())->DWM_scaling_factor();
|
||||
return h() + bt/scaling + 2 * by +1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// --- window management
|
||||
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::shape_bitmap_(Fl_Image* b) {
|
||||
shape_data_->shape_ = b;
|
||||
}
|
||||
|
||||
void Fl_WinAPI_Window_Driver::shape_alpha_(Fl_Image* img, int offset) {
|
||||
int i, j, d = img->d(), w = img->w(), h = img->h(), bytesperrow = (w+7)/8;
|
||||
unsigned u;
|
||||
uchar byte, onebit;
|
||||
// build an Fl_Bitmap covering the non-fully transparent/black part of the image
|
||||
const uchar* bits = new uchar[h*bytesperrow]; // to store the bitmap
|
||||
const uchar* alpha = (const uchar*)*img->data() + offset; // points to alpha value of rgba pixels
|
||||
for (i = 0; i < h; i++) {
|
||||
uchar *p = (uchar*)bits + i * bytesperrow;
|
||||
byte = 0;
|
||||
onebit = 1;
|
||||
for (j = 0; j < w; j++) {
|
||||
if (d == 3) {
|
||||
u = *alpha;
|
||||
u += *(alpha+1);
|
||||
u += *(alpha+2);
|
||||
}
|
||||
else u = *alpha;
|
||||
if (u > 0) { // if the pixel is not fully transparent/black
|
||||
byte |= onebit; // turn on the corresponding bit of the bitmap
|
||||
}
|
||||
onebit = onebit << 1; // move the single set bit one position to the left
|
||||
if (onebit == 0 || j == w-1) {
|
||||
onebit = 1;
|
||||
*p++ = byte; // store in bitmap one pack of bits
|
||||
byte = 0;
|
||||
}
|
||||
alpha += d; // point to alpha value of next pixel
|
||||
}
|
||||
}
|
||||
Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h);
|
||||
bitmap->alloc_array = 1;
|
||||
shape_bitmap_(bitmap);
|
||||
shape_data_->todelete_ = bitmap;
|
||||
}
|
||||
|
||||
void Fl_WinAPI_Window_Driver::shape(const Fl_Image* img) {
|
||||
if (shape_data_) {
|
||||
if (shape_data_->todelete_) { delete shape_data_->todelete_; }
|
||||
}
|
||||
else {
|
||||
shape_data_ = new shape_data_type;
|
||||
}
|
||||
memset(shape_data_, 0, sizeof(shape_data_type));
|
||||
pWindow->border(false);
|
||||
int d = img->d();
|
||||
if (d && img->count() >= 2) shape_pixmap_((Fl_Image*)img);
|
||||
else if (d == 0) shape_bitmap_((Fl_Image*)img);
|
||||
else if (d == 2 || d == 4) shape_alpha_((Fl_Image*)img, d - 1);
|
||||
else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_Image*)img, 0);
|
||||
}
|
||||
|
||||
|
||||
static inline BYTE bit(int x) { return (BYTE)(1 << (x%8)); }
|
||||
|
||||
static HRGN bitmap2region(Fl_Image* image) {
|
||||
HRGN hRgn = 0;
|
||||
/* Does this need to be dynamically determined, perhaps? */
|
||||
const int ALLOC_UNIT = 100;
|
||||
DWORD maxRects = ALLOC_UNIT;
|
||||
|
||||
RGNDATA* pData = (RGNDATA*)malloc(sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects));
|
||||
pData->rdh.dwSize = sizeof(RGNDATAHEADER);
|
||||
pData->rdh.iType = RDH_RECTANGLES;
|
||||
pData->rdh.nCount = pData->rdh.nRgnSize = 0;
|
||||
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
|
||||
|
||||
const int bytesPerLine = (image->w() + 7)/8;
|
||||
BYTE* p, *data = (BYTE*)*image->data();
|
||||
for (int y = 0; y < image->h(); y++) {
|
||||
// each row, left to right
|
||||
for (int x = 0; x < image->w(); x++) {
|
||||
int x0 = x;
|
||||
while (x < image->w()) {
|
||||
p = data + x / 8;
|
||||
if (!((*p) & bit(x))) break; // transparent pixel
|
||||
x++;
|
||||
}
|
||||
if (x > x0) {
|
||||
RECT *pr;
|
||||
/* Add the pixels (x0, y) to (x, y+1) as a new rectangle
|
||||
* in the region
|
||||
*/
|
||||
if (pData->rdh.nCount >= maxRects) {
|
||||
maxRects += ALLOC_UNIT;
|
||||
pData = (RGNDATA*)realloc(pData, sizeof(RGNDATAHEADER)
|
||||
+ (sizeof(RECT)*maxRects));
|
||||
}
|
||||
pr = (RECT*)&pData->Buffer;
|
||||
SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
|
||||
if (x0 < pData->rdh.rcBound.left)
|
||||
pData->rdh.rcBound.left = x0;
|
||||
if (y < pData->rdh.rcBound.top)
|
||||
pData->rdh.rcBound.top = y;
|
||||
if (x > pData->rdh.rcBound.right)
|
||||
pData->rdh.rcBound.right = x;
|
||||
if (y+1 > pData->rdh.rcBound.bottom)
|
||||
pData->rdh.rcBound.bottom = y+1;
|
||||
pData->rdh.nCount++;
|
||||
/* On Windows98, ExtCreateRegion() may fail if the
|
||||
* number of rectangles is too large (ie: >
|
||||
* 4000). Therefore, we have to create the region by
|
||||
* multiple steps.
|
||||
*/
|
||||
if (pData->rdh.nCount == 2000) {
|
||||
HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER)
|
||||
+ (sizeof(RECT)*maxRects), pData);
|
||||
if (hRgn) {
|
||||
CombineRgn(hRgn, hRgn, h, RGN_OR);
|
||||
DeleteObject(h);
|
||||
} else
|
||||
hRgn = h;
|
||||
pData->rdh.nCount = 0;
|
||||
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Go to next row */
|
||||
data += bytesPerLine;
|
||||
}
|
||||
/* Create or extend the region with the remaining rectangles*/
|
||||
HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER)
|
||||
+ (sizeof(RECT)*maxRects), pData);
|
||||
if (hRgn) {
|
||||
CombineRgn(hRgn, hRgn, h, RGN_OR);
|
||||
DeleteObject(h);
|
||||
} else hRgn = h;
|
||||
free(pData); // I've created the region so I can free this now, right?
|
||||
return hRgn;
|
||||
}
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::draw_begin()
|
||||
{
|
||||
if (shape_data_) {
|
||||
float s = Fl::screen_driver()->scale(screen_num());
|
||||
if ((shape_data_->lw_ != s*w() || shape_data_->lh_ != s*h()) && shape_data_->shape_) {
|
||||
// size of window has changed since last time
|
||||
shape_data_->lw_ = s*w();
|
||||
shape_data_->lh_ = s*h();
|
||||
Fl_Image* temp = shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_);
|
||||
HRGN region = bitmap2region(temp);
|
||||
SetWindowRgn(fl_xid(pWindow), region, TRUE); // the system deletes the region when it's no longer needed
|
||||
delete temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::flush_double()
|
||||
{
|
||||
if (!shown()) return;
|
||||
pWindow->make_current(); // make sure fl_gc is non-zero
|
||||
Fl_X *i = Fl_X::i(pWindow);
|
||||
if (!i) return; // window not yet created
|
||||
|
||||
if (!other_xid) {
|
||||
other_xid = fl_create_offscreen(w(), h());
|
||||
pWindow->clear_damage(FL_DAMAGE_ALL);
|
||||
}
|
||||
if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) {
|
||||
fl_clip_region(i->region); i->region = 0;
|
||||
fl_begin_offscreen(other_xid);
|
||||
fl_graphics_driver->clip_region( 0 );
|
||||
draw();
|
||||
fl_end_offscreen();
|
||||
}
|
||||
|
||||
int X,Y,W,H; fl_clip_box(0,0,w(),h(),X,Y,W,H);
|
||||
if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid, X, Y);
|
||||
}
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::flush_overlay()
|
||||
{
|
||||
Fl_Overlay_Window *oWindow = pWindow->as_overlay_window();
|
||||
|
||||
if (!shown()) return;
|
||||
pWindow->make_current(); // make sure fl_gc is non-zero
|
||||
Fl_X *i = Fl_X::i(pWindow);
|
||||
if (!i) return; // window not yet created
|
||||
|
||||
int eraseoverlay = (pWindow->damage()&FL_DAMAGE_OVERLAY);
|
||||
pWindow->clear_damage((uchar)(pWindow->damage()&~FL_DAMAGE_OVERLAY));
|
||||
|
||||
if (!other_xid) {
|
||||
other_xid = fl_create_offscreen(w(), h());
|
||||
pWindow->clear_damage(FL_DAMAGE_ALL);
|
||||
}
|
||||
if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) {
|
||||
fl_clip_region(i->region); i->region = 0;
|
||||
fl_begin_offscreen(other_xid);
|
||||
fl_graphics_driver->clip_region(0);
|
||||
draw();
|
||||
fl_end_offscreen();
|
||||
}
|
||||
|
||||
if (eraseoverlay) fl_clip_region(0);
|
||||
int X, Y, W, H; fl_clip_box(0, 0, w(), h(), X, Y, W, H);
|
||||
if (other_xid) fl_copy_offscreen(X, Y, W, H, other_xid, X, Y);
|
||||
|
||||
if (overlay() == oWindow) oWindow->draw_overlay();
|
||||
}
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::icons(const Fl_RGB_Image *icons[], int count) {
|
||||
free_icons();
|
||||
|
||||
if (count > 0) {
|
||||
icon_->icons = new Fl_RGB_Image*[count];
|
||||
icon_->count = count;
|
||||
// FIXME: Fl_RGB_Image lacks const modifiers on methods
|
||||
for (int i = 0;i < count;i++)
|
||||
icon_->icons[i] = (Fl_RGB_Image*)((Fl_RGB_Image*)icons[i])->copy();
|
||||
}
|
||||
|
||||
if (Fl_X::i(pWindow))
|
||||
set_icons();
|
||||
}
|
||||
|
||||
const void *Fl_WinAPI_Window_Driver::icon() const {
|
||||
return icon_->legacy_icon;
|
||||
}
|
||||
|
||||
void Fl_WinAPI_Window_Driver::icon(const void * ic) {
|
||||
free_icons();
|
||||
icon_->legacy_icon = ic;
|
||||
}
|
||||
|
||||
void Fl_WinAPI_Window_Driver::free_icons() {
|
||||
int i;
|
||||
icon_->legacy_icon = 0L;
|
||||
if (icon_->icons) {
|
||||
for (i = 0;i < icon_->count;i++)
|
||||
delete icon_->icons[i];
|
||||
delete [] icon_->icons;
|
||||
icon_->icons = 0L;
|
||||
}
|
||||
icon_->count = 0;
|
||||
if (icon_->big_icon)
|
||||
DestroyIcon(icon_->big_icon);
|
||||
if (icon_->small_icon)
|
||||
DestroyIcon(icon_->small_icon);
|
||||
icon_->big_icon = NULL;
|
||||
icon_->small_icon = NULL;
|
||||
}
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::make_current() {
|
||||
fl_GetDC(fl_xid(pWindow));
|
||||
|
||||
#if USE_COLORMAP
|
||||
// Windows maintains a hardware and software color palette; the
|
||||
// SelectPalette() call updates the current soft->hard mapping
|
||||
// for all drawing calls, so we must select it here before any
|
||||
// code does any drawing...
|
||||
fl_select_palette();
|
||||
#endif // USE_COLORMAP
|
||||
|
||||
fl_graphics_driver->clip_region(0);
|
||||
((Fl_GDI_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num()));
|
||||
}
|
||||
|
||||
void Fl_WinAPI_Window_Driver::label(const char *name,const char *iname) {
|
||||
if (shown() && !parent()) {
|
||||
if (!name) name = "";
|
||||
size_t l = strlen(name);
|
||||
// WCHAR *lab = (WCHAR*) malloc((l + 1) * sizeof(short));
|
||||
// l = fl_utf2unicode((unsigned char*)name, l, (wchar_t*)lab);
|
||||
unsigned wlen = fl_utf8toUtf16(name, (unsigned) l, NULL, 0); // Pass NULL to query length
|
||||
wlen++;
|
||||
unsigned short * lab = (unsigned short*)malloc(sizeof(unsigned short)*wlen);
|
||||
wlen = fl_utf8toUtf16(name, (unsigned) l, lab, wlen);
|
||||
lab[wlen] = 0;
|
||||
SetWindowTextW(fl_xid(pWindow), (WCHAR *)lab);
|
||||
free(lab);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern void fl_clipboard_notify_retarget(HWND wnd);
|
||||
extern void fl_update_clipboard(void);
|
||||
|
||||
void Fl_WinAPI_Window_Driver::hide() {
|
||||
Fl_X* ip = Fl_X::i(pWindow);
|
||||
// STR#3079: if there remains a window and a non-modal window, and the window is deleted,
|
||||
// the app remains running without any apparent window.
|
||||
// Bug mechanism: hiding an owner window unmaps the owned (non-modal) window(s)
|
||||
// but does not delete it(them) in FLTK.
|
||||
// Fix for it:
|
||||
// when hiding a window, build list of windows it owns, and do hide/show on them.
|
||||
int count = 0;
|
||||
Fl_Window *win, **doit = NULL;
|
||||
for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) {
|
||||
if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == ip->xid) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count) {
|
||||
doit = new Fl_Window*[count];
|
||||
count = 0;
|
||||
for (win = Fl::first_window(); win && ip; win = Fl::next_window(win)) {
|
||||
if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == ip->xid) {
|
||||
doit[count++] = win;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hide_common()) return;
|
||||
|
||||
// make sure any custom icons get freed
|
||||
// icons(NULL, 0); // free_icons() is called by the Fl_Window destructor
|
||||
// this little trick keeps the current clipboard alive, even if we are about
|
||||
// to destroy the window that owns the selection.
|
||||
if (GetClipboardOwner()==ip->xid)
|
||||
fl_update_clipboard();
|
||||
// Make sure we unlink this window from the clipboard chain
|
||||
fl_clipboard_notify_retarget(ip->xid);
|
||||
// Send a message to myself so that I'll get out of the event loop...
|
||||
PostMessage(ip->xid, WM_APP, 0, 0);
|
||||
if (private_dc) fl_release_dc(ip->xid, private_dc);
|
||||
if (ip->xid == fl_window && fl_graphics_driver->gc()) {
|
||||
fl_release_dc(fl_window, (HDC)fl_graphics_driver->gc());
|
||||
fl_window = (HWND)-1;
|
||||
fl_graphics_driver->gc(0);
|
||||
# ifdef FLTK_USE_CAIRO
|
||||
if (Fl::cairo_autolink_context()) Fl::cairo_make_current((Fl_Window*) 0);
|
||||
# endif
|
||||
}
|
||||
|
||||
if (ip->region) Fl_Graphics_Driver::default_driver().XDestroyRegion(ip->region);
|
||||
|
||||
// this little trickery seems to avoid the popup window stacking problem
|
||||
HWND p = GetForegroundWindow();
|
||||
if (p==GetParent(ip->xid)) {
|
||||
ShowWindow(ip->xid, SW_HIDE);
|
||||
ShowWindow(p, SW_SHOWNA);
|
||||
}
|
||||
DestroyWindow(ip->xid);
|
||||
// end of fix for STR#3079
|
||||
if (count) {
|
||||
int ii;
|
||||
for (ii = 0; ii < count; ii++) doit[ii]->hide();
|
||||
for (ii = 0; ii < count; ii++) {
|
||||
if (ii != 0) doit[0]->show(); // Fix for STR#3165
|
||||
doit[ii]->show();
|
||||
}
|
||||
delete[] doit;
|
||||
}
|
||||
// Try to stop the annoying "raise another program" behavior
|
||||
if (pWindow->non_modal() && Fl::first_window() && Fl::first_window()->shown())
|
||||
Fl::first_window()->show();
|
||||
delete ip;
|
||||
screen_num_ = -1;
|
||||
}
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::map() {
|
||||
ShowWindow(fl_xid(pWindow), SW_RESTORE); // extra map calls are harmless
|
||||
}
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::unmap() {
|
||||
ShowWindow(fl_xid(pWindow), SW_HIDE);
|
||||
}
|
||||
|
||||
#if !defined(FL_DOXYGEN) // FIXME - silence Doxygen warning
|
||||
|
||||
void Fl_WinAPI_Window_Driver::make_fullscreen(int X, int Y, int W, int H) {
|
||||
Fl_Window *w = pWindow;
|
||||
int top, bottom, left, right;
|
||||
int sx, sy, sw, sh;
|
||||
|
||||
top = fullscreen_screen_top();
|
||||
bottom = fullscreen_screen_bottom();
|
||||
left = fullscreen_screen_left();
|
||||
right = fullscreen_screen_right();
|
||||
|
||||
if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) {
|
||||
top = screen_num();
|
||||
bottom = top;
|
||||
left = top;
|
||||
right = top;
|
||||
}
|
||||
|
||||
Fl::screen_xywh(sx, sy, sw, sh, top);
|
||||
Y = sy;
|
||||
Fl::screen_xywh(sx, sy, sw, sh, bottom);
|
||||
H = sy + sh - Y;
|
||||
Fl::screen_xywh(sx, sy, sw, sh, left);
|
||||
X = sx;
|
||||
Fl::screen_xywh(sx, sy, sw, sh, right);
|
||||
W = sx + sw - X;
|
||||
|
||||
DWORD flags = GetWindowLong(fl_xid(w), GWL_STYLE);
|
||||
flags = flags & ~(WS_THICKFRAME|WS_CAPTION);
|
||||
SetWindowLong(fl_xid(w), GWL_STYLE, flags);
|
||||
|
||||
// SWP_NOSENDCHANGING is so that we can override size limits
|
||||
float s = Fl::screen_driver()->scale(screen_num());
|
||||
SetWindowPos(fl_xid(w), HWND_TOP, X*s, Y*s, W*s, H*s, SWP_NOSENDCHANGING | SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
#endif // !defined(FL_DOXYGEN) // FIXME - silence Doxygen warning
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::fullscreen_on() {
|
||||
pWindow->_set_fullscreen();
|
||||
make_fullscreen(x(), y(), w(), h());
|
||||
Fl::handle(FL_FULLSCREEN, pWindow);
|
||||
}
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::fullscreen_off(int X, int Y, int W, int H) {
|
||||
pWindow->_clear_fullscreen();
|
||||
DWORD style = GetWindowLong(fl_xid(pWindow), GWL_STYLE);
|
||||
// Remove the xid temporarily so that Fl_WinAPI_Window_Driver::fake_X_wm() behaves like it
|
||||
// does in Fl_WinAPI_Window_Driver::makeWindow().
|
||||
HWND xid = fl_xid(pWindow);
|
||||
Fl_X::i(pWindow)->xid = NULL;
|
||||
int wx, wy, bt, bx, by;
|
||||
switch (fake_X_wm(wx, wy, bt, bx, by)) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
style |= WS_CAPTION;
|
||||
break;
|
||||
case 2:
|
||||
if (border()) {
|
||||
style |= WS_THICKFRAME | WS_CAPTION;
|
||||
}
|
||||
break;
|
||||
}
|
||||
Fl_X::i(pWindow)->xid = xid;
|
||||
// compute window position and size in scaled units
|
||||
float s = Fl::screen_driver()->scale(screen_num());
|
||||
int scaledX = ceil(X*s), scaledY= ceil(Y*s), scaledW = ceil(W*s), scaledH = ceil(H*s);
|
||||
// Adjust for decorations (but not if that puts the decorations
|
||||
// outside the screen)
|
||||
if ((X != x()) || (Y != y())) {
|
||||
scaledX -= bx;
|
||||
scaledY -= by+bt;
|
||||
}
|
||||
scaledW += bx*2;
|
||||
scaledH += by*2+bt;
|
||||
SetWindowLong(fl_xid(pWindow), GWL_STYLE, style);
|
||||
SetWindowPos(fl_xid(pWindow), 0, scaledX, scaledY, scaledW, scaledH,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
Fl::handle(FL_FULLSCREEN, pWindow);
|
||||
}
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::iconize() {
|
||||
ShowWindow(fl_xid(pWindow), SW_SHOWMINNOACTIVE);
|
||||
}
|
||||
|
||||
|
||||
void Fl_WinAPI_Window_Driver::decoration_sizes(int *top, int *left, int *right, int *bottom) {
|
||||
if (size_range_set() && (maxw() != minw() || maxh() != minh())) {
|
||||
*left = *right = GetSystemMetrics(SM_CXSIZEFRAME);
|
||||
*top = *bottom = GetSystemMetrics(SM_CYSIZEFRAME);
|
||||
} else {
|
||||
*left = *right = GetSystemMetrics(SM_CXFIXEDFRAME);
|
||||
*top = *bottom = GetSystemMetrics(SM_CYFIXEDFRAME);
|
||||
}
|
||||
*top += GetSystemMetrics(SM_CYCAPTION);
|
||||
}
|
||||
|
||||
int Fl_WinAPI_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y,
|
||||
void (*draw_area)(void*, int,int,int,int), void* data)
|
||||
{
|
||||
typedef int (WINAPI* fl_GetRandomRgn_func)(HDC, HRGN, INT);
|
||||
static fl_GetRandomRgn_func fl_GetRandomRgn = 0L;
|
||||
static char first_time = 1;
|
||||
// We will have to do some Region magic now, so let's see if the
|
||||
// required function is available (and it should be starting w/Win95)
|
||||
if (first_time) {
|
||||
HMODULE hMod = GetModuleHandle("GDI32.DLL");
|
||||
if (hMod) {
|
||||
fl_GetRandomRgn = (fl_GetRandomRgn_func)GetProcAddress(hMod, "GetRandomRgn");
|
||||
}
|
||||
first_time = 0;
|
||||
}
|
||||
float s = Fl::screen_driver()->scale(screen_num());
|
||||
src_x *= s; src_y *= s; src_w *= s; src_h *= s; dest_x *= s; dest_y *= s;
|
||||
// Now check if the source scrolling area is fully visible.
|
||||
// If it is, we will do a quick scroll and just update the
|
||||
// newly exposed area. If it is not, we go the safe route and
|
||||
// re-render the full area instead.
|
||||
// Note 1: we could go and find the areas that are actually
|
||||
// obscured and recursively call fl_scroll for the newly found
|
||||
// rectangles. However, this practice would rely on the
|
||||
// elements of the undocumented Rgn structure.
|
||||
// Note 2: although this method should take care of most
|
||||
// multi-screen solutions, it will not solve issues scrolling
|
||||
// from a different resolution screen onto another.
|
||||
// Note 3: this has been tested with image maps, too.
|
||||
HDC gc = (HDC)fl_graphics_driver->gc();
|
||||
if (fl_GetRandomRgn) {
|
||||
// get the DC region minus all overlapping windows
|
||||
HRGN sys_rgn = CreateRectRgn(0, 0, 0, 0);
|
||||
fl_GetRandomRgn(gc, sys_rgn, 4);
|
||||
// now get the source scrolling rectangle
|
||||
HRGN src_rgn = CreateRectRgn(src_x, src_y, src_x+src_w, src_y+src_h);
|
||||
POINT offset = { 0, 0 };
|
||||
if (GetDCOrgEx(gc, &offset)) {
|
||||
OffsetRgn(src_rgn, offset.x, offset.y);
|
||||
}
|
||||
// see if all source pixels are available in the system region
|
||||
// Note: we could be a bit more merciful and subtract the
|
||||
// scroll destination region as well.
|
||||
HRGN dst_rgn = CreateRectRgn(0, 0, 0, 0);
|
||||
int r = CombineRgn(dst_rgn, src_rgn, sys_rgn, RGN_DIFF);
|
||||
DeleteObject(dst_rgn);
|
||||
DeleteObject(src_rgn);
|
||||
DeleteObject(sys_rgn);
|
||||
if (r != NULLREGION) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// Great, we can do an accelerated scroll instead of re-rendering
|
||||
BitBlt(gc, dest_x, dest_y, src_w, src_h, gc, src_x, src_y,SRCCOPY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Fl_WinAPI_Window_Driver::type_for_resize_window_between_screens Fl_WinAPI_Window_Driver::data_for_resize_window_between_screens_ = {0, false};
|
||||
|
||||
void Fl_WinAPI_Window_Driver::resize_after_screen_change(void *data) {
|
||||
Fl_Window *win = (Fl_Window*)data;
|
||||
RECT r;
|
||||
GetClientRect(fl_xid(win), &r);
|
||||
float old_f = float(r.right)/win->w();
|
||||
int ns = data_for_resize_window_between_screens_.screen;
|
||||
win->driver()->resize_after_scale_change(ns, old_f, Fl::screen_driver()->scale(ns));
|
||||
data_for_resize_window_between_screens_.busy = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Android_Window_Driver.cxx 12641 2018-01-31 21:17:17Z AlbrechtS $".
|
||||
//
|
52
src/drivers/Android/Fl_Font.H
Normal file
52
src/drivers/Android/Fl_Font.H
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// "$Id: Fl_Font.H 12650 2018-02-07 15:34:44Z manolo $"
|
||||
//
|
||||
// Font definitions for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2018 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// http://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please report all bugs and problems on the following page:
|
||||
//
|
||||
// http://www.fltk.org/str.php
|
||||
//
|
||||
|
||||
// Two internal fltk data structures:
|
||||
//
|
||||
// Fl_Fontdesc: an entry into the fl_font() table. There is one of these
|
||||
// for each fltk font number.
|
||||
//
|
||||
#ifndef FL_FONT_
|
||||
#define FL_FONT_
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if 0
|
||||
|
||||
class Fl_GDI_Font_Descriptor : public Fl_Font_Descriptor {
|
||||
public:
|
||||
HFONT fid;
|
||||
int *width[64];
|
||||
TEXTMETRIC metr;
|
||||
int angle;
|
||||
FL_EXPORT Fl_GDI_Font_Descriptor(const char* fontname, Fl_Fontsize size);
|
||||
# if HAVE_GL
|
||||
char glok[64];
|
||||
# endif // HAVE_GL
|
||||
FL_EXPORT ~Fl_GDI_Font_Descriptor();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
extern FL_EXPORT Fl_Fontdesc *fl_fonts; // the table
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// End of "$Id: Fl_Font.H 12650 2018-02-07 15:34:44Z manolo $".
|
||||
//
|
4853
src/drivers/Android/stb_truetype.h
Normal file
4853
src/drivers/Android/stb_truetype.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user