Remove experimental platforms Android, Pico, SDL (PR #376)
... as discussed in fltk.coredev: "FLTK 1.4.0 release schedule" https://groups.google.com/g/fltkcoredev/c/PDbHTRpXVh0/m/JqboexZ_AwAJ
This commit is contained in:
parent
b275ff0715
commit
04ccc8cc46
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -41,9 +41,6 @@ misc/update_config_scripts eol=lf
|
||||
*.rc eol=crlf
|
||||
*.bat eol=crlf
|
||||
|
||||
# Android Studio special support file (Windows .bat file)
|
||||
ide/AndroidStudio3/gradlew.rename_to_bat eol=crlf
|
||||
|
||||
# binary files
|
||||
|
||||
*.ico binary
|
||||
|
@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.fltk.@ANDROID_APP_NAME@"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:hasCode="false">
|
||||
<activity android:name="android.app.NativeActivity"
|
||||
android:label="@string/app_name">
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="test_@ANDROID_APP_NAME@" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
@ -1,60 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 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.
|
||||
#
|
||||
# Modified to be a template for Android builds in FLTK
|
||||
# Copyright 2019 Matthias Melcher and others
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
set(FLTK_DIR "@ANDROID_FLTK_DIR@")
|
||||
set(FLTK_IDE_DIR "../../../..")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
|
||||
|
||||
# FIXME: this includes the entire CMakeLists again, creating an entire library
|
||||
# build in every target
|
||||
# TODO: create separate targets for all fltk libraries that can be easily
|
||||
# linked by all app targets
|
||||
add_subdirectory("${FLTK_DIR}/" "${CMAKE_CURRENT_BINARY_DIR}/lib" EXCLUDE_FROM_ALL)
|
||||
|
||||
# run Fluid build steps for every .fl file, if any
|
||||
@ANDROID_FLUID_COMMANDS@
|
||||
# now build app's shared lib
|
||||
add_library(
|
||||
test_@ANDROID_APP_NAME@ SHARED
|
||||
@ANDROID_APP_SOURCES@)
|
||||
|
||||
target_include_directories(
|
||||
test_@ANDROID_APP_NAME@ PRIVATE
|
||||
${FLTK_DIR}/
|
||||
${FLTK_IDE_DIR}/ )
|
||||
|
||||
# Export ANativeActivity_onCreate()
|
||||
# Refer to: https://github.com/android-ndk/ndk/issues/381.
|
||||
set(CMAKE_SHARED_LINKER_FLAGS
|
||||
"${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")
|
||||
|
||||
# add lib dependencies
|
||||
# FIXME: apps may depend on additional fltk libraries; thise dependencies
|
||||
# must be created in the CREATE_ANDROID_IDE_FOR_TEST macro
|
||||
target_link_libraries(
|
||||
test_@ANDROID_APP_NAME@
|
||||
fltk
|
||||
android
|
||||
log
|
||||
m
|
||||
)
|
||||
|
@ -1,137 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "../../../test/@ANDROID_APP_NAME@.cxx"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Missing:
|
||||
- screen scale and size: most desktop apps expect to be in a draggable window
|
||||
on a larger desktop surface. For Android, there is usually no desktop, and
|
||||
screen resolution is often very high, so that a regular FLTK window would
|
||||
hide as a tiny gray spot in the top left corner
|
||||
* windows should probably be centered by default
|
||||
? the screen resolution should adapt to the first opened window
|
||||
? we should be able to hint at a prefered screen resolution
|
||||
* drawing call must scale at some point (line width!)
|
||||
* rotating the screen must call the app handler and(?) window resize
|
||||
* proportions: pixels should be square
|
||||
Need Work:
|
||||
- Fl_Android_Graphics_Driver::pie(int) needs refactoring
|
||||
- ...::line(...) has round ing issues (see rounded box type)
|
||||
- grab() not working when leaving window (adjuster...)
|
||||
- scrolling if implemented as a complete redraw. Must implement real scrolling
|
||||
- the 'hotspot' idea to position dialogs under the mouse cursor makes little sense on touch screen devices
|
||||
- fix screen when keyboard pops up in front of the text cursor or input field (temporarily shift up?)
|
||||
- ending 'message' will not quit the app right away, but wait for some timeout
|
||||
- no support for dead-key entry
|
||||
- no Shift-Tab
|
||||
|
||||
* test/CubeMain.cxx : UNSUPPORTED - needs OpenGL
|
||||
* test/CubeView.cxx : UNSUPPORTED - needs OpenGL
|
||||
* test/shape.cxx : UNSUPPORTED - needs OpenGL
|
||||
* test/cube.cxx : UNSUPPORTED - needs OpenGL
|
||||
* test/fractals.cxx : UNSUPPORTED - needs OpenGL
|
||||
* test/fracviewer.cxx : UNSUPPORTED - needs OpenGL
|
||||
* test/fullscreen.cxx : UNSUPPORTED - needs OpenGL
|
||||
* test/gl_overlay.cxx : UNSUPPORTED - needs OpenGL
|
||||
* test/glpuzzle.cxx : UNSUPPORTED - needs OpenGL
|
||||
* test/mandelbrot.cxx : UNSUPPORTED - needs Fluid
|
||||
* test/keyboard.cxx : UNSUPPORTED - needs Fluid
|
||||
* test/CubeViewUI.fl
|
||||
* test/keyboard_ui.fl
|
||||
* test/radio.fl
|
||||
* test/tree.fl
|
||||
* test/fast_slow.fl
|
||||
* test/mandelbrot_ui.fl
|
||||
* test/resize.fl
|
||||
* test/valuators.fl
|
||||
* test/inactive.fl
|
||||
* test/preferences.fl
|
||||
* test/tabs.fl
|
||||
* test/cairo_test.cxx : UNSUPPORTED - needs Cairo
|
||||
* test/tiled_image.cxx : UNSUPPORTED - X11 only
|
||||
* test/forms.cxx : UNSUPPORTED - needs Forms
|
||||
|
||||
* test/doublebuffer.cxx : FIXME - redering is completely wrong
|
||||
* test/line_style.cxx : TODO - no line styles yet
|
||||
* test/list_visuals.cxx : TODO - needs config.h
|
||||
* test/threads.cxx : TODO - needs config.h for pthreads
|
||||
* test/animated.cxx : TODO - redering errors (alpha channel?)
|
||||
* test/native-filechooser.cxx : TODO - not yet implemented
|
||||
* test/blocks.cxx : TODO - needs config.h
|
||||
* test/offscreen.cxx : TODO - not yet implemented
|
||||
* test/overlay.cxx : TODO - no overlay yet
|
||||
* test/pixmap_browser.cxx : TODO - filebrowser not yet implemented, no images, no printer
|
||||
* test/clock.cxx : TODO - no system clock call yet
|
||||
* test/resizebox.cxx : TODO - no window manager yet
|
||||
* test/rotated_text.cxx : TODO - no rotated text
|
||||
* test/subwindow.cxx : TODO - no subwindows yet
|
||||
* test/sudoku.cxx : TODO - sound support is in our way
|
||||
* test/demo.cxx : TODO - fails to open window, but is is useful at all?
|
||||
* test/device.cxx : TODO - printing support
|
||||
* test/tile.cxx : TODO - subwindow support
|
||||
* test/editor.cxx : TODO - file chooser missing
|
||||
* test/file_chooser.cxx : TODO - file chooser missing
|
||||
* test/fonts.cxx : TODO - works, but does not list system fonts or resource fonts
|
||||
* test/help_dialog.cxx : TODO - not implemented
|
||||
* test/icon.cxx : TODO - what does this do on Android?
|
||||
* test/iconize.cxx : TODO - no window manager
|
||||
* test/utf8.cxx : TODO - window manager, clipping
|
||||
* test/windowfocus.cxx : TODO - what does this do?
|
||||
* test/browser.cxx : TODO - needs text resource to load browser content
|
||||
* test/unittests.cxx : TODO - crashing, no alpha in image drawing, clipping issues
|
||||
|
||||
* test/image.cxx : + works
|
||||
* test/twowin.cxx : + works
|
||||
* test/table.cxx : + works, but window is much too large for mobile device
|
||||
* test/cursor.cxx : + works, but no cursor on Android
|
||||
* test/colbrowser.cxx : + works
|
||||
* test/checkers.cxx : + works
|
||||
* test/pixmap.cxx : + works
|
||||
* test/navigation.cxx : + works
|
||||
* test/curve.cxx : + works
|
||||
* test/input_choice.cxx : + works
|
||||
* test/input.cxx : + works
|
||||
* test/scroll.cxx : - works ok
|
||||
- some dirt when a popup draws over another menu button!?
|
||||
- on touch-screens, menuitem should be selected when released
|
||||
- on touch-screens, scroll groups should scroll on multitouch, or when not causing any other action
|
||||
* test/bitmap.cxx : + 'bitmap' works
|
||||
* test/message.cxx : - 'message' mostly works
|
||||
- when ending the app, it will not close right away but instead hang around for a few seconds
|
||||
* test/menubar.cxx : - 'menubar' mostly works including unicode
|
||||
! pressing 'button' will hang the app
|
||||
- shortcut modifiers don't work
|
||||
- right-click does not work (should this be emulated via click-and-hold?)
|
||||
* test/output.cxx : + 'output' works
|
||||
* test/ask.cxx : + 'ask' works
|
||||
* test/button.cxx : + 'button' works, including beep
|
||||
* test/pack.cxx : + 'pack' works
|
||||
* test/adjuster.cxx : + 'adjuster' works
|
||||
* test/arc.cxx : + 'arc' works as expected
|
||||
* test/minimum.cxx : + 'minimum' works
|
||||
* test/boxtype.cxx : + 'boxtype' works
|
||||
* test/buttons.cxx : + 'buttons' works
|
||||
* test/color_chooser.cxx: + 'color_chooser' works
|
||||
* test/symbols.cxx : + 'symbols' working as expected
|
||||
* test/hello.cxx : + 'hello' works fine, italics, shadow, etc.
|
||||
* test/label.cxx : + 'label' works
|
||||
|
||||
*/
|
Binary file not shown.
@ -1,26 +0,0 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
|
||||
defaultConfig {
|
||||
applicationId 'org.fltk.@ANDROID_APP_NAME@'
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 25
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments '-DANDROID_STL=c++_shared'
|
||||
}
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path 'src/main/cpp/CMakeLists.txt'
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Configuration file for the Fast Light Tool Kit (FLTK).
|
||||
*
|
||||
* Copyright 1998-2020 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:
|
||||
*
|
||||
* https://www.fltk.org/COPYING.php
|
||||
*
|
||||
* Please see the following page on how to report bugs and issues:
|
||||
*
|
||||
* https://www.fltk.org/bugs.php
|
||||
*/
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
DO NOT EDIT - This file is generated by CMake !
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
/* define FL_ABI_VERSION as 10x0y for FLTK ABI version 1.x.y */
|
||||
|
||||
/* #undef FL_ABI_VERSION */
|
Binary file not shown.
Before Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
@ -1 +0,0 @@
|
||||
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">@ANDROID_APP_NAME@</string>
|
||||
</resources>
|
Binary file not shown.
Before Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.1 KiB |
@ -1,169 +0,0 @@
|
||||
|
||||
# This module defines
|
||||
# SDL2_LIBRARY, the name of the library to link against
|
||||
# SDL2_FOUND, if false, do not try to link to SDL2
|
||||
# SDL2_INCLUDE_DIR, where to find SDL.h
|
||||
#
|
||||
# This module responds to the the flag:
|
||||
# SDL2_BUILDING_LIBRARY
|
||||
# If this is defined, then no SDL2main will be linked in because
|
||||
# only applications need main().
|
||||
# Otherwise, it is assumed you are building an application and this
|
||||
# module will attempt to locate and set the the proper link flags
|
||||
# as part of the returned SDL2_LIBRARY variable.
|
||||
#
|
||||
# Don't forget to include SDLmain.h and SDLmain.m your project for the
|
||||
# OS X framework based version. (Other versions link to -lSDL2main which
|
||||
# this module will try to find on your behalf.) Also for OS X, this
|
||||
# module will automatically add the -framework Cocoa on your behalf.
|
||||
#
|
||||
#
|
||||
# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
|
||||
# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
|
||||
# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
|
||||
# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
|
||||
# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
|
||||
# as appropriate. These values are used to generate the final SDL2_LIBRARY
|
||||
# variable, but when these values are unset, SDL2_LIBRARY does not get created.
|
||||
#
|
||||
#
|
||||
# $SDL2DIR is an environment variable that would
|
||||
# correspond to the ./configure --prefix=$SDL2DIR
|
||||
# used in building SDL2.
|
||||
# l.e.galup 9-20-02
|
||||
#
|
||||
# Modified by Eric Wing.
|
||||
# Added code to assist with automated building by using environmental variables
|
||||
# and providing a more controlled/consistent search behavior.
|
||||
# Added new modifications to recognize OS X frameworks and
|
||||
# additional Unix paths (FreeBSD, etc).
|
||||
# Also corrected the header search path to follow "proper" SDL guidelines.
|
||||
# Added a search for SDL2main which is needed by some platforms.
|
||||
# Added a search for threads which is needed by some platforms.
|
||||
# Added needed compile switches for MinGW.
|
||||
#
|
||||
# On OSX, this will prefer the Framework version (if found) over others.
|
||||
# People will have to manually change the cache values of
|
||||
# SDL2_LIBRARY to override this selection or set the CMake environment
|
||||
# CMAKE_INCLUDE_PATH to modify the search paths.
|
||||
#
|
||||
# Note that the header path has changed from SDL2/SDL.h to just SDL.h
|
||||
# This needed to change because "proper" SDL convention
|
||||
# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
|
||||
# reasons because not all systems place things in SDL2/ (see FreeBSD).
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2003-2009 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
message("<FindSDL2.cmake>")
|
||||
|
||||
SET(SDL2_SEARCH_PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local
|
||||
/usr
|
||||
/sw # Fink
|
||||
/opt/local # DarwinPorts
|
||||
/opt/csw # Blastwave
|
||||
/opt
|
||||
${SDL2_PATH}
|
||||
)
|
||||
|
||||
FIND_PATH(SDL2_INCLUDE_DIR SDL.h
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES include/SDL2 include
|
||||
PATHS ${SDL2_SEARCH_PATHS}
|
||||
)
|
||||
|
||||
FIND_LIBRARY(SDL2_LIBRARY_TEMP
|
||||
NAMES SDL2
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${SDL2_SEARCH_PATHS}
|
||||
)
|
||||
|
||||
IF(NOT SDL2_BUILDING_LIBRARY)
|
||||
IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||
# Non-OS X framework versions expect you to also dynamically link to
|
||||
# SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
|
||||
# seem to provide SDL2main for compatibility even though they don't
|
||||
# necessarily need it.
|
||||
FIND_LIBRARY(SDL2MAIN_LIBRARY
|
||||
NAMES SDL2main
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS ${SDL2_SEARCH_PATHS}
|
||||
)
|
||||
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||
ENDIF(NOT SDL2_BUILDING_LIBRARY)
|
||||
|
||||
# SDL2 may require threads on your system.
|
||||
# The Apple build may not need an explicit flag because one of the
|
||||
# frameworks may already provide it.
|
||||
# But for non-OSX systems, I will use the CMake Threads package.
|
||||
IF(NOT APPLE)
|
||||
FIND_PACKAGE(Threads)
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
# MinGW needs an additional library, mwindows
|
||||
# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows
|
||||
# (Actually on second look, I think it only needs one of the m* libraries.)
|
||||
IF(MINGW)
|
||||
SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
|
||||
ENDIF(MINGW)
|
||||
|
||||
IF(SDL2_LIBRARY_TEMP)
|
||||
# For SDL2main
|
||||
IF(NOT SDL2_BUILDING_LIBRARY)
|
||||
IF(SDL2MAIN_LIBRARY)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
|
||||
ENDIF(SDL2MAIN_LIBRARY)
|
||||
ENDIF(NOT SDL2_BUILDING_LIBRARY)
|
||||
|
||||
# For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
|
||||
# CMake doesn't display the -framework Cocoa string in the UI even
|
||||
# though it actually is there if I modify a pre-used variable.
|
||||
# I think it has something to do with the CACHE STRING.
|
||||
# So I use a temporary variable until the end so I can set the
|
||||
# "real" variable in one-shot.
|
||||
IF(APPLE)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
|
||||
ENDIF(APPLE)
|
||||
|
||||
# For threads, as mentioned Apple doesn't need this.
|
||||
# In fact, there seems to be a problem if I used the Threads package
|
||||
# and try using this line, so I'm just skipping it entirely for OS X.
|
||||
IF(NOT APPLE)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
# For MinGW library
|
||||
IF(MINGW)
|
||||
SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
|
||||
ENDIF(MINGW)
|
||||
|
||||
# Set the final string here so the GUI reflects the final state.
|
||||
SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
|
||||
# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
|
||||
SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
|
||||
ENDIF(SDL2_LIBRARY_TEMP)
|
||||
|
||||
message("</FindSDL2.cmake>")
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
||||
|
@ -1,141 +0,0 @@
|
||||
#
|
||||
# android.cmake to build the FLTK AndroidStudio project using CMake
|
||||
# Written by Matthias Melcher
|
||||
#
|
||||
# Copyright 1998-2019 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:
|
||||
#
|
||||
# https://www.fltk.org/COPYING.php
|
||||
#
|
||||
# Please see the following page on how to report bugs and issues:
|
||||
#
|
||||
# https://www.fltk.org/bugs.php
|
||||
#
|
||||
|
||||
# all target modules will be added here later
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/CMake/Android/settings.gradle.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/AndroidStudio/settings.gradle"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
# configuration file for all modules
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/CMake/Android/build.gradle.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/AndroidStudio/build.gradle"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
# create a custom abi file for this setup
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/fl_config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/AndroidStudio/FL/fl_config.h"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
# TODO: where should we create config.h?
|
||||
|
||||
macro(CREATE_ANDROID_IDE_FOR_TEST NAME SOURCES LIBRARIES)
|
||||
|
||||
# message(STATUS "Creating Android IDE for ${NAME}")
|
||||
|
||||
set (ANDROID_APP_NAME ${NAME})
|
||||
set (ANDROID_FLTK_DIR ${CMAKE_SOURCE_DIR})
|
||||
|
||||
set (srcs)
|
||||
set (ANDROID_APP_SOURCES)
|
||||
set (ANDROID_FLUID_COMMANDS)
|
||||
set (flsrcs) # fluid source files
|
||||
foreach(src ${SOURCES})
|
||||
if ("${src}" MATCHES "\\.fl$")
|
||||
list(APPEND flsrcs ${src})
|
||||
string(REGEX REPLACE "(.*).fl" \\1 basename ${src})
|
||||
string(APPEND ANDROID_FLUID_COMMANDS
|
||||
"add_custom_command(\n"
|
||||
" OUTPUT \"\${FLTK_DIR}/test/${basename}.cxx\" \"\${FLTK_DIR}/test/${basename}.h\"\n"
|
||||
" COMMAND fluid -c \"${src}\"\n"
|
||||
" WORKING_DIRECTORY \"\${FLTK_DIR}/test\"\n"
|
||||
" DEPENDS \"\${FLTK_DIR}/test/${src}\"\n"
|
||||
" MAIN_DEPENDENCY \"\${FLTK_DIR}/test/${src}\"\n"
|
||||
")\n\n"
|
||||
)
|
||||
file(TOUCH "${basename}.cxx")
|
||||
file(TOUCH "${basename}.h")
|
||||
file(TOUCH "${basename}.fl")
|
||||
set(src_cxx ${basename}.cxx)
|
||||
else ()
|
||||
list(APPEND srcs ${src})
|
||||
set(src_cxx ${src})
|
||||
endif ("${src}" MATCHES "\\.fl$")
|
||||
string(APPEND ANDROID_APP_SOURCES " \"\${FLTK_DIR}/test/${src_cxx}\"\n")
|
||||
endforeach(src)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/CMake/Android/app.build.gradle.in"
|
||||
"${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/build.gradle"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/CMake/Android/AndroidManifest.xml.in"
|
||||
"${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/AndroidManifest.xml"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/CMake/Android/Roboto-Regular.ttf"
|
||||
"${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/assets/fonts/Roboto-Regular.ttf"
|
||||
COPYONLY
|
||||
)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/CMake/Android/mdpi.ic_launcher.png"
|
||||
"${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/res/mipmap-mdpi/ic_launcher.png"
|
||||
COPYONLY
|
||||
)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/CMake/Android/hdpi.ic_launcher.png"
|
||||
"${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/res/mipmap-hdpi/ic_launcher.png"
|
||||
COPYONLY
|
||||
)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/CMake/Android/xhdpi.ic_launcher.png"
|
||||
"${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/res/mipmap-xhdpi/ic_launcher.png"
|
||||
COPYONLY
|
||||
)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/CMake/Android/xxhdpi.ic_launcher.png"
|
||||
"${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/res/mipmap-xxhdpi/ic_launcher.png"
|
||||
COPYONLY
|
||||
)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/CMake/Android/strings.xml.in"
|
||||
"${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/res/values/strings.xml"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
configure_file(
|
||||
"${CMAKE_SOURCE_DIR}/CMake/Android/CMakeList.txt.in"
|
||||
"${CMAKE_BINARY_DIR}/AndroidStudio/${ANDROID_APP_NAME}/src/main/cpp/CMakeLists.txt"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
file(APPEND "${CMAKE_BINARY_DIR}/AndroidStudio/settings.gradle" "include ':${ANDROID_APP_NAME}'\n")
|
||||
|
||||
endmacro(CREATE_ANDROID_IDE_FOR_TEST NAME SOURCES LIBRARIES)
|
||||
|
||||
|
||||
macro(CREATE_ANDROID_IDE_WRAPUP)
|
||||
|
||||
# message(STATUS "Wrapping up Android IDE creation")
|
||||
|
||||
endmacro(CREATE_ANDROID_IDE_WRAPUP)
|
||||
|
||||
|
@ -46,8 +46,7 @@
|
||||
# quotes if more than one library is required, e.g. "fltk_gl;fltk"
|
||||
#
|
||||
# CREATE_EXAMPLE can have an optional fourth argument with a list of options
|
||||
# - the option ANDROID_OK is set if CREATE_EXAMPLE creates code for Android
|
||||
# builds in addition to the native build
|
||||
# - these options are currently not used
|
||||
#
|
||||
################################################################################
|
||||
|
||||
@ -62,11 +61,11 @@ macro (CREATE_EXAMPLE NAME SOURCES LIBRARIES)
|
||||
|
||||
# create macOS bundle? 0 = no, 1 = yes
|
||||
|
||||
if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
if (APPLE AND (NOT OPTION_APPLE_X11))
|
||||
set (MAC_BUNDLE 1)
|
||||
else ()
|
||||
set (MAC_BUNDLE 0)
|
||||
endif (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
endif (APPLE AND (NOT OPTION_APPLE_X11))
|
||||
|
||||
# rename target name "help" (reserved since CMake 2.8.12)
|
||||
# FIXME: not necessary in FLTK 1.4 but left for compatibility (06/2020)
|
||||
@ -164,15 +163,17 @@ macro (CREATE_EXAMPLE NAME SOURCES LIBRARIES)
|
||||
endif (MAC_BUNDLE)
|
||||
|
||||
######################################################################
|
||||
# Parse optional fourth argument "ANDROID_OK", see description above.
|
||||
# Parse optional fourth argument, see description above.
|
||||
######################################################################
|
||||
|
||||
if (${ARGC} GREATER 3)
|
||||
foreach (OPTION ${ARGV3})
|
||||
if (${OPTION} STREQUAL "ANDROID_OK" AND OPTION_CREATE_ANDROID_STUDIO_IDE)
|
||||
CREATE_ANDROID_IDE_FOR_TEST (${NAME} ${SOURCES} ${LIBRARIES})
|
||||
endif ()
|
||||
endforeach ()
|
||||
endif ()
|
||||
# code left commented out as an example
|
||||
|
||||
# *unused* # if (${ARGC} GREATER 3)
|
||||
# *unused* # foreach (OPTION ${ARGV3})
|
||||
# *unused* # if (${OPTION} STREQUAL "xxx")
|
||||
# *unused* # # do something ...
|
||||
# *unused* # endif ()
|
||||
# *unused* # endforeach ()
|
||||
# *unused* # endif ()
|
||||
|
||||
endmacro (CREATE_EXAMPLE NAME SOURCES LIBRARIES)
|
||||
|
@ -65,7 +65,6 @@ endif (WIN32)
|
||||
#######################################################################
|
||||
if (APPLE)
|
||||
option (OPTION_APPLE_X11 "use X11" OFF)
|
||||
option (OPTION_APPLE_SDL "use SDL" OFF)
|
||||
if (CMAKE_OSX_SYSROOT)
|
||||
list (APPEND FLTK_CFLAGS "-isysroot ${CMAKE_OSX_SYSROOT}")
|
||||
endif (CMAKE_OSX_SYSROOT)
|
||||
@ -100,14 +99,6 @@ if (OPTION_APPLE_X11)
|
||||
endif (X11_INCLUDE_DIR)
|
||||
endif (OPTION_APPLE_X11)
|
||||
|
||||
if (OPTION_APPLE_SDL)
|
||||
find_package (SDL2 REQUIRED)
|
||||
if (SDL2_FOUND)
|
||||
set (USE_SDL 1)
|
||||
list (APPEND FLTK_LDLIBS SDL2_LIBRARY)
|
||||
endif (SDL2_FOUND)
|
||||
endif (OPTION_APPLE_SDL)
|
||||
|
||||
#######################################################################
|
||||
option (OPTION_USE_POLL "use poll if available" OFF)
|
||||
mark_as_advanced (OPTION_USE_POLL)
|
||||
@ -238,8 +229,6 @@ if (OPTION_USE_GL)
|
||||
set (OPENGL_LIBRARIES -L${PATH_TO_XLIBS} -lGLU -lGL)
|
||||
unset(HAVE_GL_GLU_H CACHE)
|
||||
find_file (HAVE_GL_GLU_H GL/glu.h PATHS ${X11_INCLUDE_DIR})
|
||||
elseif (OPTION_APPLE_SDL)
|
||||
set (OPENGL_FOUND FALSE)
|
||||
else()
|
||||
include (FindOpenGL)
|
||||
if (APPLE)
|
||||
@ -618,10 +607,6 @@ else ()
|
||||
endif (OPTION_USE_KDIALOG)
|
||||
#######################################################################
|
||||
|
||||
#######################################################################
|
||||
option (OPTION_CREATE_ANDROID_STUDIO_IDE "create files needed to compile FLTK for Android" OFF)
|
||||
#######################################################################
|
||||
|
||||
#######################################################################
|
||||
option (CMAKE_SUPPRESS_REGENERATION "suppress rules to re-run CMake on rebuild" OFF)
|
||||
mark_as_advanced (CMAKE_SUPPRESS_REGENERATION)
|
||||
|
@ -89,9 +89,6 @@ if (APPLE)
|
||||
if (NOT(${CMAKE_SYSTEM_VERSION} VERSION_LESS 17.0.0)) # a.k.a. macOS version ≥ 10.13
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_LIBCPP_HAS_THREAD_API_PTHREAD")
|
||||
endif (NOT(${CMAKE_SYSTEM_VERSION} VERSION_LESS 17.0.0))
|
||||
elseif (OPTION_APPLE_SDL)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SDL2_INCLUDE_DIRS} -U__APPLE__")
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SDL2_INCLUDE_DIRS} -U__APPLE__")
|
||||
else ()
|
||||
set (__APPLE_QUARTZ__ 1)
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework Cocoa")
|
||||
|
@ -41,8 +41,6 @@ endif (DEBUG_VARIABLES_CMAKE)
|
||||
|
||||
if (WIN32)
|
||||
list (APPEND FLTK_LDLIBS -lole32 -luuid -lcomctl32 -lws2_32)
|
||||
elseif (APPLE AND OPTION_APPLE_SDL)
|
||||
# FIXME: do nothing?
|
||||
elseif (APPLE AND NOT OPTION_APPLE_X11)
|
||||
list (APPEND FLTK_LDLIBS "-framework Cocoa")
|
||||
else ()
|
||||
|
@ -80,13 +80,6 @@ include (CMake/resources.cmake)
|
||||
#######################################################################
|
||||
include (CMake/options.cmake)
|
||||
|
||||
#######################################################################
|
||||
# Android Studio setup
|
||||
#######################################################################
|
||||
if (OPTION_CREATE_ANDROID_STUDIO_IDE)
|
||||
include (CMake/android.cmake)
|
||||
endif (OPTION_CREATE_ANDROID_STUDIO_IDE)
|
||||
|
||||
#######################################################################
|
||||
# print (debug) several build variables and options
|
||||
#######################################################################
|
||||
@ -102,7 +95,6 @@ if (debug_build)
|
||||
fl_debug_var (MSVC)
|
||||
fl_debug_var (UNIX)
|
||||
fl_debug_var (APPLE)
|
||||
fl_debug_var (ANDROID)
|
||||
fl_debug_var (CMAKE_BUILD_TYPE)
|
||||
fl_debug_var (CMAKE_SIZEOF_VOID_P)
|
||||
fl_debug_var (OPTION_OPTIM)
|
||||
@ -124,9 +116,7 @@ add_subdirectory(src)
|
||||
# build fluid
|
||||
#######################################################################
|
||||
|
||||
if (NOT ANDROID)
|
||||
add_subdirectory(fluid)
|
||||
endif()
|
||||
|
||||
#######################################################################
|
||||
# variables shared by export and install
|
||||
@ -159,13 +149,6 @@ if (FLTK_BUILD_EXAMPLES)
|
||||
add_subdirectory (examples)
|
||||
endif (FLTK_BUILD_EXAMPLES)
|
||||
|
||||
#######################################################################
|
||||
# Android Studio wrapup
|
||||
#######################################################################
|
||||
if (OPTION_CREATE_ANDROID_STUDIO_IDE)
|
||||
CREATE_ANDROID_IDE_WRAPUP()
|
||||
endif (OPTION_CREATE_ANDROID_STUDIO_IDE)
|
||||
|
||||
#######################################################################
|
||||
# installation
|
||||
#######################################################################
|
||||
|
159
FL/android.H
159
FL/android.H
@ -1,159 +0,0 @@
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.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
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
This is the function that application code must implement, representing
|
||||
the main entry to the app.
|
||||
*/
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
These events are specific to the Android OS driver system. They can
|
||||
be read by adding a callback via Fl::add_system_handler() and reading Fl::event()
|
||||
Don't change the order of these enums! See Fl_Android_Application.H .
|
||||
*/
|
||||
enum Fl_Android_Platform_Event
|
||||
{
|
||||
FL_ANDROID_EVENTS = 0x00010000,
|
||||
|
||||
/**
|
||||
* Command from main thread: the AInputQueue has changed. Upon processing
|
||||
* this command, android_app->inputQueue will be updated to the new queue
|
||||
* (or NULL).
|
||||
*/
|
||||
FL_ANDROID_EVENT_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.
|
||||
*/
|
||||
FL_ANDROID_EVENT_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.
|
||||
*/
|
||||
FL_ANDROID_EVENT_TERM_WINDOW,
|
||||
|
||||
/**
|
||||
* Command from main thread: the current ANativeWindow has been resized.
|
||||
* Please redraw with its new size.
|
||||
*/
|
||||
FL_ANDROID_EVENT_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.
|
||||
*/
|
||||
FL_ANDROID_EVENT_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.
|
||||
*/
|
||||
FL_ANDROID_EVENT_CONTENT_RECT_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity window has gained
|
||||
* input focus.
|
||||
*/
|
||||
FL_ANDROID_EVENT_GAINED_FOCUS,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity window has lost
|
||||
* input focus.
|
||||
*/
|
||||
FL_ANDROID_EVENT_LOST_FOCUS,
|
||||
|
||||
/**
|
||||
* Command from main thread: the current device configuration has changed.
|
||||
*/
|
||||
FL_ANDROID_EVENT_CONFIG_CHANGED,
|
||||
|
||||
/**
|
||||
* Command from main thread: the system is running low on memory.
|
||||
* Try to reduce your memory use.
|
||||
*/
|
||||
FL_ANDROID_EVENT_LOW_MEMORY,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been started.
|
||||
*/
|
||||
FL_ANDROID_EVENT_START,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been resumed.
|
||||
*/
|
||||
FL_ANDROID_EVENT_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.
|
||||
*/
|
||||
FL_ANDROID_EVENT_SAVE_STATE,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been paused.
|
||||
*/
|
||||
FL_ANDROID_EVENT_PAUSE,
|
||||
|
||||
/**
|
||||
* Command from main thread: the app's activity has been stopped.
|
||||
*/
|
||||
FL_ANDROID_EVENT_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.
|
||||
*/
|
||||
FL_ANDROID_EVENT_DESTROY
|
||||
};
|
@ -37,8 +37,6 @@ class Fl_Window;
|
||||
# include "win32.H"
|
||||
# elif defined(__APPLE__)
|
||||
# include "mac.H"
|
||||
# elif defined(__ANDROID__)
|
||||
# include "android.H"
|
||||
# elif defined(FLTK_USE_X11)
|
||||
# include "x11.H"
|
||||
# endif // _WIN32
|
||||
|
@ -72,12 +72,6 @@ typedef opaque GLContext; /**< an OpenGL graphics context, into which all OpenGL
|
||||
typedef intptr_t fl_intptr_t;
|
||||
typedef uintptr_t fl_uintptr_t;
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
|
||||
#include <sys/stat.h>
|
||||
typedef intptr_t fl_intptr_t;
|
||||
typedef uintptr_t fl_uintptr_t;
|
||||
|
||||
#else /* ! _WIN64 */
|
||||
|
||||
typedef long fl_intptr_t;
|
||||
@ -122,22 +116,6 @@ typedef struct HGLRC__ *GLContext;
|
||||
struct dirent {char d_name[1];};
|
||||
#endif
|
||||
|
||||
#elif defined(__ANDROID__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
typedef class Fl_Rect_Region *Fl_Region;
|
||||
#else
|
||||
typedef struct Fl_Rect_Region *Fl_Region;
|
||||
#endif
|
||||
|
||||
// TODO: the types below have not yet been ported
|
||||
typedef unsigned long Fl_Offscreen;
|
||||
typedef unsigned long Fl_Bitmask;
|
||||
typedef int FL_SOCKET;
|
||||
typedef struct __GLXcontextRec *GLContext;
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#elif defined(FLTK_USE_X11)
|
||||
|
||||
typedef unsigned long Fl_Offscreen;
|
||||
|
@ -1,80 +0,0 @@
|
||||
README.Android.md
|
||||
|
||||
# Building and Running FLTK with Android Studio 3
|
||||
|
||||
|
||||
WARNING: FLTK FOR ANDROID IS WORK IN PROGRESS IN A PRETTY EARLY STAGE.
|
||||
|
||||
|
||||
## Contents
|
||||
|
||||
1. Building FLTK with Android Studio 3
|
||||
2. Extensions and limitation of FLTK on Android
|
||||
3. Document History
|
||||
|
||||
|
||||
## Building FLTK with Android Studio 3
|
||||
|
||||
There is no need to ever write a single line of Java.
|
||||
|
||||
Download and install AndroidStudio on your developer machine. If you use
|
||||
AndroidStudio for the first time, use the IDE to download and build the
|
||||
"Native Plasm" sample app. In the process, all resources required to build
|
||||
FLTK will be installed. Once Native Plasm runs on your emulator or physical
|
||||
device, you are ready to install FLTK.
|
||||
|
||||
Build FLTK for your native platform first using CMake. AndroidStudio will need a native
|
||||
version of the user interface design tool _Fluid_.
|
||||
|
||||
The following example is for the _Xcode_ IDE on _macOS_. The same should work for
|
||||
other IDEs and Makefiles on other platforms that run _AndroidStudio_.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/fltk/fltk.git fltk-1.4.git
|
||||
cd fltk-1.4.git
|
||||
mkdir build
|
||||
cd build
|
||||
mkdir Xcode
|
||||
cd Xcode
|
||||
cmake -G "Unix Makefiles" \
|
||||
-D OPTION_USE_SYSTEM_LIBJPEG=Off \
|
||||
-D OPTION_USE_SYSTEM_ZLIB=Off \
|
||||
-D OPTION_USE_SYSTEM_LIBPNG=Off \
|
||||
-D OPTION_CREATE_ANDROID_STUDIO_IDE=On \
|
||||
../..
|
||||
```
|
||||
Note the last option, `-D OPTION_CREATE_ANDROID_STUDIO_IDE=On`. This option will
|
||||
create the file needed to create an FLTK demo project in
|
||||
`fltk-1.4.git/build/Xcode/AndroidStudio`.
|
||||
|
||||
- open the `build/Xcode/AndroidStudio/` directory as a project in AndroidStudio3
|
||||
|
||||
- click "run"; the project should compile and run out of the box
|
||||
|
||||
|
||||
## Extensions and limitation of FLTK on Android
|
||||
|
||||
Android support for FLTK is in an early stage. As of January 2019, most
|
||||
rendering works, fonts work, bitmaps and pixmaps work, clipping works, window
|
||||
layering works, and mouse clicks and keyboard events are handled
|
||||
|
||||
When loading fonts:
|
||||
- font names starting with a $ will have the system font path inserted
|
||||
- font names starting with an @ will be loaded via the Asset Manager
|
||||
- all other names will be used verbatim
|
||||
|
||||
Limitations:
|
||||
- the screen size is currently fixed to 600x800 and is scaled up
|
||||
- many many big and little functions are not yet implemented
|
||||
|
||||
|
||||
## Document History
|
||||
|
||||
Jan 15 2019 - matt: rewrote document to explain the new CMake process
|
||||
Mar 29 2018 - matt: many graphics functions have been implemented, keyboard
|
||||
Mar 17 2018 - matt: added Android extensions for fonts
|
||||
Mar 12 2018 - matt: started list of limitation that serevs as information to the
|
||||
user as much as a todo list for core developers
|
||||
Mar 6 2018 - matt: moved project to ide/AndroidStudio3/
|
||||
Mar 2 2018 - matt: rewriting Android port and documentation from scratch
|
||||
Feb 9 2016 - matt: recreated document with more warnings and active support
|
@ -3,10 +3,10 @@
|
||||
-----------------------------------------
|
||||
|
||||
Since FLTK 1.4 we do no longer include IDE [1] solution files in our
|
||||
source distribution. [2]
|
||||
source distribution.
|
||||
|
||||
If you want to build the FLTK library with an IDE you need to use
|
||||
CMake [3] to generate the IDE files from the source distribution.
|
||||
CMake [2] to generate the IDE files from the source distribution.
|
||||
|
||||
The FLTK team will officially support generation of selected IDE projects,
|
||||
particularly Visual C++ and Xcode. Older version support of these IDE
|
||||
@ -45,8 +45,4 @@ Note: "Not supported" doesn't mean that a particular generator does not work,
|
||||
for instance Visual Studio, Xcode, Eclipse, ...
|
||||
https://en.wikipedia.org/wiki/Integrated_development_environment
|
||||
|
||||
[2] The only exception is the Android Studio IDE in ide/AndroidStudio3
|
||||
currently provided for testing. This IDE solution is likely to be
|
||||
moved elsewhere or removed entirely before FLTK 1.4 will be released.
|
||||
|
||||
[3] https://cmake.org/
|
||||
[2] https://cmake.org/
|
||||
|
@ -1,72 +0,0 @@
|
||||
This documentation will explain how to quickly port FLTK to a new
|
||||
platform using the Pico driver system. For now, only the sample
|
||||
SDL Pico driver on macOS compiles and barely runs.
|
||||
|
||||
> mkdir build
|
||||
> cd build
|
||||
> mkdir XcodeSDL
|
||||
> cd XcodeSDL
|
||||
> cmake -G Xcode -D OPTION_APPLE_SDL=ON ../..
|
||||
|
||||
tl;dr - the recent commit should be transparent to all developers on
|
||||
other platforms. On macOS, the CMake setup adds 'OPTION_APPLE_SDL=ON'
|
||||
that will run FLTK on top of SDL, which in turn runs on top of the
|
||||
new "Pico" driver set.
|
||||
|
||||
The greatest help I can get from the core developers is to continue
|
||||
to refactor the platform specific functionalities into the drivers.
|
||||
|
||||
---
|
||||
|
||||
OK, long version. I know that I am repeating myself and I don't expect
|
||||
those of you who "got it" weeks ago to read this again. Writing this
|
||||
down is also for me to avoid losing track ;-)
|
||||
|
||||
Goal 1: find all the stuff that must still go into drivers
|
||||
Goal 2: have a base driver for all future porting efforts
|
||||
Goal 3: make porting fun with early gratification to the coder
|
||||
Goal 4: extensively document a sample port (SDL), and how to improve it
|
||||
Goal 5: use SDL as a base library, thereby porting FLTK to iOS and Android
|
||||
|
||||
|
||||
This is the start of a new driver, named "Pico". "Pico" is here to
|
||||
implement what I called the minimal driver.
|
||||
|
||||
"Pico" implements (eventually) a complete set of drivers. The drivers
|
||||
will be limited in functionality, but they will be good enough to
|
||||
allow basic UI's with most FLTK widget types.
|
||||
|
||||
If "Pico" compiles without any "USE_PICO" or similar defines, we
|
||||
have reached goal 1.
|
||||
|
||||
"Pico" will implement all driver functionalities "in good faith",
|
||||
meaning, in a way that FLTK runs without crashing. Only very very
|
||||
basic functions are not implemented. A driver that derives from "Pico"
|
||||
needs only to implement those missing functions, thereby reaching goals
|
||||
2 and 3. As far as I can tell, those will be:
|
||||
|
||||
- open a single fixed size window
|
||||
- setting a pixel in a color inside that window
|
||||
- polling and waiting for PUSH and RELEASE events and their positions
|
||||
|
||||
By implementing these three simple functions in the SDL driver,
|
||||
"test/hello" and quite a bunch of other tests will run (yes, they
|
||||
will be slow, but the will work).
|
||||
|
||||
This will give the person who is porting FLTK to their platform a
|
||||
very early confirmation that their build setup is working and a
|
||||
very early gratification, reaching goal 3.
|
||||
|
||||
Obviously, SDL is much more powerful, and by the nature of the
|
||||
virtual functions in the driver system, we can incrementally add
|
||||
functionality to the SDL driver, and document this incremental
|
||||
nature, reaching goal 4.
|
||||
|
||||
If we do all this right, we have goal 5.
|
||||
|
||||
If SDL is too big or complex for, say, Android, we can simply start
|
||||
a new native Android driver set by implementing the three functions
|
||||
mentioned above, and then go from there.
|
||||
|
||||
|
||||
- Matthias
|
29
README.experimental.txt
Normal file
29
README.experimental.txt
Normal file
@ -0,0 +1,29 @@
|
||||
Removed Experimental Platforms
|
||||
------------------------------
|
||||
|
||||
Removed platforms and drivers include:
|
||||
|
||||
- Android
|
||||
- Pico
|
||||
- PicoAndroid
|
||||
- PicoSDL
|
||||
|
||||
These platforms and their drivers were experimental and undocumented.
|
||||
|
||||
They have been removed in January 2022 for maintenance reasons as
|
||||
discussed in fltk.coredev: "FLTK 1.4.0 release schedule", see:
|
||||
https://groups.google.com/g/fltkcoredev/c/PDbHTRpXVh0/m/JqboexZ_AwAJ
|
||||
|
||||
More information, for instance where to find further development
|
||||
(if any) will be added in this file.
|
||||
|
||||
If you want to take a look at the removed drivers you can checkout
|
||||
the git tag "experimental-2022-01":
|
||||
|
||||
$ git clone https://github.com/fltk/fltk.git fltk-experimental
|
||||
$ cd fltk-experimental
|
||||
$ git checkout experimental-2022-01
|
||||
|
||||
You can also browse the files on GitHub:
|
||||
|
||||
https://github.com/fltk/fltk/tree/b275ff07158e80d1744ddb2f6c51094a87cf079a
|
@ -157,15 +157,6 @@
|
||||
|
||||
#cmakedefine __APPLE_QUARTZ__ 1
|
||||
|
||||
/*
|
||||
* USE_SDL
|
||||
*
|
||||
* Should we use SDL for the current platform
|
||||
*
|
||||
*/
|
||||
|
||||
#cmakedefine USE_SDL 1
|
||||
|
||||
/*
|
||||
* HAVE_GL_OVERLAY:
|
||||
*
|
||||
|
10
configh.in
10
configh.in
@ -156,16 +156,6 @@
|
||||
|
||||
#undef __APPLE_QUARTZ__
|
||||
|
||||
/*
|
||||
* USE_SDL
|
||||
*
|
||||
* Should we use SDL for the current platform
|
||||
* *FIXME* USE_SDL not yet implemented in configure !
|
||||
*
|
||||
*/
|
||||
|
||||
#undef USE_SDL
|
||||
|
||||
/*
|
||||
* HAVE_GL_OVERLAY:
|
||||
*
|
||||
|
@ -146,7 +146,7 @@ endforeach (src)
|
||||
|
||||
# Note: macOS does not need libGLEW
|
||||
|
||||
if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
if (APPLE AND (NOT OPTION_APPLE_X11))
|
||||
if (NOT LIB_GLEW)
|
||||
set (LIB_GLEW TRUE)
|
||||
endif ()
|
||||
|
@ -84,7 +84,7 @@ endif (WIN32)
|
||||
|
||||
source_group("Header Files" FILES ${HEADERFILES})
|
||||
|
||||
if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
if (APPLE AND (NOT OPTION_APPLE_X11))
|
||||
set (ICON_NAME fluid.icns)
|
||||
set (ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_NAME}")
|
||||
add_executable (fluid MACOSX_BUNDLE ${CPPFILES} ${HEADERFILES} ${ICON_PATH})
|
||||
@ -104,7 +104,7 @@ if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
|
||||
else ()
|
||||
add_executable (fluid WIN32 ${CPPFILES} ${HEADERFILES})
|
||||
endif (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
endif (APPLE AND (NOT OPTION_APPLE_X11))
|
||||
|
||||
target_link_libraries (fluid fltk fltk_images)
|
||||
|
||||
@ -123,7 +123,7 @@ endif (USE_GDIPLUS)
|
||||
|
||||
# install fluid
|
||||
|
||||
if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
if (APPLE AND (NOT OPTION_APPLE_X11))
|
||||
|
||||
# On macOS, Fluid must be installed twice. The bundled version of Fluid needs
|
||||
# to go into the /Applications folder to make it visible as a user App with
|
||||
@ -149,7 +149,7 @@ else()
|
||||
LIBRARY DESTINATION ${FLTK_LIBDIR}
|
||||
ARCHIVE DESTINATION ${FLTK_LIBDIR}
|
||||
)
|
||||
endif (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
endif (APPLE AND (NOT OPTION_APPLE_X11))
|
||||
|
||||
# install desktop files
|
||||
|
||||
|
@ -178,7 +178,7 @@ list (APPEND HEADER_FILES
|
||||
|
||||
set (GL_HEADER_FILES) # FIXME: not (yet?) defined
|
||||
|
||||
if ((FLTK_USE_X11 OR USE_SDL) AND NOT OPTION_PRINT_SUPPORT)
|
||||
if (FLTK_USE_X11 AND NOT OPTION_PRINT_SUPPORT)
|
||||
set (PSFILES
|
||||
)
|
||||
else ()
|
||||
@ -186,7 +186,7 @@ else ()
|
||||
drivers/PostScript/Fl_PostScript.cxx
|
||||
drivers/PostScript/Fl_PostScript_image.cxx
|
||||
)
|
||||
endif ((FLTK_USE_X11 OR USE_SDL) AND NOT OPTION_PRINT_SUPPORT)
|
||||
endif (FLTK_USE_X11 AND NOT OPTION_PRINT_SUPPORT)
|
||||
|
||||
set (DRIVER_FILES)
|
||||
|
||||
@ -241,35 +241,6 @@ if (FLTK_USE_X11)
|
||||
drivers/Xlib/Fl_Font.H
|
||||
)
|
||||
|
||||
elseif (USE_SDL)
|
||||
|
||||
# SDL2
|
||||
|
||||
set (DRIVER_FILES
|
||||
drivers/Pico/Fl_Pico_System_Driver.cxx
|
||||
drivers/Pico/Fl_Pico_Screen_Driver.cxx
|
||||
drivers/Pico/Fl_Pico_Window_Driver.cxx
|
||||
drivers/Pico/Fl_Pico_Graphics_Driver.cxx
|
||||
drivers/Pico/Fl_Pico_Copy_Surface.cxx
|
||||
drivers/Pico/Fl_Pico_Image_Surface.cxx
|
||||
drivers/PicoSDL/Fl_PicoSDL_System_Driver.cxx
|
||||
drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.cxx
|
||||
drivers/PicoSDL/Fl_PicoSDL_Window_Driver.cxx
|
||||
drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.cxx
|
||||
drivers/PicoSDL/Fl_PicoSDL_Copy_Surface.cxx
|
||||
drivers/PicoSDL/Fl_PicoSDL_Image_Surface.cxx
|
||||
)
|
||||
set (DRIVER_HEADER_FILES
|
||||
drivers/Pico/Fl_Pico_System_Driver.H
|
||||
drivers/Pico/Fl_Pico_Screen_Driver.H
|
||||
drivers/Pico/Fl_Pico_Window_Driver.H
|
||||
drivers/Pico/Fl_Pico_Graphics_Driver.H
|
||||
drivers/PicoSDL/Fl_PicoSDL_System_Driver.H
|
||||
drivers/PicoSDL/Fl_PicoSDL_Screen_Driver.H
|
||||
drivers/PicoSDL/Fl_PicoSDL_Window_Driver.H
|
||||
drivers/PicoSDL/Fl_PicoSDL_Graphics_Driver.H
|
||||
)
|
||||
|
||||
elseif (APPLE)
|
||||
|
||||
# Apple Quartz
|
||||
@ -302,34 +273,6 @@ elseif (APPLE)
|
||||
drivers/Quartz/Fl_Font.H
|
||||
)
|
||||
|
||||
elseif (ANDROID)
|
||||
|
||||
# Android
|
||||
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
|
||||
set (DRIVER_FILES
|
||||
drivers/Android/Fl_Android_Application.cxx
|
||||
drivers/Android/Fl_Android_System_Driver.cxx
|
||||
drivers/Android/Fl_Android_Screen_Driver.cxx
|
||||
drivers/Android/Fl_Android_Screen_Keyboard.cxx
|
||||
drivers/Android/Fl_Android_Window_Driver.cxx
|
||||
drivers/Android/Fl_Android_Image_Surface_Driver.cxx
|
||||
drivers/Android/Fl_Android_Graphics_Driver.cxx
|
||||
drivers/Android/Fl_Android_Graphics_Clipping.cxx
|
||||
drivers/Android/Fl_Android_Graphics_Font.cxx
|
||||
)
|
||||
set (DRIVER_HEADER_FILES
|
||||
drivers/Android/Fl_Android_Application.H
|
||||
drivers/Android/Fl_Android_System_Driver.H
|
||||
drivers/Android/Fl_Android_Screen_Driver.H
|
||||
drivers/Android/Fl_Android_Window_Driver.H
|
||||
drivers/Android/Fl_Android_Graphics_Driver.H
|
||||
drivers/Android/Fl_Android_Graphics_Clipping.H
|
||||
drivers/Android/Fl_Android_Graphics_Font.H
|
||||
)
|
||||
|
||||
|
||||
else ()
|
||||
|
||||
# Windows (GDI)
|
||||
@ -473,7 +416,7 @@ if (WIN32)
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
if (APPLE AND (NOT OPTION_APPLE_X11))
|
||||
set (MMFILES
|
||||
Fl_cocoa.mm
|
||||
drivers/Cocoa/Fl_Cocoa_Printer_Driver.mm
|
||||
@ -483,7 +426,7 @@ if (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
else()
|
||||
set (MMFILES
|
||||
)
|
||||
endif (APPLE AND (NOT OPTION_APPLE_X11) AND (NOT OPTION_APPLE_SDL))
|
||||
endif (APPLE AND (NOT OPTION_APPLE_X11))
|
||||
|
||||
|
||||
#######################################################################
|
||||
@ -519,10 +462,6 @@ if (FLTK_USE_X11)
|
||||
list (APPEND OPTIONAL_LIBS ${X11_LIBRARIES})
|
||||
endif (FLTK_USE_X11)
|
||||
|
||||
if (USE_SDL)
|
||||
list (APPEND OPTIONAL_LIBS ${SDL2_LIBRARY})
|
||||
endif (USE_SDL)
|
||||
|
||||
if (WIN32)
|
||||
list (APPEND OPTIONAL_LIBS comctl32 ws2_32)
|
||||
endif (WIN32)
|
||||
|
@ -50,7 +50,7 @@
|
||||
|
|
||||
+- Fl_PostScript_Graphics_Driver: platform-independent graphics driver for PostScript drawing
|
||||
+- Fl_SVG_Graphics_Driver: platform-independent graphics driver for Scalable Vector Graphics drawing
|
||||
+- Fl_..._Graphics_Driver: platform-specific graphics driver (MacOS, Android, Pico)
|
||||
+- Fl_..._Graphics_Driver: platform-specific graphics driver (MacOS)
|
||||
+- Fl_Quartz_Printer_Graphics_Driver: MacOS-specific, for drawing to printers
|
||||
+- Fl_Scalable_Graphics_Driver: helper class to support GUI scaling
|
||||
+- Fl_Xlib_Graphics_Driver: X11-specific graphics driver
|
||||
|
@ -43,7 +43,7 @@ const int Fl_System_Driver::fl_YNegative = 0x0020;
|
||||
// and/or use their own table. It is defined here "static" and assigned
|
||||
// in the constructor to avoid static initialization race conditions.
|
||||
//
|
||||
// As of June 2018 these platforms are Windows and Android. X11 does not
|
||||
// As of January 2022 the only platform is Windows. X11 does not
|
||||
// use a key table at all.
|
||||
// Platforms that use their own key tables must assign them in their
|
||||
// constructors (which overwrites the pointer and size).
|
||||
|
@ -1,270 +0,0 @@
|
||||
//
|
||||
// Android Native Application interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_Android_Application.H
|
||||
\brief Definition of Android Native Application interface
|
||||
*/
|
||||
|
||||
#ifndef FL_ANDROID_APPLICATION_H
|
||||
#define FL_ANDROID_APPLICATION_H
|
||||
|
||||
#include <FL/Fl.H>
|
||||
|
||||
extern void (*fl_unlock_function)();
|
||||
extern void (*fl_lock_function)();
|
||||
|
||||
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include <android/configuration.h>
|
||||
#include <android/looper.h>
|
||||
#include <android/native_activity.h>
|
||||
|
||||
|
||||
/**
|
||||
A class to make Java calls from C++ easier.
|
||||
*/
|
||||
class Fl_Android_Java
|
||||
{
|
||||
JavaVM *pJavaVM = nullptr;
|
||||
JNIEnv *pJNIEnv = nullptr;
|
||||
jobject pNativeActivity;
|
||||
jclass pNativeActivityClass;
|
||||
bool pAttached = false;
|
||||
|
||||
public:
|
||||
Fl_Android_Java();
|
||||
~Fl_Android_Java();
|
||||
bool is_attached() { return pAttached; }
|
||||
JavaVM *VM() { return pJavaVM; }
|
||||
JNIEnv *env() { return pJNIEnv; }
|
||||
jobject native_ativity() { return pNativeActivity; }
|
||||
jclass native_activity_class() { return pNativeActivityClass; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Static class that manages all interaction between the Android Native Activity
|
||||
and the FLTK library. It also keeps often used data for global access.
|
||||
|
||||
On launch, it creates a main thread and communication pipe to
|
||||
the Activity. All FLTK code will run in that thread. Activity
|
||||
events will be polled by the Screen driver using the provided
|
||||
Android Looper, and will also be routed back to this class as needed.
|
||||
|
||||
This code is based on the native activity interface
|
||||
provided by <android/native_activity.h>. It is based on a set
|
||||
of application-provided callbacks that will be called
|
||||
by the Activity's main thread when certain events occur.
|
||||
|
||||
1/ The application must provide a function named "int main(argc, argv)" that
|
||||
will be called when the activity is created, in a new thread that is
|
||||
distinct from the activity's main thread.
|
||||
|
||||
2/ The application has access to a static "Fl_Android_Application" class
|
||||
that contains references to other important objects, e.g. the
|
||||
ANativeActivity object instance the application is running in.
|
||||
|
||||
3/ the "Fl_Android_Application" class 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.
|
||||
|
||||
FLTK will add more items to the looper for timers and file and socket
|
||||
communication. (fl_add_timeout, Fl::add_fd(), ...
|
||||
*/
|
||||
class Fl_Android_Application
|
||||
{
|
||||
public:
|
||||
|
||||
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,
|
||||
|
||||
/**
|
||||
* Timer data ID of all timer events coming from the Unix timer_create()
|
||||
* and friends, used in fl_add_timeout() and colleagues.
|
||||
*/
|
||||
LOOPER_ID_TIMER,
|
||||
|
||||
/**
|
||||
* Start of user-defined ALooper identifiers.
|
||||
*/
|
||||
LOOPER_ID_USER,
|
||||
};
|
||||
|
||||
/**
|
||||
* @see android.H Fl_Android_Platform_Event
|
||||
*/
|
||||
enum {
|
||||
APP_CMD_INPUT_CHANGED,
|
||||
APP_CMD_INIT_WINDOW,
|
||||
APP_CMD_TERM_WINDOW,
|
||||
APP_CMD_WINDOW_RESIZED,
|
||||
APP_CMD_WINDOW_REDRAW_NEEDED,
|
||||
APP_CMD_CONTENT_RECT_CHANGED,
|
||||
APP_CMD_GAINED_FOCUS,
|
||||
APP_CMD_LOST_FOCUS,
|
||||
APP_CMD_CONFIG_CHANGED,
|
||||
APP_CMD_LOW_MEMORY,
|
||||
APP_CMD_START,
|
||||
APP_CMD_RESUME,
|
||||
APP_CMD_SAVE_STATE,
|
||||
APP_CMD_PAUSE,
|
||||
APP_CMD_STOP,
|
||||
APP_CMD_DESTROY,
|
||||
};
|
||||
|
||||
public:
|
||||
// --- logging
|
||||
static void log_e(const char *text, ...);
|
||||
static void log_w(const char *text, ...);
|
||||
static void log_i(const char *text, ...);
|
||||
static void log_v(const char *text, ...);
|
||||
|
||||
// --- application state stuff
|
||||
static int8_t read_cmd();
|
||||
static void pre_exec_cmd(int8_t cmd);
|
||||
static void post_exec_cmd(int8_t cmd);
|
||||
static int destroy_requested() { return pDestroyRequested; }
|
||||
static const char *get_internal_data_path() { return pActivity->internalDataPath; }
|
||||
static const char *get_external_data_path() { return pActivity->externalDataPath; }
|
||||
static AAssetManager *get_asset_manager() { return pActivity->assetManager; }
|
||||
static ANativeActivity *get_activity() { return pActivity; }
|
||||
|
||||
// --- event handling
|
||||
static AInputQueue *input_event_queue() { return pInputQueue; }
|
||||
|
||||
// --- screen stuff
|
||||
static bool copy_screen();
|
||||
static inline ANativeWindow *native_window() { return pNativeWindow; }
|
||||
static inline ANativeWindow_Buffer &graphics_buffer() { return pApplicationWindowBuffer; }
|
||||
|
||||
// --- timer stuff
|
||||
static void send_timer_index(uint8_t ix);
|
||||
static uint8_t receive_timer_index();
|
||||
|
||||
|
||||
protected:
|
||||
static void free_saved_state();
|
||||
static void print_cur_config();
|
||||
static void destroy();
|
||||
static void* thread_entry(void* param);
|
||||
|
||||
// --- screen handling stuff
|
||||
static void allocate_screen();
|
||||
static bool lock_screen();
|
||||
static void unlock_and_post_screen();
|
||||
static bool screen_is_locked();
|
||||
|
||||
// --- timer stuff
|
||||
static void create_timer_handler();
|
||||
static void destroy_timer_handler();
|
||||
|
||||
static ANativeActivity *pActivity;
|
||||
static AConfiguration *pConfig;
|
||||
static void *pSavedState;
|
||||
static size_t pSavedStateSize;
|
||||
static ALooper *pAppLooper;
|
||||
static AInputQueue *pInputQueue;
|
||||
static ANativeWindow *pNativeWindow;
|
||||
static ANativeWindow_Buffer pNativeWindowBuffer;
|
||||
static ANativeWindow_Buffer pApplicationWindowBuffer;
|
||||
static int pActivityState;
|
||||
static int pDestroyRequested;
|
||||
|
||||
// ---- no need to make these visible to the outside ----
|
||||
static pthread_mutex_t pMutex;
|
||||
static pthread_cond_t pCond;
|
||||
static int pMsgReadPipe;
|
||||
static int pMsgWritePipe;
|
||||
static pthread_t pThread;
|
||||
static int pRunning;
|
||||
static int pStateSaved;
|
||||
static int pDestroyed;
|
||||
static AInputQueue* pPendingInputQueue;
|
||||
static ANativeWindow* pPendingWindow;
|
||||
|
||||
// --- timer variables
|
||||
static int pTimerReadPipe;
|
||||
static int pTimerWritePipe;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Fl_Android_Activity : public Fl_Android_Application
|
||||
{
|
||||
public:
|
||||
static void create(ANativeActivity* activity, void* savedState, size_t savedStateSize);
|
||||
|
||||
private:
|
||||
static void set_activity(ANativeActivity *a) { pActivity = a; }
|
||||
static void set_callbacks();
|
||||
|
||||
// ---- Android Native Activity interface
|
||||
static void write_cmd(int8_t cmd);
|
||||
static void set_input(AInputQueue* inputQueue);
|
||||
static void set_window(ANativeWindow* window);
|
||||
static void set_activity_state(int8_t cmd);
|
||||
static void close_activity();
|
||||
|
||||
// ---- Android Native Activity callbacks ----
|
||||
static void onContentRectChanged(ANativeActivity *activity, const ARect *rect);
|
||||
static void onNativeWindowRedrawNeeded(ANativeActivity *activity, ANativeWindow *window);
|
||||
static void onNativeWindowResized(ANativeActivity *activity, ANativeWindow *window);
|
||||
static void onDestroy(ANativeActivity* activity);
|
||||
static void onStart(ANativeActivity* activity);
|
||||
static void onResume(ANativeActivity* activity);
|
||||
static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen);
|
||||
static void onPause(ANativeActivity* activity);
|
||||
static void onStop(ANativeActivity* activity);
|
||||
static void onConfigurationChanged(ANativeActivity* activity);
|
||||
static void onLowMemory(ANativeActivity* activity);
|
||||
static void onWindowFocusChanged(ANativeActivity* activity, int focused);
|
||||
static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window);
|
||||
static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window);
|
||||
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue);
|
||||
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue);
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_ANDROID_APPLICATION_H
|
@ -1,843 +0,0 @@
|
||||
//
|
||||
// Android Native Application interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_Android_Application.H
|
||||
\brief Definition of Android Native Application interface
|
||||
*/
|
||||
|
||||
#include "Fl_Android_Application.H"
|
||||
#include "Fl_Android_Window_Driver.H"
|
||||
|
||||
#include <FL/platform.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/fl_string_functions.h>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
|
||||
void fl_set_status(int x, int y, int w, int h) {}
|
||||
|
||||
static const char *LOG_TAG = "FLTK";
|
||||
|
||||
|
||||
// The ANativeActivity object instance that this app is running in.
|
||||
ANativeActivity *Fl_Android_Application::pActivity = 0L;
|
||||
|
||||
// The current configuration the app is running in.
|
||||
AConfiguration* Fl_Android_Application::pConfig = 0L;
|
||||
|
||||
// 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* Fl_Android_Application::pSavedState = 0;
|
||||
size_t Fl_Android_Application::pSavedStateSize = 0;
|
||||
|
||||
// The ALooper associated with the app's thread.
|
||||
ALooper* Fl_Android_Application::pAppLooper = 0;
|
||||
|
||||
// When non-NULL, this is the input queue from which the app will
|
||||
// receive user input events.
|
||||
AInputQueue* Fl_Android_Application::pInputQueue = 0;
|
||||
|
||||
// When non-NULL, this is the window surface that the app can draw in.
|
||||
ANativeWindow* Fl_Android_Application::pNativeWindow = 0;
|
||||
|
||||
// Use this buffer for direct drawing access
|
||||
ANativeWindow_Buffer Fl_Android_Application::pNativeWindowBuffer = { 0 };
|
||||
ANativeWindow_Buffer Fl_Android_Application::pApplicationWindowBuffer = { 0 };
|
||||
|
||||
// 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 Fl_Android_Application::pActivityState = 0;
|
||||
|
||||
// This is non-zero when the application's NativeActivity is being
|
||||
// destroyed and waiting for the app thread to complete.
|
||||
int Fl_Android_Application::pDestroyRequested = 0;
|
||||
|
||||
pthread_mutex_t Fl_Android_Application::pMutex = { 0 };
|
||||
pthread_cond_t Fl_Android_Application::pCond = { 0 };
|
||||
int Fl_Android_Application::pMsgReadPipe = 0;
|
||||
int Fl_Android_Application::pMsgWritePipe = 0;
|
||||
pthread_t Fl_Android_Application::pThread = 0;
|
||||
int Fl_Android_Application::pRunning = 0;
|
||||
int Fl_Android_Application::pStateSaved = 0;
|
||||
int Fl_Android_Application::pDestroyed = 0;
|
||||
//int Fl_Android_Application::pRedrawNeeded = 0;
|
||||
AInputQueue *Fl_Android_Application::pPendingInputQueue = 0;
|
||||
ANativeWindow *Fl_Android_Application::pPendingWindow = 0;
|
||||
//ARect Fl_Android_Application::pPendingContentRect = { 0 };
|
||||
|
||||
int Fl_Android_Application::pTimerReadPipe = -1;
|
||||
int Fl_Android_Application::pTimerWritePipe = -1;
|
||||
|
||||
|
||||
|
||||
void Fl_Android_Application::log_e(const char *text, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, text);
|
||||
__android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, text, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Application::log_w(const char *text, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, text);
|
||||
__android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, text, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Application::log_i(const char *text, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, text);
|
||||
__android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, text, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Application::log_v(const char *text, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
va_list args;
|
||||
va_start (args, text);
|
||||
__android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, text, args);
|
||||
va_end (args);
|
||||
#else
|
||||
text = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Application::free_saved_state()
|
||||
{
|
||||
pthread_mutex_lock(&pMutex);
|
||||
if (pSavedState != NULL) {
|
||||
free(pSavedState);
|
||||
pSavedState = NULL;
|
||||
pSavedStateSize = 0;
|
||||
}
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
|
||||
app command message.
|
||||
*/
|
||||
int8_t Fl_Android_Application::read_cmd()
|
||||
{
|
||||
int8_t cmd;
|
||||
if (read(pMsgReadPipe, &cmd, sizeof(cmd)) == sizeof(cmd)) {
|
||||
switch (cmd) {
|
||||
case APP_CMD_SAVE_STATE:
|
||||
free_saved_state();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return cmd;
|
||||
} else {
|
||||
log_e("No data on command pipe!");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Application::print_cur_config()
|
||||
{
|
||||
char lang[2], country[2];
|
||||
AConfiguration_getLanguage(pConfig, lang);
|
||||
AConfiguration_getCountry(pConfig, country);
|
||||
|
||||
log_v("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
|
||||
"keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
|
||||
"modetype=%d modenight=%d",
|
||||
AConfiguration_getMcc(pConfig),
|
||||
AConfiguration_getMnc(pConfig),
|
||||
lang[0], lang[1], country[0], country[1],
|
||||
AConfiguration_getOrientation(pConfig),
|
||||
AConfiguration_getTouchscreen(pConfig),
|
||||
AConfiguration_getDensity(pConfig),
|
||||
AConfiguration_getKeyboard(pConfig),
|
||||
AConfiguration_getNavigation(pConfig),
|
||||
AConfiguration_getKeysHidden(pConfig),
|
||||
AConfiguration_getNavHidden(pConfig),
|
||||
AConfiguration_getSdkVersion(pConfig),
|
||||
AConfiguration_getScreenSize(pConfig),
|
||||
AConfiguration_getScreenLong(pConfig),
|
||||
AConfiguration_getUiModeType(pConfig),
|
||||
AConfiguration_getUiModeNight(pConfig));
|
||||
}
|
||||
|
||||
/**
|
||||
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 Fl_Android_Application::pre_exec_cmd(int8_t cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case APP_CMD_INPUT_CHANGED:
|
||||
log_v("APP_CMD_INPUT_CHANGED\n");
|
||||
pthread_mutex_lock(&pMutex);
|
||||
if (pInputQueue != NULL) {
|
||||
AInputQueue_detachLooper(pInputQueue);
|
||||
}
|
||||
pInputQueue = pPendingInputQueue;
|
||||
if (pInputQueue != NULL) {
|
||||
log_v("Attaching input queue to looper");
|
||||
AInputQueue_attachLooper(pInputQueue, pAppLooper, LOOPER_ID_INPUT, NULL, NULL);
|
||||
}
|
||||
pthread_cond_broadcast(&pCond);
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
log_v("APP_CMD_INIT_WINDOW\n");
|
||||
// tell the main thread that we received the window handle
|
||||
pthread_mutex_lock(&pMutex);
|
||||
pNativeWindow = pPendingWindow;
|
||||
pthread_cond_broadcast(&pCond);
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
// change the format of the buffers to match our needs
|
||||
// FIXME: current default screen size and format is 600x800xRGB565
|
||||
ANativeWindow_setBuffersGeometry(pNativeWindow,
|
||||
600,
|
||||
800,
|
||||
WINDOW_FORMAT_RGB_565);
|
||||
// tell FLTK that the buffer is available now
|
||||
Fl_Android_Window_Driver::expose_all();
|
||||
break;
|
||||
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
log_v("APP_CMD_TERM_WINDOW\n");
|
||||
pthread_cond_broadcast(&pCond);
|
||||
break;
|
||||
|
||||
case APP_CMD_RESUME:
|
||||
case APP_CMD_START:
|
||||
case APP_CMD_PAUSE:
|
||||
case APP_CMD_STOP:
|
||||
log_v("activityState=%d\n", cmd);
|
||||
pthread_mutex_lock(&pMutex);
|
||||
pActivityState = cmd;
|
||||
pthread_cond_broadcast(&pCond);
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_CONFIG_CHANGED:
|
||||
log_v("APP_CMD_CONFIG_CHANGED\n");
|
||||
AConfiguration_fromAssetManager(pConfig,
|
||||
pActivity->assetManager);
|
||||
print_cur_config();
|
||||
break;
|
||||
|
||||
case APP_CMD_DESTROY:
|
||||
log_v("APP_CMD_DESTROY\n");
|
||||
pDestroyRequested = 1;
|
||||
Fl::program_should_quit(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Call with the command returned by 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 Fl_Android_Application::post_exec_cmd(int8_t cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
log_v("APP_CMD_TERM_WINDOW\n");
|
||||
pthread_mutex_lock(&pMutex);
|
||||
pNativeWindow = NULL;
|
||||
pthread_cond_broadcast(&pCond);
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_SAVE_STATE:
|
||||
log_v("APP_CMD_SAVE_STATE\n");
|
||||
pthread_mutex_lock(&pMutex);
|
||||
pStateSaved = 1;
|
||||
pthread_cond_broadcast(&pCond);
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_RESUME:
|
||||
free_saved_state();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Application::create_timer_handler()
|
||||
{
|
||||
int msgpipe[2];
|
||||
if (::pipe(msgpipe)) {
|
||||
log_e("could not create timer pipe: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
pTimerReadPipe = msgpipe[0];
|
||||
pTimerWritePipe = msgpipe[1];
|
||||
ALooper_addFd(pAppLooper, pTimerReadPipe, LOOPER_ID_TIMER, ALOOPER_EVENT_INPUT, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Application::destroy_timer_handler()
|
||||
{
|
||||
ALooper_removeFd(pAppLooper, pTimerReadPipe);
|
||||
::close(pTimerWritePipe);
|
||||
::close(pTimerReadPipe);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Application::send_timer_index(uint8_t ix)
|
||||
{
|
||||
if (pTimerWritePipe!=-1)
|
||||
::write(pTimerWritePipe, &ix, 1);
|
||||
}
|
||||
|
||||
|
||||
uint8_t Fl_Android_Application::receive_timer_index()
|
||||
{
|
||||
uint8_t ix = 0;
|
||||
if (pTimerReadPipe!=-1)
|
||||
::read(pTimerReadPipe, &ix, 1);
|
||||
return ix;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Application::destroy()
|
||||
{
|
||||
log_v("android_app_destroy!");
|
||||
free_saved_state();
|
||||
pthread_mutex_lock(&pMutex);
|
||||
if (pInputQueue != NULL) {
|
||||
AInputQueue_detachLooper(pInputQueue);
|
||||
}
|
||||
destroy_timer_handler();
|
||||
AConfiguration_delete(pConfig);
|
||||
pDestroyed = 1;
|
||||
pthread_cond_broadcast(&pCond);
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
// Can't touch android_app object after this.
|
||||
}
|
||||
|
||||
|
||||
void *Fl_Android_Application::thread_entry(void* param)
|
||||
{
|
||||
pConfig = AConfiguration_new();
|
||||
AConfiguration_fromAssetManager(pConfig, pActivity->assetManager);
|
||||
|
||||
print_cur_config();
|
||||
|
||||
pAppLooper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
||||
ALooper_addFd(pAppLooper, pMsgReadPipe, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, NULL);
|
||||
|
||||
create_timer_handler();
|
||||
|
||||
pthread_mutex_lock(&pMutex);
|
||||
pRunning = 1;
|
||||
pthread_cond_broadcast(&pCond);
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
|
||||
char *argv[] = { fl_strdup(pActivity->obbPath), 0 };
|
||||
main(1, argv);
|
||||
|
||||
destroy();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Allocate memory for our internal screen buffer.
|
||||
|
||||
FIXME: everything is currently hardcoded to an 600x800 resolution
|
||||
TODO: react to screen changes
|
||||
*/
|
||||
void Fl_Android_Application::allocate_screen()
|
||||
{
|
||||
pApplicationWindowBuffer.bits = calloc(600*800, 2); // one uint16_t per pixel
|
||||
pApplicationWindowBuffer.width = 600;
|
||||
pApplicationWindowBuffer.height = 800;
|
||||
pApplicationWindowBuffer.stride = 600;
|
||||
pApplicationWindowBuffer.format = WINDOW_FORMAT_RGB_565;
|
||||
}
|
||||
|
||||
|
||||
bool Fl_Android_Application::copy_screen()
|
||||
{
|
||||
bool ret = false;
|
||||
if (lock_screen()) {
|
||||
|
||||
#if 0
|
||||
// screen activity viewer
|
||||
static int i = 0;
|
||||
fl_color( (i&1) ? FL_RED : FL_GREEN);
|
||||
fl_rectf(i*10, 600+i*10, 50, 50);
|
||||
i++;
|
||||
if (i>10) i = 0;
|
||||
#endif
|
||||
|
||||
// TODO: there are endless possibilities to optimize the following code
|
||||
// We are wasting time by copying the entire screen contents at every dirty frame
|
||||
// We can identify previously written buffers and copy only those pixels
|
||||
// that actually changed.
|
||||
const uint16_t *src = (uint16_t*)pApplicationWindowBuffer.bits;
|
||||
int srcStride = pApplicationWindowBuffer.stride;
|
||||
int ww = pApplicationWindowBuffer.width;
|
||||
int hh = pApplicationWindowBuffer.height;
|
||||
|
||||
uint16_t *dst = (uint16_t*)pNativeWindowBuffer.bits;
|
||||
int dstStride = pNativeWindowBuffer.stride;
|
||||
if (pNativeWindowBuffer.width<ww) ww = pNativeWindowBuffer.width;
|
||||
if (pNativeWindowBuffer.height<ww) ww = pNativeWindowBuffer.height;
|
||||
|
||||
for (int row=hh; row>0; --row) {
|
||||
memcpy(dst, src, size_t(ww * 2));
|
||||
src += srcStride;
|
||||
dst += dstStride;
|
||||
}
|
||||
|
||||
unlock_and_post_screen();
|
||||
ret = true;
|
||||
} else {
|
||||
// wait for screen buffer to be created
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
Take ownership of screen memory for gaining write access.
|
||||
|
||||
If the screen is already locked, it will not be locked again
|
||||
and a value of true will be returned.
|
||||
|
||||
\return true if we gaines access, false if no access was granted and screen memory must not be writte to
|
||||
*/
|
||||
bool Fl_Android_Application::lock_screen()
|
||||
{
|
||||
if (screen_is_locked())
|
||||
return true;
|
||||
|
||||
if (!pNativeWindow) {
|
||||
log_w("Unable to lock window buffer: no native window found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ANativeWindow_lock(pNativeWindow, &pNativeWindowBuffer, 0L) < 0) {
|
||||
log_w("Unable to lock window buffer: Android won't lock.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Release screen memory ownership and give it back to the system.
|
||||
|
||||
The memory content will be copied to the physical screen next.
|
||||
If the screen is not locked, this call will have no effect.
|
||||
*/
|
||||
void Fl_Android_Application::unlock_and_post_screen()
|
||||
{
|
||||
if (!screen_is_locked())
|
||||
return;
|
||||
|
||||
ANativeWindow_unlockAndPost(pNativeWindow);
|
||||
pNativeWindowBuffer.bits = 0L; // avoid any misunderstandings...
|
||||
}
|
||||
|
||||
/**
|
||||
Is the screen currently locked?
|
||||
\return true if it is locked and the app has write access.
|
||||
*/
|
||||
bool Fl_Android_Application::screen_is_locked()
|
||||
{
|
||||
return (pNativeWindowBuffer.bits!=0L);
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Native activity interaction (called from main thread)
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
void Fl_Android_Activity::write_cmd(int8_t cmd)
|
||||
{
|
||||
if (write(pMsgWritePipe, &cmd, sizeof(cmd)) != sizeof(cmd)) {
|
||||
log_e("Failure writing android_app cmd: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Activity::set_input(AInputQueue* inputQueue)
|
||||
{
|
||||
pthread_mutex_lock(&pMutex);
|
||||
pPendingInputQueue = inputQueue;
|
||||
write_cmd(APP_CMD_INPUT_CHANGED);
|
||||
while (pInputQueue != pPendingInputQueue) {
|
||||
pthread_cond_wait(&pCond, &pMutex);
|
||||
}
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Activity::set_window(ANativeWindow* window)
|
||||
{
|
||||
pthread_mutex_lock(&pMutex);
|
||||
if (pPendingWindow != NULL) {
|
||||
write_cmd(APP_CMD_TERM_WINDOW);
|
||||
}
|
||||
pPendingWindow = window;
|
||||
if (window != NULL) {
|
||||
write_cmd(APP_CMD_INIT_WINDOW);
|
||||
}
|
||||
while (pNativeWindow != pPendingWindow) {
|
||||
pthread_cond_wait(&pCond, &pMutex);
|
||||
}
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Activity::set_activity_state(int8_t cmd)
|
||||
{
|
||||
pthread_mutex_lock(&pMutex);
|
||||
write_cmd(cmd);
|
||||
while (pActivityState != cmd) {
|
||||
pthread_cond_wait(&pCond, &pMutex);
|
||||
}
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Activity::close_activity()
|
||||
{
|
||||
pthread_mutex_lock(&pMutex);
|
||||
write_cmd(APP_CMD_DESTROY);
|
||||
while (!pDestroyed) {
|
||||
pthread_cond_wait(&pCond, &pMutex);
|
||||
}
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
|
||||
close(pMsgReadPipe);
|
||||
close(pMsgWritePipe);
|
||||
pthread_cond_destroy(&pCond);
|
||||
pthread_mutex_destroy(&pMutex);
|
||||
}
|
||||
|
||||
|
||||
// ---- Android Native Activity callbacks ----
|
||||
|
||||
/**
|
||||
The rectangle in the window in which content should be placed has changed.
|
||||
*/
|
||||
void Fl_Android_Activity::onContentRectChanged(ANativeActivity *activity, const ARect *rect)
|
||||
{
|
||||
// TODO: implement me
|
||||
}
|
||||
|
||||
/**
|
||||
The drawing window for this native activity needs to be redrawn. To avoid transient artifacts during screen changes (such resizing after rotation), applications should not return from this function until they have finished drawing their window in its current state.
|
||||
*/
|
||||
void Fl_Android_Activity::onNativeWindowRedrawNeeded(ANativeActivity *activity, ANativeWindow *window)
|
||||
{
|
||||
// TODO: implement me
|
||||
}
|
||||
|
||||
/**
|
||||
The drawing window for this native activity has been resized. You should retrieve the new size from the window and ensure that your rendering in it now matches.
|
||||
*/
|
||||
void Fl_Android_Activity::onNativeWindowResized(ANativeActivity *activity, ANativeWindow *window)
|
||||
{
|
||||
// TODO: implement me
|
||||
}
|
||||
|
||||
/**
|
||||
NativeActivity is being destroyed. See Java documentation for Activity.onDestroy() for more information.
|
||||
*/
|
||||
void Fl_Android_Activity::onDestroy(ANativeActivity* activity)
|
||||
{
|
||||
log_v("Destroy: %p\n", activity);
|
||||
// FIXME: use the correct free()
|
||||
close_activity();
|
||||
}
|
||||
|
||||
/**
|
||||
NativeActivity has started. See Java documentation for Activity.onStart() for more information.
|
||||
*/
|
||||
void Fl_Android_Activity::onStart(ANativeActivity* activity)
|
||||
{
|
||||
log_v("Start: %p\n", activity);
|
||||
set_activity_state(APP_CMD_START);
|
||||
}
|
||||
|
||||
/**
|
||||
NativeActivity has resumed. See Java documentation for Activity.onResume() for more information.
|
||||
*/
|
||||
void Fl_Android_Activity::onResume(ANativeActivity* activity)
|
||||
{
|
||||
log_v("Resume: %p\n", activity);
|
||||
set_activity_state(APP_CMD_RESUME);
|
||||
}
|
||||
|
||||
/**
|
||||
Framework is asking NativeActivity to save its current instance state. See Java documentation for Activity.onSaveInstanceState() for more information. The returned pointer needs to be created with malloc(); the framework will call free() on it for you. You also must fill in outSize with the number of bytes in the allocation. Note that the saved state will be persisted, so it can not contain any active entities (pointers to memory, file descriptors, etc).
|
||||
*/
|
||||
void *Fl_Android_Activity::onSaveInstanceState(ANativeActivity* activity, size_t* outLen)
|
||||
{
|
||||
struct android_app* android_app = (struct android_app*)activity->instance;
|
||||
void* savedState = NULL;
|
||||
|
||||
log_v("SaveInstanceState: %p\n", activity);
|
||||
pthread_mutex_lock(&pMutex);
|
||||
pStateSaved = 0;
|
||||
write_cmd(APP_CMD_SAVE_STATE);
|
||||
while (!pStateSaved) {
|
||||
pthread_cond_wait(&pCond, &pMutex);
|
||||
}
|
||||
|
||||
if (pSavedState != NULL) {
|
||||
savedState = pSavedState;
|
||||
*outLen = pSavedStateSize;
|
||||
pSavedState = NULL;
|
||||
pSavedStateSize = 0;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
|
||||
return savedState;
|
||||
}
|
||||
|
||||
/**
|
||||
NativeActivity has paused. See Java documentation for Activity.onPause() for more information.
|
||||
*/
|
||||
void Fl_Android_Activity::onPause(ANativeActivity* activity)
|
||||
{
|
||||
log_v("Pause: %p\n", activity);
|
||||
set_activity_state(APP_CMD_PAUSE);
|
||||
}
|
||||
|
||||
/**
|
||||
NativeActivity has stopped. See Java documentation for Activity.onStop() for more information.
|
||||
*/
|
||||
void Fl_Android_Activity::onStop(ANativeActivity* activity)
|
||||
{
|
||||
log_v("Stop: %p\n", activity);
|
||||
set_activity_state(APP_CMD_STOP);
|
||||
}
|
||||
|
||||
/**
|
||||
The current device AConfiguration has changed. The new configuration can be retrieved from assetManager.
|
||||
*/
|
||||
void Fl_Android_Activity::onConfigurationChanged(ANativeActivity* activity)
|
||||
{
|
||||
struct android_app* android_app = (struct android_app*)activity->instance;
|
||||
log_v("ConfigurationChanged: %p\n", activity);
|
||||
write_cmd(APP_CMD_CONFIG_CHANGED);
|
||||
}
|
||||
|
||||
/**
|
||||
The system is running low on memory. Use this callback to release resources you do not need, to help the system avoid killing more important processes.
|
||||
*/
|
||||
void Fl_Android_Activity::onLowMemory(ANativeActivity* activity)
|
||||
{
|
||||
struct android_app* android_app = (struct android_app*)activity->instance;
|
||||
log_v("LowMemory: %p\n", activity);
|
||||
write_cmd(APP_CMD_LOW_MEMORY);
|
||||
}
|
||||
|
||||
/**
|
||||
Focus has changed in this NativeActivity's window. This is often used, for example, to pause a game when it loses input focus.
|
||||
*/
|
||||
void Fl_Android_Activity::onWindowFocusChanged(ANativeActivity* activity, int focused)
|
||||
{
|
||||
log_v("WindowFocusChanged: %p -- %d\n", activity, focused);
|
||||
write_cmd(focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
|
||||
}
|
||||
|
||||
/**
|
||||
The drawing window for this native activity has been created. You can use the given native window object to start drawing.
|
||||
*/
|
||||
void Fl_Android_Activity::onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window)
|
||||
{
|
||||
log_v("NativeWindowCreated: %p -- %p\n", activity, window);
|
||||
set_window(window);
|
||||
}
|
||||
|
||||
/**
|
||||
The drawing window for this native activity is going to be destroyed. You MUST ensure that you do not touch the window object after returning from this function: in the common case of drawing to the window from another thread, that means the implementation of this callback must properly synchronize with the other thread to stop its drawing before returning from here.
|
||||
*/
|
||||
void Fl_Android_Activity::onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window)
|
||||
{
|
||||
log_v("NativeWindowDestroyed: %p -- %p\n", activity, window);
|
||||
set_window(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
The input queue for this native activity's window has been created. You can use the given input queue to start retrieving input events.
|
||||
*/
|
||||
void Fl_Android_Activity::onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
|
||||
{
|
||||
log_v("InputQueueCreated: %p -- %p\n", activity, queue);
|
||||
set_input(queue);
|
||||
}
|
||||
|
||||
/**
|
||||
The input queue for this native activity's window is being destroyed. You should no longer try to reference this object upon returning from this function.
|
||||
*/
|
||||
void Fl_Android_Activity::onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
|
||||
{
|
||||
log_v("InputQueueDestroyed: %p -- %p\n", activity, queue);
|
||||
set_input(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
Create a thread that will run our FLTK code and the required communications and locks.
|
||||
\param activity the interface to the Java end of Android
|
||||
\param savedState if this app is relaunched, this is a memory block with the state of the app when it was interrupted
|
||||
\param savedStateSize size of that block
|
||||
*/
|
||||
void Fl_Android_Activity::create(ANativeActivity* activity, void* savedState,
|
||||
size_t savedStateSize)
|
||||
{
|
||||
static const char *FLTK = "FLTK";
|
||||
activity->instance = (void*)FLTK;
|
||||
|
||||
set_activity(activity);
|
||||
set_callbacks();
|
||||
|
||||
allocate_screen(); // TODO: we may need to change this to when the actual screen is allocated
|
||||
|
||||
pthread_mutex_init(&pMutex, NULL);
|
||||
pthread_cond_init(&pCond, NULL);
|
||||
|
||||
if (savedState != NULL) {
|
||||
pSavedState = malloc(savedStateSize);
|
||||
pSavedStateSize = savedStateSize;
|
||||
memcpy(pSavedState, savedState, savedStateSize);
|
||||
}
|
||||
|
||||
int msgpipe[2];
|
||||
if (pipe(msgpipe)) {
|
||||
log_e("could not create pipe: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
pMsgReadPipe = msgpipe[0];
|
||||
pMsgWritePipe = msgpipe[1];
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&pThread, &attr, thread_entry, 0L);
|
||||
|
||||
// Wait for thread to start.
|
||||
pthread_mutex_lock(&pMutex);
|
||||
while (!pRunning) {
|
||||
pthread_cond_wait(&pCond, &pMutex);
|
||||
}
|
||||
pthread_mutex_unlock(&pMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
Set all callbacks from the Native Activity.
|
||||
*/
|
||||
void Fl_Android_Activity::set_callbacks()
|
||||
{
|
||||
ANativeActivityCallbacks *cb = pActivity->callbacks;
|
||||
cb->onContentRectChanged = onContentRectChanged;
|
||||
cb->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
|
||||
cb->onNativeWindowResized = onNativeWindowResized;
|
||||
cb->onDestroy = onDestroy;
|
||||
cb->onStart = onStart;
|
||||
cb->onResume = onResume;
|
||||
cb->onSaveInstanceState = onSaveInstanceState;
|
||||
cb->onPause = onPause;
|
||||
cb->onStop = onStop;
|
||||
cb->onConfigurationChanged = onConfigurationChanged;
|
||||
cb->onLowMemory = onLowMemory;
|
||||
cb->onWindowFocusChanged = onWindowFocusChanged;
|
||||
cb->onNativeWindowCreated = onNativeWindowCreated;
|
||||
cb->onNativeWindowDestroyed = onNativeWindowDestroyed;
|
||||
cb->onInputQueueCreated = onInputQueueCreated;
|
||||
cb->onInputQueueDestroyed = onInputQueueDestroyed;
|
||||
}
|
||||
|
||||
/**
|
||||
This is the main entry point from the Android JavaVM into the native world.
|
||||
*/
|
||||
JNIEXPORT void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
|
||||
{
|
||||
// TODO: can we return an error message her is creation of the app failed?
|
||||
Fl_Android_Activity::create(activity, savedState, savedStateSize);
|
||||
}
|
||||
|
||||
|
||||
// ---- Java Stuff -------------------------------------------------------------
|
||||
|
||||
|
||||
Fl_Android_Java::Fl_Android_Java()
|
||||
{
|
||||
jint lResult;
|
||||
jint lFlags = 0;
|
||||
|
||||
pJavaVM = Fl_Android_Application::get_activity()->vm;
|
||||
pJNIEnv = Fl_Android_Application::get_activity()->env;
|
||||
|
||||
JavaVMAttachArgs lJavaVMAttachArgs = {
|
||||
.version = JNI_VERSION_1_6,
|
||||
.name = "NativeThread",
|
||||
.group = nullptr
|
||||
};
|
||||
|
||||
lResult = pJavaVM->AttachCurrentThread(&pJNIEnv, &lJavaVMAttachArgs);
|
||||
if (lResult == JNI_ERR) return;
|
||||
|
||||
pNativeActivity = Fl_Android_Application::get_activity()->clazz;
|
||||
|
||||
pNativeActivityClass = env()->GetObjectClass(pNativeActivity);
|
||||
|
||||
pAttached = true;
|
||||
}
|
||||
|
||||
|
||||
Fl_Android_Java::~Fl_Android_Java()
|
||||
{
|
||||
if (is_attached()) {
|
||||
pJavaVM->DetachCurrentThread();
|
||||
}
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
//
|
||||
// Graphics regions and clipping for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_Android_Graphics_Clipping.H
|
||||
\brief Graphics regions and clipping for the Fast Light Tool Kit (FLTK).
|
||||
*/
|
||||
|
||||
#ifndef FL_ANDROID_GRAPHICS_CLIPPING_H
|
||||
#define FL_ANDROID_GRAPHICS_CLIPPING_H
|
||||
|
||||
#include <FL/Fl_Graphics_Driver.H>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
class Fl_Android_Window_Driver;
|
||||
|
||||
|
||||
/**
|
||||
The Fl_Rect_Region describes a rectangular clipping region.
|
||||
|
||||
Contrary to common FLTK convention, rectangles are stored with coordinates
|
||||
instead of their width and height to accelerate calculations. The discreet
|
||||
constructor however uses the old convention for convenience.
|
||||
*/
|
||||
class Fl_Rect_Region
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
EMPTY = 0, SAME, LESS, MORE, INFINITE
|
||||
};
|
||||
|
||||
Fl_Rect_Region();
|
||||
Fl_Rect_Region(int x, int y, int w, int h);
|
||||
Fl_Rect_Region(const Fl_Rect_Region&);
|
||||
Fl_Rect_Region(enum Type what);
|
||||
virtual ~Fl_Rect_Region() { }
|
||||
|
||||
int x() const { return pLeft; }
|
||||
int y() const { return pTop; }
|
||||
int w() const { return pRight - pLeft; }
|
||||
int h() const { return pBottom - pTop; }
|
||||
|
||||
int left() const { return pLeft; }
|
||||
int top() const { return pTop; }
|
||||
int right() const { return pRight; }
|
||||
int bottom() const { return pBottom; }
|
||||
|
||||
bool is_empty() const;
|
||||
bool is_infinite() const;
|
||||
|
||||
virtual void set_empty();
|
||||
void set(int x, int y, int w, int h);
|
||||
void set_ltrb(int l, int t, int r, int b);
|
||||
virtual void set(const Fl_Rect_Region &r);
|
||||
virtual int intersect_with(const Fl_Rect_Region &r);
|
||||
void add_to_bbox(const Fl_Rect_Region &r);
|
||||
|
||||
virtual void print(const char*) const;
|
||||
|
||||
protected:
|
||||
int pLeft, pTop, pRight, pBottom;
|
||||
|
||||
private:
|
||||
Fl_Rect_Region& operator = (const Fl_Rect_Region& other);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
The Fl_Complex_Region represents a clipping region of any shape.
|
||||
|
||||
This class is organized in a tree-like structure. If the region is
|
||||
rectangular, is_simple() returns 1 and the rectangle can be used just
|
||||
as in Fl_Rect_Region.
|
||||
|
||||
If a more complex representation is needed, subregions are created which are
|
||||
guaranteed to lie within the bounding box of the current region. Subregions
|
||||
themselves can again contain sub-subregions to describe the entire clipping
|
||||
region, effectively creating a tree where the leafs contain the rectangles
|
||||
that together describe the clipping area.
|
||||
|
||||
To make life easier, Fl_Complex_Region provides two types of iterator to
|
||||
travers the entire tree.
|
||||
|
||||
1. Fl_Complex_Region itself is compatible to C++11 range-based loops and
|
||||
can bewalked simply by writing ``for (auto &&it: rgn) { ... }``.
|
||||
|
||||
2. Fl_Complex_Region provides an alternative iterator that loop only through
|
||||
leafs that intersects with a given rectangle. The returned object
|
||||
provides access to the readily clipped rectangle.
|
||||
|
||||
\code
|
||||
Fl_Complex_Region rgn(something);
|
||||
for (auto &&it: rgn.iterate(Fl_Rect_Region(0, 0, 100, 100)) {
|
||||
draw_something(it->rect());
|
||||
}
|
||||
\endcode
|
||||
|
||||
*/
|
||||
class Fl_Complex_Region : public Fl_Rect_Region
|
||||
{
|
||||
class Iterator {
|
||||
public:
|
||||
Iterator(Fl_Complex_Region *r);
|
||||
bool operator!= (const Iterator& other) const;
|
||||
const Iterator& operator++ ();
|
||||
Fl_Complex_Region *operator* () const;
|
||||
Fl_Complex_Region *pRegion;
|
||||
};
|
||||
|
||||
class Overlapping {
|
||||
class OverlappingIterator {
|
||||
public:
|
||||
OverlappingIterator(Overlapping *ov);
|
||||
bool operator!= (const OverlappingIterator& other) const;
|
||||
const OverlappingIterator& operator++ ();
|
||||
Overlapping *operator* () const;
|
||||
Overlapping *pOv;
|
||||
};
|
||||
public:
|
||||
Overlapping(Fl_Complex_Region *rgn, const Fl_Rect_Region &rect);
|
||||
OverlappingIterator begin();
|
||||
OverlappingIterator end();
|
||||
Fl_Rect_Region &clipped_rect();
|
||||
bool intersects();
|
||||
bool find_intersecting();
|
||||
bool find_next();
|
||||
Fl_Complex_Region *pRegion;
|
||||
Fl_Rect_Region pOriginalRect;
|
||||
Fl_Rect_Region pClippedRect;
|
||||
};
|
||||
|
||||
public:
|
||||
Fl_Complex_Region();
|
||||
Fl_Complex_Region(const Fl_Rect_Region&);
|
||||
virtual ~Fl_Complex_Region() override;
|
||||
void delete_all_subregions();
|
||||
|
||||
virtual void set(const Fl_Rect_Region &r) override;
|
||||
void set(const Fl_Complex_Region &r);
|
||||
virtual void set_empty() override { delete pSubregion; pSubregion=0L; Fl_Rect_Region::set_empty(); }
|
||||
Fl_Complex_Region *subregion() const { return pSubregion; }
|
||||
Fl_Complex_Region *next() const { return pNext; }
|
||||
Fl_Complex_Region *parent() const { return pParent; }
|
||||
char is_simple() const { return pSubregion==0; }
|
||||
char is_complex() const { return pSubregion!=0; }
|
||||
|
||||
virtual int intersect_with(const Fl_Rect_Region &r) override;
|
||||
int subtract(const Fl_Rect_Region &r);
|
||||
|
||||
virtual void print(const char*) const override;
|
||||
|
||||
Iterator begin();
|
||||
Iterator end();
|
||||
|
||||
Overlapping overlapping(const Fl_Rect_Region &r);
|
||||
|
||||
protected:
|
||||
void print_data(int indent) const;
|
||||
int subtract_smaller_region(const Fl_Rect_Region &r);
|
||||
Fl_Complex_Region *add_subregion();
|
||||
void compress();
|
||||
|
||||
Fl_Complex_Region *pSubregion = 0L;
|
||||
Fl_Complex_Region *pParent = 0L;
|
||||
Fl_Complex_Region *pNext = 0L;
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_ANDROID_GRAPHICS_CLIPPING_H
|
@ -1,808 +0,0 @@
|
||||
//
|
||||
// Clipping region routines for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_Android_Graphics_Driver.H"
|
||||
#include "Fl_Android_Application.H"
|
||||
#include <FL/platform.H>
|
||||
|
||||
|
||||
/**
|
||||
Create an empty clipping region.
|
||||
*/
|
||||
Fl_Rect_Region::Fl_Rect_Region() :
|
||||
pLeft(0), pTop(0), pRight(0), pBottom(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Create a clipping region based on position and size.
|
||||
\param x, y position
|
||||
\param w, h size
|
||||
*/
|
||||
Fl_Rect_Region::Fl_Rect_Region(int x, int y, int w, int h) :
|
||||
pLeft(x), pTop(y), pRight(x+w), pBottom(y+h)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Clone a clipping rectangle.
|
||||
*/
|
||||
Fl_Rect_Region::Fl_Rect_Region(const Fl_Rect_Region &r) :
|
||||
pLeft(r.pLeft), pTop(r.pTop),
|
||||
pRight(r.pRight), pBottom(r.pBottom)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Clone a clipping rectangle.
|
||||
The pointer can be NULL if an empty rectangle is needed.
|
||||
*/
|
||||
Fl_Rect_Region::Fl_Rect_Region(enum Type what)
|
||||
{
|
||||
if (what==INFINITE) {
|
||||
pLeft = pTop = INT_MIN;
|
||||
pRight = pBottom = INT_MAX;
|
||||
} else {
|
||||
pLeft = pTop = pRight = pBottom = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
If the rectangle has no width or height, it's considered empty.
|
||||
\return true, if everything will be clipped and there is nothing to draw
|
||||
*/
|
||||
bool Fl_Rect_Region::is_empty() const
|
||||
{
|
||||
return (pRight<=pLeft || pBottom<=pTop);
|
||||
}
|
||||
|
||||
/**
|
||||
Return true, if the rectangle is of unlimited size and nothing should be clipped.
|
||||
\return treu, if there is no clipping
|
||||
*/
|
||||
bool Fl_Rect_Region::is_infinite() const
|
||||
{
|
||||
return (pLeft==INT_MIN);
|
||||
}
|
||||
|
||||
/**
|
||||
Set an empty clipping rect.
|
||||
*/
|
||||
void Fl_Rect_Region::set_empty()
|
||||
{
|
||||
pLeft = pTop = pRight = pBottom = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Set a clipping rect using position and size
|
||||
\param x, y position
|
||||
\param w, h size
|
||||
*/
|
||||
void Fl_Rect_Region::set(int x, int y, int w, int h)
|
||||
{
|
||||
pLeft = x;
|
||||
pTop = y;
|
||||
pRight = x+w;
|
||||
pBottom = y+h;
|
||||
}
|
||||
|
||||
/**
|
||||
Set a rectangle using the coordinates of two points, top left and bottom right.
|
||||
\param l, t left and top coordinate
|
||||
\param r, b right and bottom coordinate
|
||||
*/
|
||||
void Fl_Rect_Region::set_ltrb(int l, int t, int r, int b)
|
||||
{
|
||||
pLeft = l;
|
||||
pTop = t;
|
||||
pRight = r;
|
||||
pBottom = b;
|
||||
}
|
||||
|
||||
/**
|
||||
Copy the corrdinates from another rect.
|
||||
\param r source rectangle
|
||||
*/
|
||||
void Fl_Rect_Region::set(const Fl_Rect_Region &r)
|
||||
{
|
||||
pLeft = r.pLeft;
|
||||
pTop = r.pTop;
|
||||
pRight = r.pRight;
|
||||
pBottom = r.pBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
Set this rect to be the intersecting area between the original rect and another rect.
|
||||
\param r another rectangular region
|
||||
\return EMPTY, if rectangles are not intersecting, SAME if this and rect are
|
||||
equal, LESS if the new rect is smaller than the original rect
|
||||
*/
|
||||
int Fl_Rect_Region::intersect_with(const Fl_Rect_Region &r)
|
||||
{
|
||||
if (is_empty()) {
|
||||
return EMPTY;
|
||||
}
|
||||
if (r.is_empty()) {
|
||||
set_empty();
|
||||
return EMPTY;
|
||||
}
|
||||
bool same = true;
|
||||
if ( pLeft != r.pLeft ) {
|
||||
same = false;
|
||||
if ( r.pLeft > pLeft ) pLeft = r.pLeft;
|
||||
}
|
||||
if ( pTop != r.pTop ) {
|
||||
same = false;
|
||||
if ( r.pTop > pTop ) pTop = r.pTop;
|
||||
}
|
||||
if ( pRight != r.pRight ) {
|
||||
same = false;
|
||||
if ( r.pRight < pRight ) pRight = r.pRight;
|
||||
}
|
||||
if ( pBottom != r.pBottom ) {
|
||||
same = false;
|
||||
if ( r.pBottom < pBottom ) pBottom = r.pBottom;
|
||||
}
|
||||
if (same)
|
||||
return SAME;
|
||||
if (is_empty())
|
||||
return EMPTY;
|
||||
return LESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Use rectangle as a bounding box and add the outline of another rect.
|
||||
*/
|
||||
void Fl_Rect_Region::add_to_bbox(const Fl_Rect_Region &r)
|
||||
{
|
||||
if (is_empty()) return;
|
||||
if (r.pLeft<pLeft) pLeft = r.pLeft;
|
||||
if (r.pTop<pTop) pTop = r.pTop;
|
||||
if (r.pRight>pRight) pRight = r.pRight;
|
||||
if (r.pBottom>pBottom) pBottom = r.pBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
Print the coordinates of the rect to the log.
|
||||
\param label some text that is logged with this message.
|
||||
*/
|
||||
void Fl_Rect_Region::print(const char *label) const
|
||||
{
|
||||
Fl_Android_Application::log_i("---> Fl_Rect_Region: %s", label);
|
||||
Fl_Android_Application::log_i("Rect l:%d t:%d r:%d b:%d", left(), top(), right(), bottom());
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
Create an empty complex region.
|
||||
*/
|
||||
Fl_Complex_Region::Fl_Complex_Region() :
|
||||
Fl_Rect_Region()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Create a complex region with the same bounds as the give rect.
|
||||
\param r region size
|
||||
*/
|
||||
Fl_Complex_Region::Fl_Complex_Region(const Fl_Rect_Region &r) :
|
||||
Fl_Rect_Region(r)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Delete this region, all subregions recursively, and all following regions.
|
||||
*/
|
||||
Fl_Complex_Region::~Fl_Complex_Region()
|
||||
{
|
||||
delete_all_subregions();
|
||||
}
|
||||
|
||||
/**
|
||||
Delete all subregions of this region.
|
||||
The pSubregion pointer should always be seen as a list of subregions, rather
|
||||
than a single region and some pNext pointer. So everything we do, we should
|
||||
probably do for every object in that list.
|
||||
|
||||
Also note, that the top level region never has pNext pointing to anything.
|
||||
*/
|
||||
void Fl_Complex_Region::delete_all_subregions()
|
||||
{
|
||||
// Do NOT delete the chain in pNext! The caller has to that job.
|
||||
// A top-level coplex region has pNext always set to NULL, and it does
|
||||
// delete all subregions chained via the subregion pNext.
|
||||
while (pSubregion) {
|
||||
Fl_Complex_Region *rgn = pSubregion;
|
||||
pSubregion = rgn->pNext;
|
||||
delete rgn; rgn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Print the entire content of this region recursively.
|
||||
*/
|
||||
void Fl_Complex_Region::print(const char *label) const
|
||||
{
|
||||
Fl_Android_Application::log_i("---> Fl_Complex_Region: %s", label);
|
||||
print_data(0);
|
||||
}
|
||||
|
||||
/*
|
||||
Print the rectangular data only.
|
||||
*/
|
||||
void Fl_Complex_Region::print_data(int indent) const
|
||||
{
|
||||
static const char *space = " ";
|
||||
if (pSubregion) {
|
||||
Fl_Android_Application::log_i("%sBBox l:%d t:%d r:%d b:%d", space+16-indent, left(), top(), right(), bottom());
|
||||
pSubregion->print_data(indent+1);
|
||||
} else {
|
||||
Fl_Android_Application::log_i("%sRect l:%d t:%d r:%d b:%d", space+16-indent, left(), top(), right(), bottom());
|
||||
}
|
||||
if (pNext) {
|
||||
pNext->print_data(indent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Replace this region with a rectangle.
|
||||
\param r the source rectangle
|
||||
*/
|
||||
void Fl_Complex_Region::set(const Fl_Rect_Region &r)
|
||||
{
|
||||
Fl_Rect_Region::set(r);
|
||||
delete_all_subregions();
|
||||
}
|
||||
|
||||
/**
|
||||
Replace this region with a copy of another region.
|
||||
This operation can be expensive for very complex regions.
|
||||
\param r the source region
|
||||
*/
|
||||
void Fl_Complex_Region::set(const Fl_Complex_Region &r)
|
||||
{
|
||||
Fl_Rect_Region::set((const Fl_Rect_Region&)r);
|
||||
delete_all_subregions();
|
||||
|
||||
Fl_Complex_Region *srcRgn = r.pSubregion;
|
||||
if (srcRgn) {
|
||||
// copy first subregion
|
||||
Fl_Complex_Region *dstRgn = pSubregion = new Fl_Complex_Region();
|
||||
pSubregion->set(*srcRgn);
|
||||
// copy rest of list
|
||||
while (srcRgn) {
|
||||
dstRgn->pNext = new Fl_Complex_Region();
|
||||
dstRgn = dstRgn->next();
|
||||
dstRgn->set(*srcRgn);
|
||||
srcRgn = srcRgn->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Set this region to the intersection of the original region and some rect.
|
||||
\param r intersect with this rectangle
|
||||
\return EMPTY, SAME, LESS
|
||||
*/
|
||||
int Fl_Complex_Region::intersect_with(const Fl_Rect_Region &r)
|
||||
{
|
||||
if (pSubregion) {
|
||||
Fl_Complex_Region *rgn = pSubregion;
|
||||
while (rgn) {
|
||||
rgn->intersect_with(r);
|
||||
rgn = rgn->next();
|
||||
}
|
||||
compress();
|
||||
} else {
|
||||
Fl_Rect_Region::intersect_with(r);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Subtract a rectangular region from this region.
|
||||
\param r the rect that we want removed
|
||||
\return currently 0, but could return something meaningful
|
||||
*/
|
||||
int Fl_Complex_Region::subtract(const Fl_Rect_Region &r)
|
||||
{
|
||||
if (pSubregion) {
|
||||
Fl_Complex_Region *rgn = pSubregion;
|
||||
while (rgn) {
|
||||
rgn->subtract(r);
|
||||
rgn = rgn->next();
|
||||
}
|
||||
compress();
|
||||
} else {
|
||||
// Check if we overlap at all
|
||||
Fl_Rect_Region s(r);
|
||||
int intersects = s.intersect_with(*this);
|
||||
switch (intersects) {
|
||||
case EMPTY:
|
||||
// nothing to do
|
||||
break;
|
||||
case SAME:
|
||||
set_empty(); // Will be deleted by compress()
|
||||
break;
|
||||
case LESS:
|
||||
// split this rect into 1, 2, 3, or 4 new ones
|
||||
subtract_smaller_region(s);
|
||||
break;
|
||||
default:
|
||||
Fl_Android_Application::log_e("Invalid case in %s:%d", __FUNCTION__, __LINE__);
|
||||
break;
|
||||
}
|
||||
if (pSubregion) compress(); // because intersecting this may have created subregions
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Compress the subregion of this region if possible and update the bounding
|
||||
box of this region.
|
||||
|
||||
Does not recurse down the tree!
|
||||
*/
|
||||
void Fl_Complex_Region::compress()
|
||||
{
|
||||
// Can't compress anything that does not have a subregion
|
||||
if (!pSubregion) return;
|
||||
|
||||
// remove all empty regions, because the really don't add anything (literally)
|
||||
// print("Compress");
|
||||
Fl_Complex_Region *rgn = pSubregion;
|
||||
while (rgn && rgn->is_empty()) {
|
||||
pSubregion = rgn->next();
|
||||
delete rgn; rgn = pSubregion;
|
||||
}
|
||||
if (!pSubregion) return;
|
||||
|
||||
rgn = pSubregion;
|
||||
while (rgn) {
|
||||
while (rgn->pNext && rgn->pNext->is_empty()) {
|
||||
Fl_Complex_Region *nextNext = rgn->pNext->pNext;
|
||||
delete rgn->pNext; rgn->pNext = nextNext;
|
||||
}
|
||||
rgn = rgn->next();
|
||||
}
|
||||
|
||||
// find rectangles that can be merged into a single new rectangle
|
||||
// (Too much work for much too little benefit)
|
||||
|
||||
// if there is only a single subregion left, merge it into this region
|
||||
if (pSubregion->pNext==nullptr) {
|
||||
set((Fl_Rect_Region&)*pSubregion); // deletes subregion for us
|
||||
}
|
||||
if (!pSubregion) return;
|
||||
|
||||
// finally, update the boudning box
|
||||
Fl_Rect_Region::set((Fl_Rect_Region&)*pSubregion);
|
||||
for (rgn=pSubregion->pNext; rgn; rgn=rgn->pNext) {
|
||||
add_to_bbox(*rgn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Subtract a smaller rect from a larger rect, potentially creating four new rectangles.
|
||||
This assumes that the calling region is NOT complex.
|
||||
\param r subtract the area of this rectangle; r must fit within ``this``.
|
||||
\return currently 0, but this may change
|
||||
*/
|
||||
int Fl_Complex_Region::subtract_smaller_region(const Fl_Rect_Region &r)
|
||||
{
|
||||
// subtract a smaller rect from a larger rect and create subrects as needed
|
||||
// if there is only one single coordinate different, we can reuse this container
|
||||
if (left()==r.left() && top()==r.top() && right()==r.right() && bottom()==r.bottom()) {
|
||||
// this should not happen
|
||||
set_empty();
|
||||
} else if (left()!=r.left() && top()==r.top() && right()==r.right() && bottom()==r.bottom()) {
|
||||
pRight = r.left();
|
||||
} else if (left()==r.left() && top()!=r.top() && right()==r.right() && bottom()==r.bottom()) {
|
||||
pBottom = r.top();
|
||||
} else if (left()==r.left() && top()==r.top() && right()!=r.right() && bottom()==r.bottom()) {
|
||||
pLeft = r.right();
|
||||
} else if (left()==r.left() && top()==r.top() && right()==r.right() && bottom()!=r.bottom()) {
|
||||
pTop = r.bottom();
|
||||
} else {
|
||||
// create multiple regions
|
||||
if (pTop!=r.top()) {
|
||||
Fl_Complex_Region *s = add_subregion();
|
||||
s->set_ltrb(pLeft, pTop, pRight, r.top());
|
||||
}
|
||||
if (pBottom!=r.bottom()) {
|
||||
Fl_Complex_Region *s = add_subregion();
|
||||
s->set_ltrb(pLeft, r.bottom(), pRight, pBottom);
|
||||
}
|
||||
if (pLeft!=r.left()) {
|
||||
Fl_Complex_Region *s = add_subregion();
|
||||
s->set_ltrb(pLeft, r.top(), r.left(), r.bottom());
|
||||
}
|
||||
if (pRight!=r.right()) {
|
||||
Fl_Complex_Region *s = add_subregion();
|
||||
s->set_ltrb(r.right(), r.top(), pRight, r.bottom());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Add an empty subregion to the current region.
|
||||
\return a pointer to the newly created region.
|
||||
*/
|
||||
Fl_Complex_Region *Fl_Complex_Region::add_subregion()
|
||||
{
|
||||
Fl_Complex_Region *r = new Fl_Complex_Region();
|
||||
r->pParent = this;
|
||||
r->pNext = pSubregion;
|
||||
pSubregion = r;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Returns an iterator object for loops that traverse the entire region tree.
|
||||
C++11 interface to range-based loops.
|
||||
\return Iterator pointing to the first element.
|
||||
*/
|
||||
Fl_Complex_Region::Iterator Fl_Complex_Region::begin()
|
||||
{
|
||||
return Iterator(this);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns an interator object to mark the end of travesing the tree.
|
||||
C++11 interface to range-based loops.
|
||||
\return
|
||||
*/
|
||||
Fl_Complex_Region::Iterator Fl_Complex_Region::end()
|
||||
{
|
||||
return Iterator(nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
Create an iterator to walk the entire tree.
|
||||
\param r Iterate through this region, r must not have a parent().
|
||||
*/
|
||||
Fl_Complex_Region::Iterator::Iterator(Fl_Complex_Region *r) :
|
||||
pRegion(r)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Compare two iterators.
|
||||
C++11 needs this to find the end of a for loop.
|
||||
\param other
|
||||
\return
|
||||
*/
|
||||
bool Fl_Complex_Region::Iterator::operator!=(const Iterator &other) const
|
||||
{
|
||||
return pRegion != other.pRegion;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the iterator to the next object in the tree, down first.
|
||||
C++11 needs this to iterate in a for loop.
|
||||
\return
|
||||
*/
|
||||
const Fl_Complex_Region::Iterator &Fl_Complex_Region::Iterator::operator++()
|
||||
{
|
||||
if (pRegion->subregion()) {
|
||||
pRegion = pRegion->subregion();
|
||||
} else if (pRegion->next()) {
|
||||
pRegion = pRegion->next();
|
||||
} else {
|
||||
pRegion = pRegion->parent();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the current object while iterating through the tree.
|
||||
\return
|
||||
*/
|
||||
Fl_Complex_Region *Fl_Complex_Region::Iterator::operator*() const
|
||||
{
|
||||
return pRegion;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Use this to iterate through a region, hitting only nodes that intersect with this rect.
|
||||
\param r find all parts of the region that intersect with this rect.
|
||||
\return an object that can be used in range-based for loops in C++11.
|
||||
*/
|
||||
Fl_Complex_Region::Overlapping Fl_Complex_Region::overlapping(const Fl_Rect_Region &r)
|
||||
{
|
||||
return Overlapping(this, r);
|
||||
}
|
||||
|
||||
/**
|
||||
A helper object for iterating through a region, finding only overlapping rects.
|
||||
\param rgn
|
||||
\param rect
|
||||
*/
|
||||
Fl_Complex_Region::Overlapping::Overlapping(Fl_Complex_Region *rgn,
|
||||
const Fl_Rect_Region &rect) :
|
||||
pRegion(rgn),
|
||||
pOriginalRect(rect),
|
||||
pClippedRect(rect)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Return an itertor for the first clipping rectangle inside the region.
|
||||
\return
|
||||
*/
|
||||
Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::begin()
|
||||
{
|
||||
find_intersecting();
|
||||
return OverlappingIterator(this);
|
||||
}
|
||||
|
||||
/**
|
||||
Return an iterator for the end of forward iteration.
|
||||
\return
|
||||
*/
|
||||
Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::end()
|
||||
{
|
||||
return OverlappingIterator(nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
Return the result of intersecting the original rect with this iterator.
|
||||
\return
|
||||
*/
|
||||
Fl_Rect_Region &Fl_Complex_Region::Overlapping::clipped_rect()
|
||||
{
|
||||
return pClippedRect;
|
||||
}
|
||||
|
||||
/**
|
||||
Store the intersection in pClippedRect and return true if there was an intersection.
|
||||
\return
|
||||
*/
|
||||
bool Fl_Complex_Region::Overlapping::intersects()
|
||||
{
|
||||
return (pClippedRect.intersect_with(*pRegion) != EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
Find the next element in the tree that actually intersects with the initial rect.
|
||||
Starting the search at the current object, NOT the next object.
|
||||
\return
|
||||
*/
|
||||
bool Fl_Complex_Region::Overlapping::find_intersecting()
|
||||
{
|
||||
for (;;) {
|
||||
if (!pRegion) return false;
|
||||
pClippedRect.set(pOriginalRect);
|
||||
if (intersects()) {
|
||||
if (!pRegion->subregion()) {
|
||||
return true;
|
||||
} else {
|
||||
pRegion = pRegion->subregion();
|
||||
}
|
||||
} else {
|
||||
find_next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Find the next object in the tree, complex, simple, intersecting or not.
|
||||
\return
|
||||
*/
|
||||
bool Fl_Complex_Region::Overlapping::find_next()
|
||||
{
|
||||
if (pRegion->subregion()) {
|
||||
pRegion = pRegion->subregion();
|
||||
} else if (pRegion->next()) {
|
||||
pRegion = pRegion->next();
|
||||
} else {
|
||||
pRegion = pRegion->parent(); // can be NULL
|
||||
}
|
||||
return (pRegion != nullptr);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Create the actual iterator for finding true clipping rects.
|
||||
\see Fl_Complex_Region::Overlapping
|
||||
\param ov
|
||||
*/
|
||||
Fl_Complex_Region::Overlapping::OverlappingIterator::OverlappingIterator(
|
||||
Overlapping *ov) :
|
||||
pOv(ov)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Compare two iterator.
|
||||
This is used by C++11 range-based for loops to find the end of the range.
|
||||
\param other
|
||||
\return
|
||||
*/
|
||||
bool Fl_Complex_Region::Overlapping::OverlappingIterator::operator!=(
|
||||
const OverlappingIterator &other) const
|
||||
{
|
||||
auto thisRegion = pOv ? pOv->pRegion : nullptr;
|
||||
auto otherRegion = other.pOv ? other.pOv->pRegion : nullptr;
|
||||
return thisRegion != otherRegion;
|
||||
}
|
||||
|
||||
/**
|
||||
Wrapper to find and set the next intersecting rectangle.
|
||||
\see Fl_Complex_Region::Overlapping::find_intersecting
|
||||
\see Fl_Complex_Region::Overlapping::find_next
|
||||
\return
|
||||
*/
|
||||
const Fl_Complex_Region::Overlapping::OverlappingIterator &
|
||||
Fl_Complex_Region::Overlapping::OverlappingIterator::operator++()
|
||||
{
|
||||
pOv->find_next();
|
||||
if (pOv->pRegion)
|
||||
pOv->find_intersecting();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the Fl_Complex_Region::Overlapping state for this iterator.
|
||||
This gives the user access to the current rectangular fragment of
|
||||
the clipping region.
|
||||
\return
|
||||
*/
|
||||
Fl_Complex_Region::Overlapping *
|
||||
Fl_Complex_Region::Overlapping::OverlappingIterator::operator*() const
|
||||
{
|
||||
return pOv;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
|
||||
void Fl_Android_Graphics_Driver::restore_clip()
|
||||
{
|
||||
fl_clip_state_number++;
|
||||
|
||||
// find the current user clipping rectangle
|
||||
Fl_Region b = rstack[rstackptr]; // Fl_Region is a pointer to Fl_Rect_Region
|
||||
if (b) {
|
||||
if (b->is_empty()) {
|
||||
// if this is an empty region, the intersection is always empty as well
|
||||
pClippingRegion.set_empty();
|
||||
} else {
|
||||
// if there is a region, copy the full window region
|
||||
pClippingRegion.set(pDesktopWindowRegion);
|
||||
if (!b->is_infinite()) {
|
||||
// if the rect has dimensions, calculate the intersection
|
||||
pClippingRegion.intersect_with(*b);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no rect? Just copy the window region
|
||||
pClippingRegion.set(pDesktopWindowRegion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Graphics_Driver::clip_region(Fl_Region r)
|
||||
{
|
||||
Fl_Region oldr = rstack[rstackptr];
|
||||
if (oldr)
|
||||
::free(oldr);
|
||||
rstack[rstackptr] = r;
|
||||
restore_clip();
|
||||
}
|
||||
|
||||
|
||||
Fl_Region Fl_Android_Graphics_Driver::clip_region()
|
||||
{
|
||||
return rstack[rstackptr];
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Graphics_Driver::push_clip(int x, int y, int w, int h)
|
||||
{
|
||||
Fl_Region r;
|
||||
if (w > 0 && h > 0) {
|
||||
r = new Fl_Rect_Region(x, y, w, h);
|
||||
Fl_Region current = rstack[rstackptr];
|
||||
if (current) {
|
||||
r->intersect_with(*current);
|
||||
}
|
||||
} else { // make empty clip region:
|
||||
r = new Fl_Rect_Region();
|
||||
}
|
||||
if (rstackptr < region_stack_max) rstack[++rstackptr] = r;
|
||||
else Fl::warning("Fl_Android_Graphics_Driver::push_clip: clip stack overflow!\n");
|
||||
restore_clip();
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Graphics_Driver::push_no_clip()
|
||||
{
|
||||
if (rstackptr < region_stack_max) rstack[++rstackptr] = 0;
|
||||
else Fl::warning("Fl_Android_Graphics_Driver::push_no_clip: clip stack overflow!\n");
|
||||
restore_clip();
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Graphics_Driver::pop_clip()
|
||||
{
|
||||
if (rstackptr > 0) {
|
||||
Fl_Region oldr = rstack[rstackptr--];
|
||||
if (oldr)
|
||||
::free(oldr);
|
||||
} else Fl::warning("Fl_Android_Graphics_Driver::pop_clip: clip stack underflow!\n");
|
||||
restore_clip();
|
||||
}
|
||||
|
||||
/*
|
||||
Intersects the rectangle with the current clip region and returns the
|
||||
bounding box of the result.
|
||||
|
||||
Returns non-zero if the resulting rectangle is different to the original.
|
||||
This can be used to limit the necessary drawing to a rectangle.
|
||||
\p W and \p H are set to zero if the rectangle is completely outside the region.
|
||||
\param[in] x,y,w,h position and size of rectangle
|
||||
\param[out] X,Y,W,H position and size of resulting bounding box.
|
||||
\returns Non-zero if the resulting rectangle is different to the original.
|
||||
*/
|
||||
int Fl_Android_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H)
|
||||
{
|
||||
Fl_Region r = rstack[rstackptr];
|
||||
if (r) {
|
||||
Fl_Rect_Region a(x, y, w, h);
|
||||
int ret = a.intersect_with(*r);
|
||||
X = a.x();
|
||||
Y = a.y();
|
||||
W = a.w();
|
||||
H = a.h();
|
||||
return (ret!=Fl_Rect_Region::SAME);
|
||||
} else {
|
||||
X = x; Y = y; W = w; H = h;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Does the rectangle intersect the current clip region?
|
||||
\param[in] x,y,w,h position and size of rectangle
|
||||
\returns non-zero if any of the rectangle intersects the current clip
|
||||
region. If this returns 0 you don't have to draw the object.
|
||||
|
||||
\note
|
||||
Under X this returns 2 if the rectangle is partially clipped,
|
||||
and 1 if it is entirely inside the clip region.
|
||||
*/
|
||||
int Fl_Android_Graphics_Driver::not_clipped(int x, int y, int w, int h)
|
||||
{
|
||||
if (w <= 0 || h <= 0) return 0;
|
||||
Fl_Region r = rstack[rstackptr];
|
||||
if (r) {
|
||||
Fl_Rect_Region a(x, y, w, h); // return 0 for empty, 1 for same, 2 if intersecting
|
||||
return a.intersect_with(*r);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
@ -1,352 +0,0 @@
|
||||
//
|
||||
// Definition of classes Fl_Graphics_Driver, Fl_Surface_Device, Fl_Display_Device
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_Android_Graphics_Driver.H
|
||||
\brief Definition of Android graphics driver.
|
||||
*/
|
||||
|
||||
#ifndef FL_ANDROID_GRAPHICS_DRIVER_H
|
||||
#define FL_ANDROID_GRAPHICS_DRIVER_H
|
||||
|
||||
#include <FL/Fl_Graphics_Driver.H>
|
||||
#include "Fl_Android_Graphics_Clipping.H"
|
||||
#include "Fl_Android_Graphics_Font.H"
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
class Fl_Android_Window_Driver;
|
||||
class Fl_Android_Bytemap;
|
||||
class Fl_Android_565A_Map;
|
||||
|
||||
/**
|
||||
\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_Graphics_Driver
|
||||
{
|
||||
// easy access to the super class
|
||||
typedef Fl_Graphics_Driver super;
|
||||
|
||||
protected:
|
||||
class Vertex; // see below
|
||||
|
||||
// --- this is a copy of Fl_Graphics_Driver ----------------------------------
|
||||
// - use this to find unimplementet calls in the derived driver
|
||||
// - excluded by #if/#endif means that we have not implemneted this yet
|
||||
// - methods marked with // super: use the implemnetation of the super class
|
||||
// - virtual ... override functions are implemented for Android
|
||||
private:
|
||||
virtual void draw_fixed(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) override;
|
||||
virtual void draw_fixed(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) override;
|
||||
virtual void draw_fixed(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) override;
|
||||
// some platforms may need to reimplement this
|
||||
// This is called from the surface device, see: end_current()
|
||||
// super: virtual void set_current_();
|
||||
protected:
|
||||
/** Sets the current value of the scaling factor */
|
||||
// super: virtual void scale(float f) { scale_ = f; } // we do not support any scaling at this point
|
||||
protected:
|
||||
// set fl_gc, which we do not use in the Android port at this point
|
||||
// super: virtual void global_gc();
|
||||
/** Support function for Fl_Pixmap drawing */
|
||||
virtual void cache(Fl_Pixmap *img) override;
|
||||
/** Support function for Fl_Bitmap drawing */
|
||||
virtual void cache(Fl_Bitmap *img) override;
|
||||
virtual void cache(Fl_RGB_Image *img) override;
|
||||
/** Support function for Fl_RGB_Image drawing */
|
||||
virtual void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) override;
|
||||
// --- implementation is in src/drivers/xxx/Fl_xxx_Graphics_Driver_image.cxx
|
||||
/** see fl_draw_image(const uchar* buf, int X,int Y,int W,int H, int D, int L) */
|
||||
virtual void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) override;
|
||||
/** see fl_draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D, int L) */
|
||||
virtual void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) override;
|
||||
/** see fl_draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) */
|
||||
virtual void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) override;
|
||||
/** see fl_draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D) */
|
||||
virtual void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) override;
|
||||
#if 0
|
||||
// TODO: where are begine_, end_, create_, and delete_offscreen? Answer: Fl_Image_Surface - you know what to do!
|
||||
virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
|
||||
/** Support function for image drawing */
|
||||
// TODO: these seem to be only needed if FL_Image and Fl_Pixmap store alpha values seperatley.
|
||||
virtual Fl_Bitmask create_bitmask(int w, int h, const uchar *array) {return 0; }
|
||||
#endif
|
||||
// Support function for image drawing
|
||||
virtual void uncache_pixmap(fl_uintptr_t p) override;
|
||||
// Support function for image drawing
|
||||
virtual void delete_bitmask(Fl_Bitmask bm) override;
|
||||
public:
|
||||
/** Constructor, C++11 initialises member variables in-line */
|
||||
Fl_Android_Graphics_Driver();
|
||||
/** destructor */
|
||||
virtual ~Fl_Android_Graphics_Driver() override;
|
||||
/** Return whether the graphics driver can do alpha blending */
|
||||
virtual char can_do_alpha_blending() override { return 0; }
|
||||
// --- implementation is in src/fl_rect.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_rect.cxx
|
||||
/** see fl_point() */
|
||||
virtual void point(int x, int y) override;
|
||||
/** see fl_rect() */
|
||||
virtual void rect(int x, int y, int w, int h) override;
|
||||
// super: virtual void focus_rect(int x, int y, int w, int h);
|
||||
/** see fl_rectf() */
|
||||
virtual void rectf(int x, int y, int w, int h) override;
|
||||
/** see fl_line(int, int, int, int) */
|
||||
virtual void line(int x, int y, int x1, int y1) override;
|
||||
/** see fl_line(int, int, int, int, int, int) */
|
||||
virtual void line(int x, int y, int x1, int y1, int x2, int y2) override;
|
||||
/** see fl_xyline(int, int, int) */
|
||||
virtual void xyline(int x, int y, int x1) override;
|
||||
/** see fl_xyline(int, int, int, int) */
|
||||
virtual void xyline(int x, int y, int x1, int y2) override;
|
||||
/** see fl_xyline(int, int, int, int, int) */
|
||||
virtual void xyline(int x, int y, int x1, int y2, int x3) override;
|
||||
/** see fl_yxline(int, int, int) */
|
||||
virtual void yxline(int x, int y, int y1) override;
|
||||
/** see fl_yxline(int, int, int, int) */
|
||||
virtual void yxline(int x, int y, int y1, int x2) override;
|
||||
/** see fl_yxline(int, int, int, int, int) */
|
||||
virtual void yxline(int x, int y, int y1, int x2, int y3) override;
|
||||
/** see fl_loop(int, int, int, int, int, int) */
|
||||
virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2) override;
|
||||
/** see fl_loop(int, int, int, int, int, int, int, int) */
|
||||
virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) override;
|
||||
/** see fl_polygon(int, int, int, int, int, int) */
|
||||
virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2) override;
|
||||
/** see fl_polygon(int, int, int, int, int, int, int, int) */
|
||||
virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) override;
|
||||
// --- clipping
|
||||
/** see fl_push_clip() */
|
||||
virtual void push_clip(int x, int y, int w, int h) override;
|
||||
/** see fl_clip_box() */
|
||||
virtual int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) override;
|
||||
/** see fl_not_clipped() */
|
||||
virtual int not_clipped(int x, int y, int w, int h) override;
|
||||
/** see fl_push_no_clip() */
|
||||
virtual void push_no_clip() override;
|
||||
/** see fl_pop_clip() */
|
||||
virtual void pop_clip() override;
|
||||
virtual Fl_Region clip_region() override;
|
||||
virtual void clip_region(Fl_Region r) override;
|
||||
virtual void restore_clip() override;
|
||||
// --- implementation is in src/fl_vertex.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_vertex.cxx
|
||||
// super: virtual void push_matrix();
|
||||
// super: virtual void pop_matrix();
|
||||
// super: virtual void mult_matrix(double a, double b, double c, double d, double x, double y);
|
||||
// super: virtual void rotate(double d);
|
||||
// super: virtual void translate(double x,double y);
|
||||
virtual void begin_points() override;
|
||||
virtual void begin_line() override;
|
||||
virtual void begin_loop() override;
|
||||
virtual void begin_polygon() override;
|
||||
virtual void begin_complex_polygon() override;
|
||||
// super: virtual double transform_x(double x, double y);
|
||||
// super: virtual double transform_y(double x, double y);
|
||||
// super: virtual double transform_dx(double x, double y);
|
||||
// super: virtual double transform_dy(double x, double y);
|
||||
/** see fl_transformed_vertex() */
|
||||
virtual void transformed_vertex(double xf, double yf) override;
|
||||
/** see fl_vertex() */
|
||||
virtual void vertex(double x, double y) override;
|
||||
/** see fl_end_points() */
|
||||
virtual void end_points() override;
|
||||
/** see fl_end_line() */
|
||||
virtual void end_line() override;
|
||||
/** see fl_end_loop() */
|
||||
virtual void end_loop() override;
|
||||
/** see fl_end_polygon() */
|
||||
virtual void end_polygon() override;
|
||||
/** see fl_end_complex_polygon() */
|
||||
virtual void end_complex_polygon() override;
|
||||
/** see fl_gap() */
|
||||
virtual void gap() override;
|
||||
/** see fl_circle() */
|
||||
virtual void circle(double x, double y, double r) override;
|
||||
// --- implementation is in src/fl_arc.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arc.cxx if needed
|
||||
virtual void arc(double x, double y, double r, double start, double end) override { super::arc(x, y, r, start, end); }
|
||||
// --- implementation is in src/fl_arci.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arci.cxx
|
||||
/** see fl_arc(int x, int y, int w, int h, double a1, double a2) */
|
||||
virtual void arc(int x, int y, int w, int h, double a1, double a2) override;
|
||||
/** see fl_pie() */
|
||||
virtual void pie(int x, int y, int w, int h, double a1, double a2) override;
|
||||
// --- implementation is in src/fl_curve.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_curve.cxx if needed
|
||||
// super: virtual void curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3, double Y3);
|
||||
// --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
|
||||
// TODO: line_style()
|
||||
/** see fl_line_style() */
|
||||
virtual void line_style(int style, int width=0, char* dashes=0) override;
|
||||
// --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
|
||||
/** see fl_color(Fl_Color) */
|
||||
virtual void color(Fl_Color c) override { super::color(c); }
|
||||
virtual void set_color(Fl_Color i, unsigned int c) override;
|
||||
// super: virtual void free_color(Fl_Color i, int overlay);
|
||||
/** see fl_color(void) */
|
||||
virtual Fl_Color color() override { return super::color(); }
|
||||
/** see fl_color(uchar, uchar, uchar) */
|
||||
virtual void color(uchar r, uchar g, uchar b) override;
|
||||
/** see fl_draw(const char *str, int n, int x, int y) */
|
||||
virtual void draw(const char *str, int n, int x, int y) override;
|
||||
/** Draw the first \p n bytes of the string \p str starting at position \p x , \p y */
|
||||
// super: virtual void draw(const char *str, int n, float x, float y);
|
||||
/** see fl_draw(int angle, const char *str, int n, int x, int y) */
|
||||
// TODO: drawing text at an angle is not supported
|
||||
virtual void draw(int angle, const char *str, int n, int x, int y) override { draw(str, n, x, y); }
|
||||
/** see fl_rtl_draw(const char *str, int n, int x, int y) */
|
||||
// TODO: drawing text right-to-left is not supported
|
||||
virtual void rtl_draw(const char *str, int n, int x, int y) override { draw(str, n, x, y); }
|
||||
/** Returns non-zero if the graphics driver possesses the \p feature */
|
||||
// super: virtual int has_feature(driver_feature feature)
|
||||
/** see fl_font(Fl_Font, Fl_Fontsize) */
|
||||
virtual void font(Fl_Font face, Fl_Fontsize fsize) override;
|
||||
/** see fl_font(void) */
|
||||
virtual Fl_Font font() override { return super::font(); }
|
||||
/** Return the current font size */
|
||||
virtual Fl_Fontsize size() override;
|
||||
/** Compute the width of the first \p n bytes of the string \p str if drawn with current font */
|
||||
virtual double width(const char *str, int n) override;
|
||||
/** Compute the width of Unicode character \p c if drawn with current font */
|
||||
virtual double width(unsigned int c) override;
|
||||
virtual void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h) override;
|
||||
/** Return the current line height */
|
||||
virtual int height() override;
|
||||
/** Return the current line descent */
|
||||
virtual int descent() override;
|
||||
/** Return the current Fl_Font_Descriptor */
|
||||
// super: inline Fl_Font_Descriptor *font_descriptor() { return font_descriptor_;}
|
||||
/** Set the current Fl_Font_Descriptor */
|
||||
// super: virtual void font_descriptor(Fl_Font_Descriptor *d) { font_descriptor_ = d;}
|
||||
#if 0
|
||||
// FIXME: do we need to implement any of the functions below?
|
||||
/** Sets the value of the driver-specific graphics context. */
|
||||
virtual void gc(void*) {}
|
||||
/** Returns the driver-specific graphics context, of NULL if there's none. */
|
||||
virtual void *gc(void) {return NULL;}
|
||||
/** Support for pixmap drawing */
|
||||
virtual uchar **mask_bitmap() { return 0; }
|
||||
/** Support for pixmap drawing */
|
||||
virtual void mask_bitmap(uchar **) {}
|
||||
#endif
|
||||
// default implementation may be enough
|
||||
/** Support for PostScript drawing */
|
||||
virtual float scale_font_for_PostScript(Fl_Font_Descriptor *desc, int s) override { return float(s); }
|
||||
// default implementation may be enough
|
||||
/** Support for PostScript drawing - no documentation found on this call*/
|
||||
// super: virtual float scale_bitmap_for_PostScript() { return 2; }
|
||||
// super: virtual void set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win);
|
||||
// super: virtual void reset_spot();
|
||||
// each platform implements these 3 functions its own way
|
||||
/* TODO: Android: we can implement this to have a redraw region based on Fl::damage
|
||||
* calls. Currently, we do not implement damage regions, but we can probably
|
||||
* implement this using our clipping regions. This may become neccesary when
|
||||
* we allow desktop-style window movement.
|
||||
*/
|
||||
// super: virtual void add_rectangle_to_region(Fl_Region r, int x, int y, int w, int h);
|
||||
// super: virtual Fl_Region XRectangleRegion(int x, int y, int w, int h);
|
||||
// super: virtual void XDestroyRegion(Fl_Region r);
|
||||
/** Support for Fl::get_font_name() */
|
||||
virtual const char* get_font_name(Fl_Font fnum, int* ap) override;
|
||||
/** Support for Fl::get_font_sizes() */
|
||||
virtual int get_font_sizes(Fl_Font fnum, int*& sizep) override;
|
||||
/** Support for Fl::set_fonts() */
|
||||
virtual Fl_Font set_fonts(const char *name) override;
|
||||
/** Some platforms may need to implement this to support fonts */
|
||||
// super: virtual Fl_Fontdesc* calc_fl_fonts(void) {return NULL;}
|
||||
/** Support for Fl::set_font() */
|
||||
// super: virtual unsigned font_desc_size();
|
||||
/** Support for Fl::get_font() */
|
||||
virtual const char *font_name(int num) override;
|
||||
/** Support for Fl::set_font() */
|
||||
virtual void font_name(int num, const char *name) override;
|
||||
/** Support function for fl_overlay_rect() and scaled GUI.
|
||||
Defaut implementation may be enough */
|
||||
// super: virtual void overlay_rect(int x, int y, int w , int h) { loop(x, y, x+w-1, y, x+w-1, y+h-1, x, y+h-1); }
|
||||
// --- end of original Fl_Graphics_Driver header -----------------------------
|
||||
|
||||
// --- start of Android additions --------------------------------------------
|
||||
// start drawing with this driver into the given window
|
||||
// The virtual call `set_current_()` changes surface, not windows
|
||||
void make_current(Fl_Window*);
|
||||
|
||||
protected:
|
||||
static uint16_t make565(uchar r, uchar g, uchar b);
|
||||
static uint16_t make565(Fl_Color crgba);
|
||||
void rectf_unclipped(int x, int y, int w, int h);
|
||||
void xyline_unclipped(int x, int y, int x1);
|
||||
void yxline_unclipped(int x, int y, int y1);
|
||||
void end_polygon(int begin, int end);
|
||||
void ellipse(double xt, double yt, double rx, double ry);
|
||||
void draw(int xx, int yy, Fl_Android_565A_Map *bm, Fl_Rect_Region &r);
|
||||
void draw(int x, int y, Fl_Android_Bytemap *bm, Fl_Rect_Region &r);
|
||||
int render_letter(int xx, int yy, uint32_t c, Fl_Rect_Region &r);
|
||||
|
||||
// pointer into the screen buffer at the top left corner of the current window
|
||||
uint16_t *pBits = nullptr;
|
||||
|
||||
// advance to next line in screen buffer
|
||||
int32_t pStride = 0;
|
||||
|
||||
// TODO: current line style, temp kludge to make focus rect work.
|
||||
int pLineStyle = 0;
|
||||
|
||||
// Clipping region of the current window in window coordinates (see: pStride and pBits)
|
||||
Fl_Rect_Region pWindowRegion;
|
||||
|
||||
// clipping region of the window minus overlapping other windows
|
||||
Fl_Complex_Region pDesktopWindowRegion;
|
||||
|
||||
// Final clipping region for all graphics calls to this class.
|
||||
Fl_Complex_Region pClippingRegion;
|
||||
|
||||
// store vertices for begin_.../end_... drawing
|
||||
class Vertex {
|
||||
public:
|
||||
void set(float x, float y, bool gap = false) { pX = x; pY = y; pIsGap = gap; }
|
||||
float pX, pY;
|
||||
bool pIsGap;
|
||||
};
|
||||
|
||||
void begin_vertices();
|
||||
void add_vertex(float x, float y, bool gap=false);
|
||||
int pnVertex = 0, pNVertex = 0, pVertexGapStart = 0;
|
||||
Vertex *pVertex = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#if 0
|
||||
/**
|
||||
The graphics driver used when printing on Android.
|
||||
*/
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif // FL_ANDROID_GRAPHICS_DRIVER_H
|
File diff suppressed because it is too large
Load Diff
@ -1,132 +0,0 @@
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
#ifndef FL_ANDROID_GRAPHICS_FONT_H
|
||||
#define FL_ANDROID_GRAPHICS_FONT_H
|
||||
|
||||
|
||||
#include "Fl_Android_Graphics_Driver.H"
|
||||
|
||||
// We violate FLTKs avoidance of STL because we live in a defined driver space
|
||||
#define FL_ALLOW_STL 1
|
||||
#ifdef FL_ALLOW_STL
|
||||
#include <map>
|
||||
#endif
|
||||
|
||||
#include "stb_truetype.h"
|
||||
|
||||
|
||||
/**
|
||||
A bytemap is an array of bytes, used as an alpha channel when redering glyphs
|
||||
in a given color.
|
||||
TODO: reate a class for RGB only and for grayscale and grayscale with alpha
|
||||
TODO: derive all this from a baseclass, so we can create the correct class for the required image
|
||||
*/
|
||||
class Fl_Android_Bytemap
|
||||
{
|
||||
public:
|
||||
Fl_Android_Bytemap();
|
||||
Fl_Android_Bytemap(int w, int h);
|
||||
~Fl_Android_Bytemap();
|
||||
|
||||
public:
|
||||
int pWidth = 0, pHeight = 0, pStride = 0;
|
||||
int pXOffset = 0, pYOffset = 0, pAdvance = 0;
|
||||
unsigned char *pBytes = nullptr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
A 565a map is an array of words for interleaved RGB and Alpha data.
|
||||
565 is the number of bit per component, compatible with our screen memory
|
||||
scheme. The second word is actually a byt containing the alpha value for
|
||||
the previous pixel: rrrrrggg.gggbbbbb.aaaaaaaa.00000000
|
||||
*/
|
||||
class Fl_Android_565A_Map
|
||||
{
|
||||
public:
|
||||
Fl_Android_565A_Map();
|
||||
Fl_Android_565A_Map(int w, int h);
|
||||
~Fl_Android_565A_Map();
|
||||
static inline uint32_t toRGBA(uchar r, uchar g, uchar b, uchar a)
|
||||
{
|
||||
return ((((r << 8) & 0xf800) |
|
||||
((g << 3) & 0x07e0) |
|
||||
((b >> 3) & 0x001f)) << 16) | a;
|
||||
}
|
||||
|
||||
public:
|
||||
int pWidth = 0, pHeight = 0, pStride = 0;
|
||||
int pXOffset = 0, pYOffset = 0;
|
||||
uint32_t *pWords = nullptr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
This class reads True Type Font files and creates Bytemaps for glyphs at the
|
||||
requested height.
|
||||
*/
|
||||
class Fl_Android_Font_Source
|
||||
{
|
||||
private:
|
||||
stbtt_fontinfo pFont;
|
||||
uint8_t *pFileBuffer;
|
||||
const char *pName;
|
||||
Fl_Font pFontIndex;
|
||||
bool pError;
|
||||
|
||||
bool load_font(const char *name);
|
||||
bool load_font_file(const char *name);
|
||||
bool load_font_asset(const char *name);
|
||||
|
||||
public:
|
||||
Fl_Android_Font_Source(const char *fname, Fl_Font fnum);
|
||||
~Fl_Android_Font_Source();
|
||||
void load_font();
|
||||
Fl_Android_Bytemap *get_bytemap(uint32_t c, int size);
|
||||
float get_advance(uint32_t c, Fl_Fontsize size);
|
||||
int get_descent(Fl_Fontsize size);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
This class caches glyphs of a font for a specified height.
|
||||
*/
|
||||
class Fl_Android_Font_Descriptor : public Fl_Font_Descriptor
|
||||
{
|
||||
#ifdef FL_ALLOW_STL
|
||||
typedef std::map<uint32_t, Fl_Android_Bytemap*> BytemapTable;
|
||||
#else
|
||||
typedef Fl_Android_Bytemap* BytemapTable[256];
|
||||
#endif
|
||||
private:
|
||||
Fl_Android_Font_Source *pFontSource;
|
||||
Fl_Font pFontIndex;
|
||||
BytemapTable pBytemapTable;
|
||||
|
||||
public:
|
||||
Fl_Android_Font_Descriptor(const char *fname, Fl_Android_Font_Source *fsrc, Fl_Font fnum, Fl_Fontsize size);
|
||||
~Fl_Android_Font_Descriptor();
|
||||
float get_advance(uint32_t c);
|
||||
Fl_Android_Bytemap *get_bytemap(uint32_t c);
|
||||
Fl_Android_Font_Source *get_font_source() { return pFontSource; }
|
||||
int get_descent();
|
||||
|
||||
static Fl_Android_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size);
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_ANDROID_GRAPHICS_FONT_H
|
@ -1,797 +0,0 @@
|
||||
//
|
||||
// Graphics 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include "Fl_Android_Graphics_Font.H"
|
||||
#include "Fl_Android_Application.H"
|
||||
#include <FL/fl_draw.H>
|
||||
#include <errno.h>
|
||||
#include <FL/filename.H>
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
|
||||
#include "stb_truetype.h"
|
||||
|
||||
|
||||
//struct Fl_Fontdesc {
|
||||
// const char *name;
|
||||
// char fontname[128]; // "Pretty" font name
|
||||
// Fl_Font_Descriptor *first; // linked list of sizes of this style
|
||||
//};
|
||||
|
||||
|
||||
/**
|
||||
- font names starting with a $ will have the system font path inserted
|
||||
- font names starting with an @ will be loaded via the Asset Manager
|
||||
- all other names will be used verbatim
|
||||
*/
|
||||
static Fl_Fontdesc built_in_table[] = {
|
||||
{"$Roboto-Regular.ttf"},
|
||||
{"$Roboto-Bold.ttf"},
|
||||
{"$Roboto-Italic.ttf"},
|
||||
{"$Roboto-BoldItalic.ttf"},
|
||||
{"$CutiveMono.ttf"},
|
||||
{"$CutiveMono.ttf"}, // sorry no bold
|
||||
{"$CutiveMono.ttf"}, // sorry no italic
|
||||
{"$CutiveMono.ttf"}, // sorry no bold-italic
|
||||
{"$NotoSerif-Regular.ttf"},
|
||||
{"$NotoSerif-Bold.ttf"},
|
||||
{"$NotoSerif-Italic.ttf"},
|
||||
{"$NotoSerif-BoldItalic.ttf"},
|
||||
{"$Roboto-Regular.ttf"},
|
||||
{"$DroidSansMono.ttf"},
|
||||
{"$DroidSansMono.ttf"}, // sorry no bold
|
||||
{"$Roboto-Regular.ttf"},
|
||||
};
|
||||
|
||||
Fl_Fontdesc* fl_fonts = built_in_table;
|
||||
|
||||
static const char *old_font_names[] = {
|
||||
"$DroidSans.ttf", "$DroidSerif-Regular.ttf",
|
||||
"$DroidSansMono.ttf", "$DroidSansMono.ttf"
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Create an empty Bytemap.
|
||||
*/
|
||||
Fl_Android_Bytemap::Fl_Android_Bytemap()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Create an empty Bytemap.
|
||||
*/
|
||||
Fl_Android_Bytemap::Fl_Android_Bytemap(int w, int h)
|
||||
{
|
||||
pWidth = w; pStride = w; pHeight = h;
|
||||
pBytes = (unsigned char *)calloc(w, h);
|
||||
}
|
||||
|
||||
/**
|
||||
Destroy the Bytemap and its allocated resources.
|
||||
*/
|
||||
Fl_Android_Bytemap::~Fl_Android_Bytemap()
|
||||
{
|
||||
if (pBytes) ::free(pBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
Render a bytemap to the screen using the current fl_color.
|
||||
|
||||
Bytes are seen as alpha values for the RGB color set by fl_color. For better
|
||||
performance, alpha is only rendered in 5 steps. All rendering is offset as
|
||||
described in the bytemap, and clipped to the clipping region.
|
||||
\param xx, yy bottom left position of the bytemap (baseline for text)
|
||||
\param bm bytemap including offsets and size
|
||||
\param r clipping rectangle
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::draw(int xx, int yy, Fl_Android_Bytemap *bm,
|
||||
Fl_Rect_Region &r)
|
||||
{
|
||||
xx += bm->pXOffset; yy += bm->pYOffset;
|
||||
|
||||
if (xx>r.right()) return;
|
||||
if (yy>r.bottom()) return;
|
||||
if (xx+bm->pWidth < r.left()) return;
|
||||
if (yy+bm->pHeight < r.top()) return;
|
||||
|
||||
uint16_t cc = make565(fl_color()), cc12 = (cc&0xf7de)>>1, cc14 = (cc12&0xf7de)>>1, cc34 = cc12+cc14;
|
||||
int32_t ss = pStride;
|
||||
uint16_t *bits = pBits;
|
||||
uint32_t ww = bm->pWidth;
|
||||
uint32_t hh = bm->pHeight;
|
||||
unsigned char *srcBytes = bm->pBytes;
|
||||
|
||||
int dx = r.left()-xx;
|
||||
int dy = r.top()-yy;
|
||||
int dr = (xx+ww)-r.right();
|
||||
int db = (yy+hh)-r.bottom();
|
||||
if (dx>0) { xx+=dx; ww-=dx; srcBytes+=dx; }
|
||||
if (dy>0) { yy+=dy; hh-=dy; srcBytes+=dy*bm->pStride; }
|
||||
if (dr>0) { ww-=dr; }
|
||||
if (db>0) { hh-=db; }
|
||||
|
||||
for (uint32_t iy = 0; iy<hh; ++iy) {
|
||||
uint16_t *d = bits + (yy+iy)*ss + xx;
|
||||
unsigned char *s = srcBytes + iy*bm->pStride;
|
||||
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&(uint16_t(0xe79c)))>>2;
|
||||
*d = nn14 + cc34;
|
||||
} else if (v<100) { // 25%
|
||||
uint16_t nn = *d, nn12 = (nn&(uint16_t(0xf7de)))>>1, nn14 = (nn12&(uint16_t(0xf7de)))>>1, nn34 = nn12+nn14;
|
||||
*d = nn34 + cc14;
|
||||
} else { // 50%
|
||||
uint16_t nn = *d, nn12 = (nn&(uint16_t(0xf7de)))>>1;
|
||||
*d = nn12 + cc12;
|
||||
}
|
||||
#else
|
||||
// pure black and white
|
||||
if (*s++ > 128)
|
||||
*d = cc;
|
||||
#endif
|
||||
d++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Create an empty image.
|
||||
All initialisation of members is done in-lin (C++11)
|
||||
*/
|
||||
Fl_Android_565A_Map::Fl_Android_565A_Map()
|
||||
{
|
||||
}
|
||||
|
||||
Fl_Android_565A_Map::Fl_Android_565A_Map(int w, int h)
|
||||
{
|
||||
pWidth = w; pStride = w; pHeight = h;
|
||||
pWords = (uint32_t*)calloc(4, w*h);
|
||||
}
|
||||
|
||||
Fl_Android_565A_Map::~Fl_Android_565A_Map()
|
||||
{
|
||||
if (pWords) ::free(pWords);
|
||||
}
|
||||
|
||||
/**
|
||||
Render a bytemap to the screen using the current fl_color.
|
||||
|
||||
Bytes are seen as alpha values for the RGB color set by fl_color. For better
|
||||
performance, alpha is only rendered in 5 steps. All rendering is offset as
|
||||
described in the bytemap, and clipped to the clipping region.
|
||||
\param xx, yy bottom left position of the bytemap (baseline for text)
|
||||
\param bm bytemap including offsets and size
|
||||
\param r clipping rectangle
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::draw(int xx, int yy, Fl_Android_565A_Map *bm,
|
||||
Fl_Rect_Region &r)
|
||||
{
|
||||
xx += bm->pXOffset; yy += bm->pYOffset;
|
||||
|
||||
if (xx>r.right()) return;
|
||||
if (yy>r.bottom()) return;
|
||||
if (xx+bm->pWidth < r.left()) return;
|
||||
if (yy+bm->pHeight < r.top()) return;
|
||||
|
||||
uint16_t cc = make565(fl_color()); // TODO: alpha: , cc12 = (cc&0xf7de)>>1, cc14 = (cc12&0xf7de)>>1, cc34 = cc12+cc14;
|
||||
int32_t ss = pStride;
|
||||
uint16_t *bits = pBits;
|
||||
uint32_t ww = bm->pWidth;
|
||||
uint32_t hh = bm->pHeight;
|
||||
uint32_t *srcWords = bm->pWords;
|
||||
|
||||
int dx = r.left()-xx;
|
||||
int dy = r.top()-yy;
|
||||
int dr = (xx+ww)-r.right();
|
||||
int db = (yy+hh)-r.bottom();
|
||||
if (dx>0) { xx+=dx; ww-=dx; srcWords+=dx; }
|
||||
if (dy>0) { yy+=dy; hh-=dy; srcWords+=dy*bm->pStride; }
|
||||
if (dr>0) { ww-=dr; }
|
||||
if (db>0) { hh-=db; }
|
||||
|
||||
for (uint32_t iy = 0; iy<hh; ++iy) {
|
||||
uint16_t *d = bits + (yy+iy)*ss + xx;
|
||||
uint32_t *s = srcWords + iy*bm->pStride;
|
||||
for (uint32_t ix = 0; ix<ww; ++ix) {
|
||||
uint32_t c = *s++;
|
||||
uint8_t alpha = c;
|
||||
if (alpha>0) {
|
||||
uint16_t rgb = c >> 16;
|
||||
// TODO: alpha blending: *d = rgb*a + (*d)*(1-a);
|
||||
*d = rgb;
|
||||
}
|
||||
d++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Create a True Type font manager.
|
||||
\param fname the name of the font as it appears in the fl_fonts table.
|
||||
\param fnum the index into the fl_fonts table
|
||||
*/
|
||||
Fl_Android_Font_Source::Fl_Android_Font_Source(const char *fname, Fl_Font fnum) :
|
||||
pFileBuffer(nullptr),
|
||||
pName(fname),
|
||||
pFontIndex(fnum),
|
||||
pError(false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Release all resources.
|
||||
*/
|
||||
Fl_Android_Font_Source::~Fl_Android_Font_Source()
|
||||
{
|
||||
if (pFileBuffer) ::free(pFileBuffer);
|
||||
// pFont does not allocate any buffers and needs no destructor
|
||||
}
|
||||
|
||||
/**
|
||||
Attempt to find an load a font file.
|
||||
\param name file or asset name
|
||||
\return
|
||||
*/
|
||||
bool Fl_Android_Font_Source::load_font(const char *name)
|
||||
{
|
||||
if (pFileBuffer) return true;
|
||||
if (!name) return false;
|
||||
bool ret = false;
|
||||
if (name[0]=='@')
|
||||
ret = load_font_asset(name+1);
|
||||
else
|
||||
ret = load_font_file(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
Attempt to load a font through the asset manager.
|
||||
\param name file or asset name
|
||||
\return
|
||||
*/
|
||||
bool Fl_Android_Font_Source::load_font_asset(const char *name)
|
||||
{
|
||||
errno = 0;
|
||||
AAssetManager *aMgr = Fl_Android_Application::get_asset_manager();
|
||||
AAsset *aFile = AAssetManager_open(aMgr, name, AASSET_MODE_STREAMING);
|
||||
if (aFile == nullptr) {
|
||||
Fl_Android_Application::log_w("Can't open font asset at '%s': ",
|
||||
name, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
size_t fsize = (size_t)AAsset_getLength(aFile);
|
||||
if (fsize == 0) {
|
||||
Fl_Android_Application::log_w("Can't read font asset at '%s': file is empty",
|
||||
name);
|
||||
AAsset_close(aFile);
|
||||
return false;
|
||||
}
|
||||
pFileBuffer = (uint8_t *)malloc(fsize);
|
||||
if (AAsset_read(aFile, pFileBuffer, fsize)<=0) {
|
||||
Fl_Android_Application::log_w("Can't read font asset at '%s': ",
|
||||
name, strerror(errno));
|
||||
free(pFileBuffer);
|
||||
pFileBuffer = 0;
|
||||
AAsset_close(aFile);
|
||||
return false;
|
||||
}
|
||||
AAsset_close(aFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Attempt to load a font through the asset manager.
|
||||
\param name file or asset name
|
||||
\return
|
||||
*/
|
||||
bool Fl_Android_Font_Source::load_font_file(const char *name)
|
||||
{
|
||||
char buf[2048];
|
||||
if (name[0] == '$') {
|
||||
// use the system path for fonts
|
||||
snprintf(buf, 2048, "/system/fonts/%s", name + 1);
|
||||
} else {
|
||||
strcpy(buf, name);
|
||||
}
|
||||
FILE *f = fopen(buf, "rb");
|
||||
if (f == nullptr) {
|
||||
Fl_Android_Application::log_w("Can't open font file at '%s': ",
|
||||
name, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t fsize = (size_t)ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
if (fsize == 0) {
|
||||
Fl_Android_Application::log_w(
|
||||
"Can't read font file at '%s': file is empty",
|
||||
name);
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
pFileBuffer = (uint8_t *)malloc(fsize);
|
||||
if (fread(pFileBuffer, 1, fsize, f)<=0) {
|
||||
Fl_Android_Application::log_w("Can't read font file at '%s': ",
|
||||
name, strerror(errno));
|
||||
free(pFileBuffer);
|
||||
pFileBuffer = 0;
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Load a True Type font file and initialize the TTF interpreter.
|
||||
A copy of the font file must remain in memory for the interpreter to work.
|
||||
*/
|
||||
void Fl_Android_Font_Source::load_font()
|
||||
{
|
||||
if (pError) return;
|
||||
if (pFileBuffer==0) {
|
||||
const char *name = fl_fonts[pFontIndex].name;
|
||||
|
||||
// first attempt, try to read a font from wherever the user wishes
|
||||
bool ret = load_font(name);
|
||||
|
||||
// if that did not work, read the old style Android fonts
|
||||
if (!ret && pFontIndex<16)
|
||||
ret = load_font(old_font_names[pFontIndex/4]);
|
||||
|
||||
// if that still didn't work, see if we have the default font asset
|
||||
if (!ret)
|
||||
ret = load_font("@fonts/Roboto-Regular.ttf");
|
||||
|
||||
// still no luck? Well, I guess we can't render anything in this font.
|
||||
if (!ret) {
|
||||
Fl_Android_Application::log_e("Giving up. Can't load font '%s'", name);
|
||||
pError = true;
|
||||
return;
|
||||
}
|
||||
stbtt_InitFont(&pFont, pFileBuffer, stbtt_GetFontOffsetForIndex(pFileBuffer,0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Return a bytemap for the give unicode character.
|
||||
\param c unicode character
|
||||
\param size height in pixels
|
||||
\return a bytemap
|
||||
*/
|
||||
Fl_Android_Bytemap *Fl_Android_Font_Source::get_bytemap(uint32_t c, int size)
|
||||
{
|
||||
if (pFileBuffer==0) load_font();
|
||||
if (pError) return nullptr;
|
||||
|
||||
Fl_Android_Bytemap *bm = new Fl_Android_Bytemap();
|
||||
|
||||
float hgt = stbtt_ScaleForPixelHeight(&pFont, size);
|
||||
bm->pBytes = stbtt_GetCodepointBitmap(&pFont, 0, hgt, c,
|
||||
&bm->pWidth, &bm->pHeight,
|
||||
&bm->pXOffset, &bm->pYOffset);
|
||||
bm->pStride = bm->pWidth;
|
||||
|
||||
int advance, lsb;
|
||||
stbtt_GetCodepointHMetrics(&pFont, c, &advance, &lsb);
|
||||
float scale = stbtt_ScaleForPixelHeight(&pFont, size);
|
||||
bm->pAdvance = (int)((scale * advance)+0.5f);
|
||||
|
||||
return bm;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the width of the character in pixels.
|
||||
This is not a good function because character advance also depends on kerning
|
||||
which takes the next character in a text line into account. Also, FLTK is
|
||||
limited to integer character positions, and so is the Android driver.
|
||||
\param c unicode character
|
||||
\param size height in pixels
|
||||
\return width in pixels to the start of the next character
|
||||
*/
|
||||
float Fl_Android_Font_Source::get_advance(uint32_t c, Fl_Fontsize size)
|
||||
{
|
||||
int advance, lsb;
|
||||
|
||||
if (pFileBuffer==0) load_font();
|
||||
if (pError) return 0.0f;
|
||||
|
||||
stbtt_GetCodepointHMetrics(&pFont, c, &advance, &lsb);
|
||||
float scale = stbtt_ScaleForPixelHeight(&pFont, size);
|
||||
return scale * advance;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Android_Font_Source::get_descent(Fl_Fontsize size)
|
||||
{
|
||||
if (pFileBuffer==0) load_font();
|
||||
if (pError) return 0.0f;
|
||||
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&pFont, &ascent, &descent, &lineGap);
|
||||
float scale = stbtt_ScaleForPixelHeight(&pFont, size);
|
||||
|
||||
return -(descent*scale-0.5f);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Create a new font descriptor.
|
||||
\param fname name of this font as in fl_fonts
|
||||
\param fsrc the font source for this font; there is one single font source
|
||||
for all hights of a single font
|
||||
\param fnum index into the fl_fonts array
|
||||
\param fsize height of font in pixels
|
||||
*/
|
||||
Fl_Android_Font_Descriptor::Fl_Android_Font_Descriptor(const char *fname, Fl_Android_Font_Source *fsrc, Fl_Font fnum, Fl_Fontsize fsize) :
|
||||
Fl_Font_Descriptor(fname, fsize),
|
||||
pFontSource(fsrc),
|
||||
pFontIndex(fnum)
|
||||
{
|
||||
descent = -1;
|
||||
if (!pFontSource) {
|
||||
pFontSource = new Fl_Android_Font_Source(fname, fnum);
|
||||
}
|
||||
// --- We probably must fill these values in:
|
||||
// Fl_Font_Descriptor *next;
|
||||
// Fl_Fontsize size; /**< font size */
|
||||
// Fl_Font_Descriptor(const char* fontname, Fl_Fontsize size);
|
||||
// FL_EXPORT ~Fl_Font_Descriptor() {}
|
||||
// short ascent, descent, q_width;
|
||||
// unsigned int listbase; // base of display list, 0 = none
|
||||
}
|
||||
|
||||
/**
|
||||
Release resources, including all cached unicode character shapes.
|
||||
*/
|
||||
Fl_Android_Font_Descriptor::~Fl_Android_Font_Descriptor()
|
||||
{
|
||||
#ifdef FL_ALLOW_STL
|
||||
// Life is easy in C++11.
|
||||
for (auto &i: pBytemapTable) {
|
||||
delete i.second; i.second = nullptr;
|
||||
}
|
||||
#else
|
||||
for (int i=0; i<256; i++) {
|
||||
if (pBytemapTable[i]) delete pBytemapTable[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
Get the width of the character in pixels.
|
||||
\param c unicode character
|
||||
\return width in pixels to the start of the next character
|
||||
*/
|
||||
float Fl_Android_Font_Descriptor::get_advance(uint32_t c)
|
||||
{
|
||||
// TODO: should we use the cached value in the Bytemap?
|
||||
// Yes, we should, because if FLTK requests the width of a character, it is
|
||||
// more than likely to render that character soon after.
|
||||
return pFontSource->get_advance(c, size);
|
||||
}
|
||||
|
||||
/**
|
||||
Get the pixels for a given Unicode character.
|
||||
|
||||
Calculating a bitmap is relatively expensive. This class will cache every
|
||||
bitmap ever generated. Currently, this is pretty much brute force because
|
||||
none of the bitmaps are ever released.
|
||||
|
||||
\param c unicode character
|
||||
\return a bytemap
|
||||
*/
|
||||
Fl_Android_Bytemap *Fl_Android_Font_Descriptor::get_bytemap(uint32_t c)
|
||||
{
|
||||
Fl_Android_Bytemap *bm = 0;
|
||||
#ifdef FL_ALLOW_STL
|
||||
auto it = pBytemapTable.find(c);
|
||||
if (it==pBytemapTable.end()) {
|
||||
bm = pFontSource->get_bytemap(c, size);
|
||||
if (bm)
|
||||
pBytemapTable[c] = bm;
|
||||
} else {
|
||||
bm = it->second;
|
||||
}
|
||||
#else
|
||||
if (c<256) {
|
||||
if (pBytemapTable[c]) {
|
||||
bm = pBytemapTable[c];
|
||||
} else {
|
||||
bm = pFontSource->get_bytemap(c, size);
|
||||
if (bm)
|
||||
pBytemapTable[c] = bm;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return bm;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Android_Font_Descriptor::get_descent()
|
||||
{
|
||||
if (descent==-1)
|
||||
descent = (short)pFontSource->get_descent(size);
|
||||
return descent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Find or create a font descriptor for a given font and height.
|
||||
\param fnum index into fl_fonts
|
||||
\param size height in pixels
|
||||
\return an existing oder newly created descriptor
|
||||
*/
|
||||
Fl_Android_Font_Descriptor* Fl_Android_Font_Descriptor::find(Fl_Font fnum, Fl_Fontsize size)
|
||||
{
|
||||
Fl_Fontdesc &s = fl_fonts[fnum];
|
||||
if (!s.name) s = fl_fonts[0]; // use 0 if fnum undefined
|
||||
|
||||
Fl_Font_Descriptor *f;
|
||||
for (f = s.first; f; f = f->next) {
|
||||
if (f->size==size) return (Fl_Android_Font_Descriptor*)f;
|
||||
}
|
||||
|
||||
Fl_Android_Font_Source *fsrc = nullptr;
|
||||
if (s.first) fsrc = ((Fl_Android_Font_Descriptor*)s.first)->get_font_source();
|
||||
|
||||
Fl_Android_Font_Descriptor *af = new Fl_Android_Font_Descriptor(s.name, fsrc, fnum, size);
|
||||
af->next = s.first;
|
||||
s.first = af;
|
||||
return af;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
Set a font for future use in text rendering calls.
|
||||
\param fnum index into fl_fonts
|
||||
\param size height in pixels
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::font(Fl_Font fnum, Fl_Fontsize size) {
|
||||
font_descriptor( Fl_Android_Font_Descriptor::find(fnum, size) );
|
||||
size_ = size;
|
||||
font_ = fnum;
|
||||
}
|
||||
|
||||
/**
|
||||
Copy a single letter to the screen.
|
||||
\param xx, yy position of character on screen
|
||||
\param c unicode character
|
||||
\return x position of next character on screen
|
||||
*/
|
||||
int Fl_Android_Graphics_Driver::render_letter(int xx, int yy, uint32_t c, Fl_Rect_Region &r)
|
||||
{
|
||||
int oxx = xx;
|
||||
|
||||
// find the font descriptor
|
||||
Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
|
||||
if (!fd) return xx; // this should not happen
|
||||
|
||||
Fl_Android_Bytemap *bm = fd->get_bytemap(c);
|
||||
if (!bm) return oxx;
|
||||
|
||||
draw(xx, yy, bm, r);
|
||||
|
||||
return oxx + bm->pAdvance;
|
||||
}
|
||||
|
||||
/**
|
||||
Render a string to screen.
|
||||
\param str text in utf-8 encoding
|
||||
\param n number of bytes to render
|
||||
\param x, y position on screen
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::draw(const char* str, int n, int x, int y)
|
||||
{
|
||||
if (str) {
|
||||
int dx, dy, w, h;
|
||||
text_extents(str, n, dx, dy, w, h);
|
||||
//pClippingRegion.print("<---- clip text to this");
|
||||
//Fl_Rect_Region(x+dx, y+dy, w, h).print(str);
|
||||
for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(x+dx, y+dy, w, h))) {
|
||||
Fl_Rect_Region &r = it->clipped_rect();
|
||||
//r.print("Clip");
|
||||
const char *e = str + n;
|
||||
for (int i = 0; i < n;) {
|
||||
int incr = 1;
|
||||
unsigned uniChar = fl_utf8decode(str + i, e, &incr);
|
||||
int x1 = x;
|
||||
x = render_letter(x, y, uniChar, r);
|
||||
#if 0
|
||||
// use this to make the character baseline visible
|
||||
Fl_Color old = fl_color();
|
||||
fl_color(FL_RED);
|
||||
fl_xyline(x1, y, x);
|
||||
fl_yxline(x1, y-5, y+5);
|
||||
fl_color(old);
|
||||
#endif
|
||||
i += incr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double Fl_Android_Graphics_Driver::width(const char *str, int n)
|
||||
{
|
||||
Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
|
||||
if (!fd) return 0;
|
||||
|
||||
int width = 0;
|
||||
const char *e = str+n;
|
||||
for (int i=0; i<n; ) {
|
||||
int incr = 1;
|
||||
unsigned uniChar = fl_utf8decode(str + i, e, &incr);
|
||||
width += ((int)(fd->get_advance(uniChar)+0.5f));
|
||||
i += incr;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
double Fl_Android_Graphics_Driver::width(unsigned int uniChar)
|
||||
{
|
||||
Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
|
||||
if (!fd) return 0;
|
||||
return ((int)(fd->get_advance(uniChar)+0.5f));
|
||||
}
|
||||
|
||||
|
||||
Fl_Fontsize Fl_Android_Graphics_Driver::size()
|
||||
{
|
||||
Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
|
||||
if (!fd) return 0;
|
||||
return fd->size;
|
||||
}
|
||||
|
||||
/**
|
||||
FIXME: use the actual size of all glyphs, which is easily found in the Bytemap!
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::text_extents(const char *str, int n, int &dx, int &dy, int &w, int &h)
|
||||
{
|
||||
w = width(str, n);
|
||||
h = height();
|
||||
dx = 0;
|
||||
dy = descent() - h;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Android_Graphics_Driver::height()
|
||||
{
|
||||
// This should really be "ascent - descent + lineGap"
|
||||
Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
|
||||
if (!fd) return 0;
|
||||
return fd->size;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Android_Graphics_Driver::descent()
|
||||
{
|
||||
Fl_Android_Font_Descriptor *fd = (Fl_Android_Font_Descriptor*)font_descriptor();
|
||||
if (!fd) return 0;
|
||||
if (fd->descent==-1) fd->get_descent();
|
||||
return fd->descent;
|
||||
}
|
||||
|
||||
/**
|
||||
Get a human-readable string describing the family of this face.
|
||||
\param fnum index into font table
|
||||
\param ap[out] returns if the face is bold or italic or both.
|
||||
\return pointer to a string; don't free, don't write
|
||||
*/
|
||||
const char *Fl_Android_Graphics_Driver::get_font_name(Fl_Font fnum, int* ap)
|
||||
{
|
||||
const char *name = fl_fonts[fnum].name;
|
||||
if (ap) {
|
||||
*ap = 0;
|
||||
if (strstr(name, "BoldItalic")) *ap = FL_BOLD_ITALIC;
|
||||
else if (strstr(name, "Bold")) *ap = FL_BOLD;
|
||||
else if (strstr(name, "Italic")) *ap = FL_ITALIC;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
Gets the string for this face.
|
||||
\param num index into font table
|
||||
\return pointer to a string; don't free, don't write
|
||||
*/
|
||||
const char *Fl_Android_Graphics_Driver::font_name(int num)
|
||||
{
|
||||
// TODO: we should probably beatify the font name, remove file path and
|
||||
// extension, and save the result in fl_fonts[num].fontname ...
|
||||
return fl_fonts[num].name;
|
||||
}
|
||||
|
||||
/**
|
||||
Return an array of sizes in sizep.
|
||||
\param fnum index into font table
|
||||
\param sizep[out] a static array that contains the single value 0, indicating
|
||||
that all fonts are arbitrarily resizable.
|
||||
\return 1, because our array has a size of 1
|
||||
*/
|
||||
int Fl_Android_Graphics_Driver::get_font_sizes(Fl_Font fnum, int*& sizep)
|
||||
{
|
||||
static int sSizes[] = { 0 };
|
||||
sizep = sSizes;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
FLTK will open the display, and add every fonts on the server to the face table.
|
||||
TODO: This is not supported under Android.
|
||||
\param name basically a wildcard for finding fonts
|
||||
\return number of fonts found
|
||||
*/
|
||||
Fl_Font Fl_Android_Graphics_Driver::set_fonts(const char *name)
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
/**
|
||||
Changes a face.
|
||||
\param num index of the font
|
||||
\param name Path to font file, prepend $ for system fonts, @ for font assets.
|
||||
The string pointer is simply stored, the string is not copied, so the
|
||||
string must be in static memory.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::font_name(int num, const char *name)
|
||||
{
|
||||
Fl_Fontdesc *s = fl_fonts + num;
|
||||
|
||||
// if the same font is requested, do nothing
|
||||
if (s && s->name && name && strcmp(s->name, name)==0) {
|
||||
s->name = name;
|
||||
return;
|
||||
}
|
||||
|
||||
// if a font is loaded, delete the all descriptors, caches, and the source
|
||||
Fl_Android_Font_Descriptor *desc = (Fl_Android_Font_Descriptor*)s->first;
|
||||
if (desc) {
|
||||
Fl_Android_Font_Source *src = desc->get_font_source();
|
||||
while (desc) {
|
||||
auto nDesc = (Fl_Android_Font_Descriptor*)desc->next;
|
||||
delete desc; desc = nDesc;
|
||||
}
|
||||
delete src; src = nullptr;
|
||||
}
|
||||
s->name = nullptr;
|
||||
s->fontname[0] = 0;
|
||||
s->first = nullptr;
|
||||
|
||||
// set the new font name
|
||||
if (name) {
|
||||
// the next time the font is used, it will be loaded and initialized
|
||||
s->name = name;
|
||||
s->fontname[0] = 0;
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
//
|
||||
// Draw-to-image code for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.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();
|
||||
POINT origin;
|
||||
#endif
|
||||
void set_current() override { } // TODO: write me
|
||||
void translate(int x, int y) override { } // TODO: write me
|
||||
void untranslate() override { } // TODO: write me
|
||||
Fl_RGB_Image *image() override { return nullptr; } // TODO: write me
|
||||
};
|
||||
|
||||
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
|
@ -1,176 +0,0 @@
|
||||
//
|
||||
// Definition of Android screen interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_Android_Screen_Driver.H
|
||||
\brief Definition of Android screen interface.
|
||||
*/
|
||||
|
||||
#ifndef FL_ANDROID_SCREEN_DRIVER_H
|
||||
#define FL_ANDROID_SCREEN_DRIVER_H
|
||||
|
||||
#include "../../Fl_Screen_Driver.H"
|
||||
#include <FL/Fl_Rect.H>
|
||||
#include <android/input.h>
|
||||
//#include <windows.h>
|
||||
|
||||
extern void (*fl_unlock_function)();
|
||||
extern void (*fl_lock_function)();
|
||||
|
||||
|
||||
class Fl_Window;
|
||||
|
||||
|
||||
class FL_EXPORT Fl_Android_Screen_Driver : public Fl_Screen_Driver
|
||||
{
|
||||
// easy access to the super class
|
||||
typedef Fl_Screen_Driver super;
|
||||
|
||||
#if 0
|
||||
// No, this is not how we will implement this.
|
||||
enum {
|
||||
/// request attribute for a specific screen; default to screen 0
|
||||
INDEX = 0x0001, // add an integer in the vararg list
|
||||
/// allow or lock screen rotation
|
||||
ROTATION_MASK = 0x0006, ROTATION_KEEP = 0x0000,
|
||||
MAY_ROTATE = 0x0006, LOCK_TO_PORTRAIT = 0x0002, LOCK_TO_LANDSCAPE = 0x0004,
|
||||
/// screen size
|
||||
SIZE_MASK = 0x0038, SIZE_KEEP = 0x0000,
|
||||
NATIVE_SIZE = 0x0008, // keep the full native screen size
|
||||
FIRST_WINDOW = 0x0010, // adapt the screen to the size of the first window
|
||||
ALL_WINDOWS = 0x0018, // adapt the screen to show all windows
|
||||
FIXED_DIAGONAL = 0x0020, // keep aspect ration at 1:1, add an int for the length of the diagonal
|
||||
// fixed size override the previous flags for portrait and/or landscape
|
||||
FIXED_PORTRAIT_SIZE = 0x0040, // add two int width and height
|
||||
NO_FIXED_PORTRAIT_SIZE = 0x80000040, // release fixed portrait size
|
||||
FIXED_LANDSCAPE_SIZE = 0x0080, // add two int width and height
|
||||
NO_FIXED_LANDSCAPE_SIZE = 0x80000080, // release fixed landscape size
|
||||
// show or hide mobile device screen items
|
||||
SHOW_STATUS_BAR = 0x0080, // top of the screen
|
||||
HIDE_STATUS_BAR = 0x80000080, // top of the screen
|
||||
SHOW_NAVIGATION_BAR = 0x0100, // bottom of the screen
|
||||
HIDE_NAVIGATION_BAR = 0x0100, // bottom of the screen
|
||||
};
|
||||
/// request some attributes from a screen that may or may not be met
|
||||
virtual hint(unsigned int flags, ...);
|
||||
#endif
|
||||
|
||||
|
||||
private:
|
||||
int handle_queued_events(double time_to_wait);
|
||||
int handle_app_command();
|
||||
int handle_input_event();
|
||||
int handle_keyboard_event(AInputQueue*, AInputEvent*);
|
||||
int handle_mouse_event(AInputQueue*, AInputEvent*);
|
||||
|
||||
public:
|
||||
Fl_Android_Screen_Driver();
|
||||
|
||||
virtual void add_timeout(double time, Fl_Timeout_Handler cb, void *argp) override;
|
||||
virtual void repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) override;
|
||||
virtual int has_timeout(Fl_Timeout_Handler cb, void *argp) override;
|
||||
virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp) override;
|
||||
|
||||
virtual int compose(int &del) override;
|
||||
|
||||
virtual void request_keyboard() override;
|
||||
virtual void release_keyboard() override;
|
||||
int pKeyboardCount = 0;
|
||||
|
||||
#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();
|
||||
#endif
|
||||
virtual int x() override { return 0; } // FIXME:
|
||||
virtual int y() override { return 0; } // FIXME:
|
||||
virtual int w() override { return 600; } // FIXME:
|
||||
virtual int h() override { return 800; } // FIXME:
|
||||
virtual void screen_xywh(int &X, int &Y, int &W, int &H, int n) override
|
||||
{ X = 0; Y = 0; W = 600; H = 800; } // FIXME:
|
||||
#if 0
|
||||
virtual void screen_dpi(float &h, float &v, int n=0);
|
||||
int screen_num_unscaled(int x, int y);
|
||||
#endif
|
||||
virtual void screen_work_area(int &X, int &Y, int &W, int &H, int n) override
|
||||
{ X = 0; Y = 0; W = 600; H = 800; } // FIXME:
|
||||
// --- audible output
|
||||
virtual void beep(int type) override;
|
||||
// --- global events
|
||||
virtual void flush() override;
|
||||
virtual double wait(double time_to_wait) override;
|
||||
#if 0
|
||||
virtual int ready();
|
||||
#endif
|
||||
virtual void grab(Fl_Window* win) override;
|
||||
#if 0
|
||||
// --- global colors
|
||||
virtual void get_system_colors();
|
||||
virtual const char *get_system_scheme();
|
||||
// --- global timers
|
||||
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);
|
||||
#endif
|
||||
virtual int get_mouse(int &x, int &y) override;
|
||||
#if 0
|
||||
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
|
||||
#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
|
||||
bool pContentChanged;
|
||||
bool pClearDesktop;
|
||||
};
|
||||
|
||||
#endif // FL_ANDROID_SCREEN_DRIVER_H
|
@ -1,568 +0,0 @@
|
||||
//
|
||||
// Android screen interface 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
/**
|
||||
@cond AndroidDev
|
||||
\defgroup AndroidDeveloper Android Developer Documentation
|
||||
\{
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_Android_Screen_Driver.H"
|
||||
#include "Fl_Android_Application.H"
|
||||
#include "Fl_Android_Graphics_Font.H"
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/platform.H>
|
||||
#include <FL/Fl_Graphics_Driver.H>
|
||||
#include <FL/Fl_RGB_Image.H>
|
||||
#include <FL/fl_ask.H>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/**
|
||||
\class Fl_Android_Screen_Driver
|
||||
|
||||
Handle Android screen devices.
|
||||
|
||||
\todo This class is in an early development stage
|
||||
*/
|
||||
|
||||
|
||||
static void nothing() {}
|
||||
void (*fl_unlock_function)() = nothing;
|
||||
void (*fl_lock_function)() = nothing;
|
||||
|
||||
static void timer_do_callback(int timerIndex);
|
||||
|
||||
|
||||
/**
|
||||
Creates a driver that manages all Android screen and display related calls.
|
||||
*/
|
||||
Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver()
|
||||
{
|
||||
return new Fl_Android_Screen_Driver();
|
||||
}
|
||||
|
||||
|
||||
extern int fl_send_system_handlers(void *e);
|
||||
|
||||
|
||||
/**
|
||||
Create the screen driver.
|
||||
*/
|
||||
Fl_Android_Screen_Driver::Fl_Android_Screen_Driver() :
|
||||
super(),
|
||||
pContentChanged(false),
|
||||
pClearDesktop(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Call the FLTK System handler with Android specific events.
|
||||
|
||||
\return always 1, assuming the event was handled
|
||||
|
||||
\see Fl_Android_Platform_Event
|
||||
*/
|
||||
int Fl_Android_Screen_Driver::handle_app_command()
|
||||
{
|
||||
// get the command
|
||||
int8_t cmd = Fl_Android_Application::read_cmd();
|
||||
|
||||
// setup the Android glue and prepare all settings for calling into FLTK
|
||||
Fl_Android_Application::pre_exec_cmd(cmd);
|
||||
|
||||
// call all registered FLTK system handlers
|
||||
Fl::e_number = ((uint32_t)(cmd-Fl_Android_Application::APP_CMD_INPUT_CHANGED)) + FL_ANDROID_EVENT_INPUT_CHANGED;
|
||||
fl_send_system_handlers(nullptr);
|
||||
|
||||
// fixup and finalize application wide command handling
|
||||
Fl_Android_Application::post_exec_cmd(cmd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Android_Screen_Driver::handle_input_event()
|
||||
{
|
||||
AInputQueue *queue = Fl_Android_Application::input_event_queue();
|
||||
AInputEvent *event = nullptr;
|
||||
|
||||
if (AInputQueue_getEvent(queue, &event) >= 0) {
|
||||
if (AInputQueue_preDispatchEvent(queue, event)==0) {
|
||||
int consumed = 0;
|
||||
switch (AInputEvent_getType(event)) {
|
||||
case AINPUT_EVENT_TYPE_KEY:
|
||||
consumed = handle_keyboard_event(queue, event);
|
||||
break;
|
||||
case AINPUT_EVENT_TYPE_MOTION:
|
||||
consumed = handle_mouse_event(queue, event);
|
||||
break;
|
||||
default:
|
||||
// don't do anything. There may be additional event types in the future
|
||||
AInputQueue_finishEvent(queue, event, consumed);
|
||||
break;
|
||||
}
|
||||
// TODO: handle all events here
|
||||
// AInputQueue_finishEvent(queue, event, consumed);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Android_Screen_Driver::handle_mouse_event(AInputQueue *queue, AInputEvent *event)
|
||||
{
|
||||
int ex = Fl::e_x_root = (int)(AMotionEvent_getX(event, 0) * 600 /
|
||||
ANativeWindow_getWidth(Fl_Android_Application::native_window()));
|
||||
int ey = Fl::e_y_root = (int)(AMotionEvent_getY(event, 0) * 800 /
|
||||
ANativeWindow_getHeight(Fl_Android_Application::native_window()));
|
||||
|
||||
// FIXME: find the window in which the event happened
|
||||
Fl_Window *win = Fl::grab();
|
||||
if (!win) {
|
||||
win = Fl::first_window();
|
||||
if (win && !win->modal()) {
|
||||
while (win) {
|
||||
if (ex >= win->x() && ex < win->x() + win->w() && ey >= win->y() &&
|
||||
ey < win->y() + win->h())
|
||||
break;
|
||||
win = Fl::next_window(win);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!win) {
|
||||
AInputQueue_finishEvent(queue, event, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (win) {
|
||||
Fl::e_x = ex-win->x();
|
||||
Fl::e_y = ey-win->y();
|
||||
} else {
|
||||
Fl::e_x = ex;
|
||||
Fl::e_y = ey;
|
||||
}
|
||||
|
||||
Fl::e_state = FL_BUTTON1;
|
||||
Fl::e_keysym = FL_Button + 1;
|
||||
if (AMotionEvent_getAction(event) == AMOTION_EVENT_ACTION_DOWN) {
|
||||
AInputQueue_finishEvent(queue, event, 1);
|
||||
Fl::e_is_click = 1;
|
||||
// Fl_Android_Application::log_i("Mouse push %x %d at %d, %d", win, Fl::event_button(), Fl::event_x(), Fl::event_y());
|
||||
if (win) Fl::handle(FL_PUSH, win); // do NOT send a push event into the "Desktop"
|
||||
} else if (AMotionEvent_getAction(event) == AMOTION_EVENT_ACTION_MOVE) {
|
||||
AInputQueue_finishEvent(queue, event, 1);
|
||||
// Fl_Android_Application::log_i("Mouse drag %x %d at %d, %d", win, Fl::event_button(), Fl::event_x(), Fl::event_y());
|
||||
if (win) Fl::handle(FL_DRAG, win);
|
||||
} else if (AMotionEvent_getAction(event) == AMOTION_EVENT_ACTION_UP) {
|
||||
AInputQueue_finishEvent(queue, event, 1);
|
||||
Fl::e_state = 0;
|
||||
// Fl_Android_Application::log_i("Mouse release %x %d at %d, %d", win, Fl::event_button(), Fl::event_x(), Fl::event_y());
|
||||
if (win) Fl::handle(FL_RELEASE, win);
|
||||
} else {
|
||||
AInputQueue_finishEvent(queue, event, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Handle all events in the even queue.
|
||||
|
||||
\todo what should this function return?
|
||||
|
||||
\param time_to_wait
|
||||
\return we do not know
|
||||
*/
|
||||
int Fl_Android_Screen_Driver::handle_queued_events(double time_to_wait)
|
||||
{
|
||||
int ret = 0;
|
||||
// Read all pending events.
|
||||
int ident;
|
||||
int events;
|
||||
int delay_millis = time_to_wait*1000;
|
||||
bool done = false;
|
||||
|
||||
int delay = Fl::damage() ? 0 : delay_millis;
|
||||
while (!done) {
|
||||
ident = ALooper_pollOnce(delay, nullptr, &events, nullptr);
|
||||
switch (ident) {
|
||||
case Fl_Android_Application::LOOPER_ID_MAIN:
|
||||
ret = handle_app_command();
|
||||
break;
|
||||
case Fl_Android_Application::LOOPER_ID_INPUT:
|
||||
ret = handle_input_event();
|
||||
break;
|
||||
case Fl_Android_Application::LOOPER_ID_TIMER:
|
||||
timer_do_callback(Fl_Android_Application::receive_timer_index());
|
||||
break;
|
||||
case ALOOPER_POLL_WAKE:
|
||||
Fl_Android_Application::log_e("Someone woke up ALooper_pollOnce.");
|
||||
done = true;
|
||||
break;
|
||||
case ALOOPER_POLL_CALLBACK:
|
||||
Fl_Android_Application::log_e(
|
||||
"Someone added a callback to ALooper_pollOnce.");
|
||||
done = true;
|
||||
break;
|
||||
case ALOOPER_POLL_TIMEOUT:
|
||||
done = true; // timer expired, return to FLTK
|
||||
break;
|
||||
case ALOOPER_POLL_ERROR:
|
||||
Fl_Android_Application::log_e(
|
||||
"Something caused an ERROR in ALooper_pollOnce.");
|
||||
done = true; // return to the app to find the error
|
||||
break;
|
||||
default:
|
||||
Fl_Android_Application::log_e(
|
||||
"Unknown return value from ALooper_pollOnce.");
|
||||
done = true; // return to the app, just in case
|
||||
break;
|
||||
}
|
||||
// we need to repeat this as long as there are messages in the queue, or any
|
||||
// change in the graphical interface will trigger a redraw immediately. To
|
||||
// save time and energy, we want to collect graphics changes and execute
|
||||
// them as soon as no more events are pending.
|
||||
// Setting delay to zero on the second round makes sure that all events
|
||||
// are handled first, and the call returns only when no more
|
||||
// events are pending.
|
||||
delay = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Wait for a maximum of `time_to_wait` until something happens.
|
||||
|
||||
\param time_to_wait in seconds
|
||||
\return We really do not know; check other platforms to see what is
|
||||
consistent here.
|
||||
|
||||
\todo return the remaining time to reach 'time_to_wait'
|
||||
*/
|
||||
double Fl_Android_Screen_Driver::wait(double time_to_wait)
|
||||
{
|
||||
Fl::run_checks();
|
||||
static int in_idle = 0;
|
||||
if (Fl::idle) {
|
||||
if (!in_idle) {
|
||||
in_idle = 1;
|
||||
Fl::idle();
|
||||
in_idle = 0;
|
||||
}
|
||||
// the idle function may turn off idle, we can then wait:
|
||||
if (Fl::idle) time_to_wait = 0.0;
|
||||
}
|
||||
|
||||
if (time_to_wait==0.0) {
|
||||
// if there is no wait time, handle the event and show the results right away
|
||||
fl_unlock_function();
|
||||
handle_queued_events(time_to_wait);
|
||||
fl_lock_function();
|
||||
// FIXME: kludge to erase a window after it was hidden
|
||||
if (pClearDesktop && fl_graphics_driver) {
|
||||
((Fl_Android_Graphics_Driver*)fl_graphics_driver)->make_current(nullptr);
|
||||
fl_rectf(0, 0, 600, 800, FL_BLACK);
|
||||
pClearDesktop = false;
|
||||
pContentChanged = true;
|
||||
}
|
||||
Fl::flush();
|
||||
} else {
|
||||
// if there is wait time, show the pending changes and then handle the events
|
||||
// FIXME: kludge to erase a window after it was hidden
|
||||
if (pClearDesktop && fl_graphics_driver) {
|
||||
((Fl_Android_Graphics_Driver*)fl_graphics_driver)->make_current(nullptr);
|
||||
fl_rectf(0, 0, 600, 800, FL_BLACK);
|
||||
pClearDesktop = false;
|
||||
pContentChanged = true;
|
||||
}
|
||||
Fl::flush();
|
||||
if (Fl::idle && !in_idle) // 'idle' may have been set within flush()
|
||||
time_to_wait = 0.0;
|
||||
fl_unlock_function();
|
||||
handle_queued_events(time_to_wait);
|
||||
fl_lock_function();
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
On Android, we currently write into a memory buffer and copy
|
||||
the content to the screen.
|
||||
|
||||
\see fl_flush()
|
||||
*/
|
||||
void Fl_Android_Screen_Driver::flush()
|
||||
{
|
||||
Fl_Screen_Driver::flush();
|
||||
// FIXME: do this only if anything actually changed on screen (need to optimize)!
|
||||
if (pContentChanged) {
|
||||
if (Fl_Android_Application::copy_screen())
|
||||
pContentChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- timers -----------------------------------------------------------------
|
||||
|
||||
|
||||
struct TimerData
|
||||
{
|
||||
timer_t handle;
|
||||
struct sigevent sigevent;
|
||||
Fl_Timeout_Handler callback;
|
||||
void *data;
|
||||
bool used;
|
||||
bool triggered;
|
||||
struct itimerspec timeout;
|
||||
};
|
||||
static TimerData* timerData = nullptr;
|
||||
static int NTimerData = 0;
|
||||
static int nTimerData = 0;
|
||||
|
||||
|
||||
static int allocate_more_timers()
|
||||
{
|
||||
if (NTimerData == 0) {
|
||||
NTimerData = 8;
|
||||
}
|
||||
if (NTimerData>256) { // out of timers
|
||||
return -1;
|
||||
}
|
||||
NTimerData *= 2;
|
||||
timerData = (TimerData*)realloc(timerData, sizeof(TimerData) * NTimerData);
|
||||
return nTimerData;
|
||||
}
|
||||
|
||||
|
||||
static void timer_signal_handler(union sigval data)
|
||||
{
|
||||
int timerIndex = data.sival_int;
|
||||
Fl_Android_Application::send_timer_index(timerIndex);
|
||||
}
|
||||
|
||||
|
||||
static void timer_do_callback(int timerIndex)
|
||||
{
|
||||
TimerData& t = timerData[timerIndex];
|
||||
t.triggered = false;
|
||||
if (t.callback) {
|
||||
t.callback(t.data);
|
||||
// TODO: should we release the timer at this point?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Screen_Driver::add_timeout(double time, Fl_Timeout_Handler cb, void *data)
|
||||
{
|
||||
repeat_timeout(time, cb, data);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data)
|
||||
{
|
||||
int ret = -1;
|
||||
int timerIndex = -1;
|
||||
|
||||
// first, find the timer associated with this handler
|
||||
for (int i = 0; i < nTimerData; ++i) {
|
||||
TimerData& t = timerData[i];
|
||||
if ( (t.used) && (t.callback==cb) && (t.data==data) ) {
|
||||
timerIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we did not have a timer yet, find a free slot
|
||||
if (timerIndex==-1) {
|
||||
for (int i = 0; i < nTimerData; ++i) {
|
||||
if (!timerData[i].used)
|
||||
timerIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if that didn't work, allocate more timers
|
||||
if (timerIndex==-1) {
|
||||
if (nTimerData==NTimerData)
|
||||
allocate_more_timers();
|
||||
timerIndex = nTimerData++;
|
||||
}
|
||||
|
||||
// if that didn't work either, we ran out of timers
|
||||
if (timerIndex==-1) {
|
||||
Fl::error("FLTK ran out of timer slots.");
|
||||
return;
|
||||
}
|
||||
|
||||
TimerData& t = timerData[timerIndex];
|
||||
if (!t.used) {
|
||||
t.data = data;
|
||||
t.callback = cb;
|
||||
memset(&t.sigevent, 0, sizeof(struct sigevent));
|
||||
t.sigevent.sigev_notify = SIGEV_THREAD;
|
||||
t.sigevent.sigev_notify_function = timer_signal_handler;
|
||||
t.sigevent.sigev_value.sival_int = timerIndex;
|
||||
ret = timer_create(CLOCK_MONOTONIC, &t.sigevent, &t.handle);
|
||||
if (ret==-1) {
|
||||
Fl_Android_Application::log_e("Can't create timer: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
t.used = true;
|
||||
}
|
||||
|
||||
double ff;
|
||||
t.timeout = {
|
||||
{ 0, 0 },
|
||||
{ (time_t)floor(time), (long)(modf(time, &ff)*1000000000) }
|
||||
};
|
||||
ret = timer_settime(t.handle, 0, &t.timeout, nullptr);
|
||||
if (ret==-1) {
|
||||
Fl_Android_Application::log_e("Can't launch timer: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
t.triggered = true;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Android_Screen_Driver::has_timeout(Fl_Timeout_Handler cb, void *data)
|
||||
{
|
||||
for (int i = 0; i < nTimerData; ++i) {
|
||||
TimerData& t = timerData[i];
|
||||
if ( (t.used) && (t.callback==cb) && (t.data==data) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void *data)
|
||||
{
|
||||
for (int i = 0; i < nTimerData; ++i) {
|
||||
TimerData& t = timerData[i];
|
||||
if ( t.used && (t.callback==cb) && ( (t.data==data) || (data==nullptr) ) ) {
|
||||
if (t.used)
|
||||
timer_delete(t.handle);
|
||||
t.triggered = t.used = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Play some system sound.
|
||||
|
||||
This function plays some rather arbitrary system sounds.
|
||||
|
||||
\param type
|
||||
|
||||
\see Fl_Screen_Driver::beep(int)
|
||||
\see fl_beep(int)
|
||||
*/
|
||||
void Fl_Android_Screen_Driver::beep(int type)
|
||||
{
|
||||
int androidSoundID = 93; // default to TONE_CDMA_ALERT_CALL_GUARD
|
||||
switch (type) {
|
||||
case FL_BEEP_DEFAULT: androidSoundID = 92; break;
|
||||
case FL_BEEP_MESSAGE: androidSoundID = 86; break;
|
||||
case FL_BEEP_ERROR: androidSoundID = 87; break;
|
||||
case FL_BEEP_QUESTION: androidSoundID = 91; break;
|
||||
case FL_BEEP_PASSWORD: androidSoundID = 95; break;
|
||||
case FL_BEEP_NOTIFICATION: androidSoundID = 93; break;
|
||||
}
|
||||
Fl_Android_Java java;
|
||||
if (java.is_attached()) {
|
||||
|
||||
jclass class_tone_generator = java.env()->FindClass("android/media/ToneGenerator");
|
||||
|
||||
jmethodID toneGeneratorConstructor = java.env()->GetMethodID(
|
||||
class_tone_generator, "<init>",
|
||||
"(II)V");
|
||||
|
||||
jobject toneGeneratorObj = java.env()->NewObject(
|
||||
class_tone_generator, toneGeneratorConstructor,
|
||||
4, // STREAM_ALARM
|
||||
100); // volume
|
||||
|
||||
jmethodID method_start_tone = java.env()->GetMethodID(
|
||||
class_tone_generator,
|
||||
"startTone",
|
||||
"(II)Z");
|
||||
|
||||
java.env()->CallBooleanMethod(
|
||||
toneGeneratorObj, method_start_tone,
|
||||
androidSoundID,
|
||||
1000);
|
||||
|
||||
java.env()->DeleteLocalRef(class_tone_generator);
|
||||
java.env()->DeleteLocalRef(toneGeneratorObj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the current mouse coordinates.
|
||||
|
||||
This is used, among other things, to position the FLTK standard dialogs in
|
||||
a way that makes it easy to click the most common button. For an Android
|
||||
touch screen, this makes no sense at all, which is why we return the center
|
||||
of the screen for now.
|
||||
|
||||
\todo rethink the dialog positioning scheme for touch devices.
|
||||
|
||||
\todo this method assumes a fixed screen resolution
|
||||
|
||||
\param [out] x
|
||||
\param [out] y
|
||||
\return
|
||||
*/
|
||||
int Fl_Android_Screen_Driver::get_mouse(int &x, int &y)
|
||||
{
|
||||
x = 600/2;
|
||||
y = 800/2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Screen_Driver::grab(Fl_Window* win)
|
||||
{
|
||||
if (win) {
|
||||
if (!Fl::grab_) {
|
||||
// TODO: will we need to fix any focus and/or direct the input stream to a window
|
||||
}
|
||||
Fl::grab_ = win;
|
||||
} else {
|
||||
if (Fl::grab_) {
|
||||
Fl::grab_ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\}
|
||||
\endcond
|
||||
*/
|
@ -1,452 +0,0 @@
|
||||
//
|
||||
// Android screen interface 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_Android_Screen_Driver.H"
|
||||
#include "Fl_Android_Application.H"
|
||||
#include "Fl_Android_Graphics_Font.H"
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/platform.H>
|
||||
#include <FL/Fl_Graphics_Driver.H>
|
||||
#include <FL/Fl_RGB_Image.H>
|
||||
#include <FL/fl_ask.H>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
// convert an FLTK (X) keysym to a MacOS symbol:
|
||||
// This table is in numeric order by FLTK symbol order for binary search.
|
||||
static const struct {unsigned short vk, fltk;} vktab[] = {
|
||||
{ AKEYCODE_SPACE, ' ' }, { AKEYCODE_APOSTROPHE, '\'' }, { AKEYCODE_COMMA, ',' }, { AKEYCODE_MINUS, '-' }, { AKEYCODE_PERIOD, '.' }, { AKEYCODE_SLASH, '/' },
|
||||
{ AKEYCODE_0, '0' }, { AKEYCODE_1, '1' }, { AKEYCODE_2, '2' }, { AKEYCODE_3, '3' },
|
||||
{ AKEYCODE_4, '4' }, { AKEYCODE_5, '5' }, { AKEYCODE_6, '6' }, { AKEYCODE_7, '7' },
|
||||
{ AKEYCODE_8, '8' }, { AKEYCODE_9, '9' }, { AKEYCODE_SEMICOLON, ';' }, { AKEYCODE_EQUALS, '=' },
|
||||
{ AKEYCODE_A, 'A' }, { AKEYCODE_B, 'B' }, { AKEYCODE_C, 'C' }, { AKEYCODE_D, 'D' },
|
||||
{ AKEYCODE_E, 'E' }, { AKEYCODE_F, 'F' }, { AKEYCODE_G, 'G' }, { AKEYCODE_H, 'H' },
|
||||
{ AKEYCODE_I, 'I' }, { AKEYCODE_J, 'J' }, { AKEYCODE_K, 'K' }, { AKEYCODE_L, 'L' },
|
||||
{ AKEYCODE_M, 'M' }, { AKEYCODE_N, 'N' }, { AKEYCODE_O, 'O' }, { AKEYCODE_P, 'P' },
|
||||
{ AKEYCODE_Q, 'Q' }, { AKEYCODE_R, 'R' }, { AKEYCODE_S, 'S' }, { AKEYCODE_T, 'T' },
|
||||
{ AKEYCODE_U, 'U' }, { AKEYCODE_V, 'V' }, { AKEYCODE_W, 'W' }, { AKEYCODE_X, 'X' },
|
||||
{ AKEYCODE_Y, 'Y' }, { AKEYCODE_Z, 'Z' },
|
||||
{ AKEYCODE_LEFT_BRACKET, '[' }, { AKEYCODE_BACKSLASH, '\\' }, { AKEYCODE_RIGHT_BRACKET, ']' }, { AKEYCODE_GRAVE, '`' },
|
||||
{ AKEYCODE_VOLUME_DOWN, FL_Volume_Down}, { AKEYCODE_MUTE, FL_Volume_Mute}, { AKEYCODE_VOLUME_UP, FL_Volume_Up},
|
||||
#if 0
|
||||
#define FL_Volume_Down 0xEF11 /* Volume control down */
|
||||
513 #define FL_Volume_Mute 0xEF12 /* Mute sound from the system */
|
||||
514 #define FL_Volume_Up 0xEF13 /* Volume control up */
|
||||
515 #define FL_Media_Play 0xEF14 /* Start playing of audio */
|
||||
516 #define FL_Media_Stop 0xEF15 /* Stop playing audio */
|
||||
517 #define FL_Media_Prev 0xEF16 /* Previous track */
|
||||
518 #define FL_Media_Next 0xEF17 /* Next track */
|
||||
519 #define FL_Home_Page 0xEF18 /* Display user's home page */
|
||||
520 #define FL_Mail 0xEF19 /* Invoke user's mail program */
|
||||
521 #define FL_Search 0xEF1B /* Search */
|
||||
522 #define FL_Back 0xEF26 /* Like back on a browser */
|
||||
523 #define FL_Forward 0xEF27 /* Like forward on a browser */
|
||||
524 #define FL_Stop 0xEF28 /* Stop current operation */
|
||||
525 #define FL_Refresh 0xEF29 /* Refresh the page */
|
||||
526 #define FL_Sleep 0xEF2F /* Put system to sleep */
|
||||
527 #define FL_Favorites 0xEF30 /* Show favorite locations */
|
||||
528
|
||||
#endif
|
||||
{ AKEYCODE_DEL, FL_BackSpace }, { AKEYCODE_TAB, FL_Tab }, { AKEYCODE_POUND, FL_Iso_Key }, { AKEYCODE_ENTER, FL_Enter }, /*{ 0x7F, FL_Pause },
|
||||
{ 0x7F, FL_Scroll_Lock },*/ { AKEYCODE_ESCAPE, FL_Escape },
|
||||
{ AKEYCODE_KANA, FL_Kana}, { AKEYCODE_EISU, FL_Eisu}, { AKEYCODE_YEN, FL_Yen}, /*{ AKEYCODE_UND, FL_JIS_Underscore},*/
|
||||
{ AKEYCODE_MOVE_HOME, FL_Home }, { AKEYCODE_DPAD_LEFT, FL_Left },
|
||||
{ AKEYCODE_DPAD_UP, FL_Up }, { AKEYCODE_DPAD_RIGHT, FL_Right }, { AKEYCODE_DPAD_DOWN, FL_Down }, { AKEYCODE_PAGE_UP, FL_Page_Up },
|
||||
{ AKEYCODE_PAGE_DOWN, FL_Page_Down }, { AKEYCODE_MOVE_END, FL_End }, { AKEYCODE_SYSRQ, FL_Print }, { AKEYCODE_INSERT, FL_Insert },
|
||||
{ AKEYCODE_MENU, FL_Menu }, { AKEYCODE_HELP, FL_Help }, { AKEYCODE_NUM_LOCK, FL_Num_Lock },
|
||||
{ AKEYCODE_NUMPAD_ENTER, FL_KP_Enter }, { AKEYCODE_NUMPAD_MULTIPLY, FL_KP+'*' }, { AKEYCODE_NUMPAD_ADD, FL_KP+'+'},
|
||||
{ AKEYCODE_NUMPAD_COMMA, FL_KP+',' },
|
||||
{ AKEYCODE_NUMPAD_SUBTRACT, FL_KP+'-' }, { AKEYCODE_NUMPAD_DOT, FL_KP+'.' }, { AKEYCODE_NUMPAD_DIVIDE, FL_KP+'/' },
|
||||
{ AKEYCODE_NUMPAD_0, FL_KP+'0' }, { AKEYCODE_NUMPAD_1, FL_KP+'1' }, { AKEYCODE_NUMPAD_2, FL_KP+'2' }, { AKEYCODE_NUMPAD_3, FL_KP+'3' },
|
||||
{ AKEYCODE_NUMPAD_4, FL_KP+'4' }, { AKEYCODE_NUMPAD_5, FL_KP+'5' }, { AKEYCODE_NUMPAD_6, FL_KP+'6' }, { AKEYCODE_NUMPAD_7, FL_KP+'7' },
|
||||
{ AKEYCODE_NUMPAD_8, FL_KP+'8' }, { AKEYCODE_NUMPAD_9, FL_KP+'9' }, { AKEYCODE_NUMPAD_EQUALS, FL_KP+'=' },
|
||||
{ AKEYCODE_F1, FL_F+1 }, { AKEYCODE_F2, FL_F+2 }, { AKEYCODE_F3, FL_F+3 }, { AKEYCODE_F4, FL_F+4 },
|
||||
{ AKEYCODE_F5, FL_F+5 }, { AKEYCODE_F6, FL_F+6 }, { AKEYCODE_F7, FL_F+7 }, { AKEYCODE_F8, FL_F+8 },
|
||||
{ AKEYCODE_F9, FL_F+9 }, { AKEYCODE_F10, FL_F+10 }, { AKEYCODE_F11, FL_F+11 }, { AKEYCODE_F12, FL_F+12 },
|
||||
//{ AKEYCODE_F13, FL_F+13 }, { AKEYCODE_F14, FL_F+14 }, { AKEYCODE_F15, FL_F+15 }, { AKEYCODE_F16, FL_F+16 },
|
||||
//{ AKEYCODE_F17, FL_F+17 }, { AKEYCODE_F18, FL_F+18 }, { AKEYCODE_F19, FL_F+19 }, { AKEYCODE_F20, FL_F+20 },
|
||||
{ AKEYCODE_SHIFT_LEFT, FL_Shift_L }, { AKEYCODE_SHIFT_RIGHT, FL_Shift_R }, { AKEYCODE_CTRL_LEFT, FL_Control_L }, { AKEYCODE_CTRL_RIGHT, FL_Control_R },
|
||||
{ AKEYCODE_CAPS_LOCK, FL_Caps_Lock }, { AKEYCODE_META_LEFT, FL_Meta_L }, { AKEYCODE_META_RIGHT, FL_Meta_R },
|
||||
{ AKEYCODE_ALT_LEFT, FL_Alt_L }, { AKEYCODE_ALT_RIGHT, FL_Alt_R }, { AKEYCODE_FORWARD_DEL, FL_Delete }
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
// public static final int KEYCODE_ALL_APPS = 284;
|
||||
// private static final int LAST_KEYCODE = KEYCODE_ALL_APPS;
|
||||
|
||||
// Computes the macKeyLookUp table that transforms a Mac OS virtual keycode into an FLTK keysym
|
||||
unsigned short *fl_compute_macKeyLookUp()
|
||||
{
|
||||
static unsigned short macKeyLookUp[128];
|
||||
memset(macKeyLookUp, 0, sizeof(macKeyLookUp));
|
||||
for (unsigned i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) {
|
||||
macKeyLookUp[vktab[i].vk] = vktab[i].fltk;
|
||||
}
|
||||
return macKeyLookUp;
|
||||
}
|
||||
|
||||
static int fltk2mac(int fltk) {
|
||||
int a = 0;
|
||||
int b = sizeof(vktab)/sizeof(*vktab);
|
||||
while (a < b) {
|
||||
int c = (a+b)/2;
|
||||
if (vktab[c].fltk == fltk) return vktab[c].vk;
|
||||
if (vktab[c].fltk < fltk) a = c+1; else b = c;
|
||||
}
|
||||
return vktab[a].vk;
|
||||
}
|
||||
|
||||
//: returns true, if that key was pressed during the last event
|
||||
int Fl_Darwin_System_Driver::event_key(int k) {
|
||||
return get_key(k);
|
||||
}
|
||||
|
||||
//: returns true, if that key is pressed right now
|
||||
int Fl_Darwin_System_Driver::get_key(int k) {
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
|
||||
if (&CGEventSourceKeyState != NULL) {
|
||||
return (int)CGEventSourceKeyState(kCGEventSourceStateCombinedSessionState, fltk2mac(k) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
typedef UInt32 fl_KeyMap[4];
|
||||
fl_KeyMap foo;
|
||||
// use the GetKeys Carbon function
|
||||
typedef void (*keymap_f)(fl_KeyMap);
|
||||
static keymap_f f = NULL;
|
||||
if (!f) f = ( keymap_f )Fl_Darwin_System_Driver::get_carbon_function("GetKeys");
|
||||
(*f)(foo);
|
||||
#ifdef MAC_TEST_FOR_KEYCODES
|
||||
static int cnt = 0;
|
||||
if (cnt++>1024) {
|
||||
cnt = 0;
|
||||
printf("%08x %08x %08x %08x\n", (ulong*)(foo)[3], (ulong*)(foo)[2], (ulong*)(foo)[1], (ulong*)(foo)[0]);
|
||||
}
|
||||
#endif
|
||||
unsigned char *b = (unsigned char*)foo;
|
||||
// KP_Enter can be at different locations for Powerbooks vs. desktop Macs
|
||||
if (k==FL_KP_Enter) {
|
||||
return (((b[0x34>>3]>>(0x34&7))&1)||((b[0x4c>>3]>>(0x4c&7))&1));
|
||||
}
|
||||
int i = fltk2mac(k);
|
||||
return (b[i>>3]>>(i&7))&1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int Fl_Android_Screen_Driver::compose(int &del)
|
||||
{
|
||||
int condition;
|
||||
unsigned char ascii = (unsigned char)Fl::e_text[0];
|
||||
condition = (Fl::e_state & (FL_ALT | FL_META | FL_CTRL)) && !(ascii & 128) ;
|
||||
if (condition) { del = 0; return 0;} // this stuff is to be treated as a function key
|
||||
del = Fl::compose_state;
|
||||
Fl::compose_state = 0;
|
||||
// Only insert non-control characters:
|
||||
if ( (!Fl::compose_state) && ! (ascii & ~31 && ascii!=127)) { return 0; }
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static unsigned short *key_lookup = nullptr;
|
||||
|
||||
// Computes the macKeyLookUp table that transforms a Mac OS virtual keycode into an FLTK keysym
|
||||
static unsigned short *compute_key_lookup()
|
||||
{
|
||||
static unsigned short AndroidKeyLookUp[AKEYCODE_ALL_APPS+1];
|
||||
memset(AndroidKeyLookUp, 0, sizeof(AndroidKeyLookUp));
|
||||
for (unsigned i = 0; i < sizeof(vktab)/sizeof(*vktab); i++) {
|
||||
AndroidKeyLookUp[vktab[i].vk] = vktab[i].fltk;
|
||||
}
|
||||
return AndroidKeyLookUp;
|
||||
}
|
||||
|
||||
|
||||
static int android_to_fltk_modifiers(int a)
|
||||
{
|
||||
int fl_mod = 0;
|
||||
if (a == AMETA_NONE) return 0;
|
||||
if (a & AMETA_ALT_ON) fl_mod |= FL_ALT;
|
||||
if (a & AMETA_SHIFT_ON) fl_mod |= FL_SHIFT;
|
||||
if (a & AMETA_CTRL_ON) fl_mod |= FL_CTRL;
|
||||
if (a & AMETA_META_ON) fl_mod |= FL_META;
|
||||
if (a & AMETA_NUM_LOCK_ON) fl_mod |= FL_NUM_LOCK;
|
||||
if (a & AMETA_CAPS_LOCK_ON) fl_mod |= FL_CAPS_LOCK;
|
||||
if (a & AMETA_SCROLL_LOCK_ON) fl_mod |= FL_SCROLL_LOCK;
|
||||
// AMETA_SYM_ON
|
||||
// AMETA_FUNCTION_ON
|
||||
// FIXME: we need to add the status of the mouse button(s)
|
||||
// FL_BUTTON1
|
||||
// FL_BUTTON2
|
||||
// FL_BUTTON3
|
||||
return fl_mod;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int Fl_Android_Screen_Driver::handle_keyboard_event(AInputQueue *queue, AInputEvent *event)
|
||||
{
|
||||
/*
|
||||
int32_t AKeyEvent_getAction (const AInputEvent *key_event)
|
||||
{ AKEY_EVENT_ACTION_DOWN = 0, AKEY_EVENT_ACTION_UP = 1, AKEY_EVENT_ACTION_MULTIPLE = 2 }
|
||||
> Reading up on ACTION_MULTIPLE also explains how to deal with
|
||||
> special or sequences of characters:
|
||||
> "If the key code is not KEYCODE_UNKNOWN then the getRepeatCount()
|
||||
> method returns the number of times the given key code should be
|
||||
> executed. Otherwise, if the key code is KEYCODE_UNKNOWN, then this
|
||||
> is a sequence of characters as returned by getCharacters()."
|
||||
|
||||
int32_t AKeyEvent_getFlags (const AInputEvent *key_event)
|
||||
{
|
||||
AKEY_EVENT_FLAG_WOKE_HERE = 0x1, AKEY_EVENT_FLAG_SOFT_KEYBOARD = 0x2, AKEY_EVENT_FLAG_KEEP_TOUCH_MODE = 0x4, AKEY_EVENT_FLAG_FROM_SYSTEM = 0x8,
|
||||
AKEY_EVENT_FLAG_EDITOR_ACTION = 0x10, AKEY_EVENT_FLAG_CANCELED = 0x20, AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY = 0x40, AKEY_EVENT_FLAG_LONG_PRESS = 0x80,
|
||||
AKEY_EVENT_FLAG_CANCELED_LONG_PRESS = 0x100, AKEY_EVENT_FLAG_TRACKING = 0x200, AKEY_EVENT_FLAG_FALLBACK = 0x400
|
||||
}
|
||||
|
||||
int32_t AKeyEvent_getKeyCode (const AInputEvent *key_event)
|
||||
{
|
||||
AKEYCODE_UNKNOWN = 0, AKEYCODE_SOFT_LEFT = 1, AKEYCODE_SOFT_RIGHT = 2, AKEYCODE_HOME = 3,
|
||||
AKEYCODE_BACK = 4, AKEYCODE_CALL = 5, AKEYCODE_ENDCALL = 6, AKEYCODE_0 = 7,
|
||||
AKEYCODE_1 = 8, AKEYCODE_2 = 9, AKEYCODE_3 = 10, AKEYCODE_4 = 11,
|
||||
AKEYCODE_5 = 12, AKEYCODE_6 = 13, AKEYCODE_7 = 14, AKEYCODE_8 = 15,
|
||||
AKEYCODE_9 = 16, AKEYCODE_STAR = 17, AKEYCODE_POUND = 18, AKEYCODE_DPAD_UP = 19,
|
||||
AKEYCODE_DPAD_DOWN = 20, AKEYCODE_DPAD_LEFT = 21, AKEYCODE_DPAD_RIGHT = 22, AKEYCODE_DPAD_CENTER = 23,
|
||||
AKEYCODE_VOLUME_UP = 24, AKEYCODE_VOLUME_DOWN = 25, AKEYCODE_POWER = 26, AKEYCODE_CAMERA = 27,
|
||||
AKEYCODE_CLEAR = 28, AKEYCODE_A = 29, AKEYCODE_B = 30, AKEYCODE_C = 31,
|
||||
AKEYCODE_D = 32, AKEYCODE_E = 33, AKEYCODE_F = 34, AKEYCODE_G = 35, ...
|
||||
|
||||
int32_t AKeyEvent_getScanCode (const AInputEvent *key_event)
|
||||
{ AKEY_STATE_UNKNOWN = -1, AKEY_STATE_UP = 0, AKEY_STATE_DOWN = 1, AKEY_STATE_VIRTUAL = 2 }
|
||||
|
||||
int32_t AKeyEvent_getMetaState (const AInputEvent *key_event)
|
||||
{
|
||||
AMETA_NONE = 0, AMETA_ALT_ON = 0x02, AMETA_ALT_LEFT_ON = 0x10, AMETA_ALT_RIGHT_ON = 0x20,
|
||||
AMETA_SHIFT_ON = 0x01, AMETA_SHIFT_LEFT_ON = 0x40, AMETA_SHIFT_RIGHT_ON = 0x80, AMETA_SYM_ON = 0x04,
|
||||
AMETA_FUNCTION_ON = 0x08, AMETA_CTRL_ON = 0x1000, AMETA_CTRL_LEFT_ON = 0x2000, AMETA_CTRL_RIGHT_ON = 0x4000,
|
||||
AMETA_META_ON = 0x10000, AMETA_META_LEFT_ON = 0x20000, AMETA_META_RIGHT_ON = 0x40000, AMETA_CAPS_LOCK_ON = 0x100000,
|
||||
AMETA_NUM_LOCK_ON = 0x200000, AMETA_SCROLL_LOCK_ON = 0x400000
|
||||
}
|
||||
|
||||
int32_t AKeyEvent_getRepeatCount (const AInputEvent *key_event)
|
||||
int64_t AKeyEvent_getDownTime (const AInputEvent *key_event)
|
||||
int64_t AKeyEvent_getEventTime (const AInputEvent *key_event)
|
||||
*/
|
||||
Fl_Android_Application::log_i("Key event: action=%d keyCode=%d metaState=0x%x scanCode=%d",
|
||||
AKeyEvent_getAction(event),
|
||||
AKeyEvent_getKeyCode(event),
|
||||
AKeyEvent_getMetaState(event),
|
||||
AKeyEvent_getScanCode(event));
|
||||
|
||||
auto keyAction = AKeyEvent_getAction(event);
|
||||
if (keyAction==AKEY_EVENT_ACTION_MULTIPLE) {
|
||||
if (AKeyEvent_getKeyCode(event)==AKEYCODE_UNKNOWN) {
|
||||
// characters are in getCharacters()
|
||||
// String class KeyEvent::getCharacters() [Java]
|
||||
// is there a way to get the true Java event somehow?
|
||||
// override dispatchKeyEvent(android.view.KeyEvent event)
|
||||
// getDeadChar()
|
||||
//
|
||||
// This seems to work for hardware keys only:
|
||||
// public static interface View.OnKeyListener
|
||||
// boolean onKey (View v,
|
||||
// int keyCode,
|
||||
// KeyEvent event)
|
||||
// public static interface KeyEvent.Callback
|
||||
// onKeyDown(int keyCode, KeyEvent event)
|
||||
// public static interface Window.Callback
|
||||
// abstract boolean dispatchKeyEvent(KeyEvent event)
|
||||
// view.setOnKeyListener(new OnKeyListener()
|
||||
//
|
||||
// NativeApplication.nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN,checkKeypress);
|
||||
// public function CheckKeypress(event:KeyboardEvent):void
|
||||
//
|
||||
// https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/KeyEvent.java
|
||||
} else {
|
||||
// send keycode as many times as getRepeatCount() / AKeyEvent_getRepeatCount(event)
|
||||
}
|
||||
}
|
||||
|
||||
int unicodeKey = 0;
|
||||
auto aKeyCode = AKeyEvent_getKeyCode(event);
|
||||
auto aMetaState = AKeyEvent_getMetaState(event);
|
||||
|
||||
Fl_Android_Java java;
|
||||
if (java.is_attached()) {
|
||||
|
||||
jclass class_key_event = java.env()->FindClass("android/view/KeyEvent");
|
||||
|
||||
jmethodID eventConstructor = java.env()->GetMethodID(
|
||||
class_key_event, "<init>",
|
||||
"(JJIIIIIIII)V");
|
||||
|
||||
jobject eventObj = java.env()->NewObject(
|
||||
class_key_event, eventConstructor,
|
||||
AKeyEvent_getDownTime(event),
|
||||
AKeyEvent_getEventTime(event),
|
||||
AKeyEvent_getAction(event),
|
||||
aKeyCode,
|
||||
AKeyEvent_getRepeatCount(event),
|
||||
aMetaState,
|
||||
AInputEvent_getDeviceId(event),
|
||||
AKeyEvent_getScanCode(event), // hardware keyboard only
|
||||
AKeyEvent_getFlags(event),
|
||||
AInputEvent_getSource(event));
|
||||
|
||||
jmethodID method_get_unicode_char = java.env()->GetMethodID(
|
||||
class_key_event,
|
||||
"getUnicodeChar",
|
||||
"(I)I");
|
||||
|
||||
unicodeKey = java.env()->CallIntMethod(
|
||||
eventObj, method_get_unicode_char,
|
||||
AKeyEvent_getMetaState(event));
|
||||
|
||||
java.env()->DeleteLocalRef(class_key_event);
|
||||
java.env()->DeleteLocalRef(eventObj);
|
||||
}
|
||||
|
||||
// FIXME: do the following thing only on key-down or key-repeat
|
||||
static char buf[8];
|
||||
int len = fl_utf8encode(unicodeKey, buf);
|
||||
if (len >= 0 && len < 8)
|
||||
buf[len] = 0;
|
||||
else
|
||||
buf[0] = 0;
|
||||
Fl_Android_Application::log_i("Unicode: %d Text: %s", unicodeKey, buf);
|
||||
|
||||
if (!key_lookup) key_lookup = compute_key_lookup();
|
||||
Fl::e_keysym = (aKeyCode>AKEYCODE_ALL_APPS) ? 0 : key_lookup[aKeyCode];
|
||||
Fl::e_state = android_to_fltk_modifiers(aMetaState);
|
||||
|
||||
AInputQueue_finishEvent(queue, event, 0);
|
||||
|
||||
Fl_Widget *w = Fl::focus();
|
||||
if (w) {
|
||||
Fl_Window *win = w->window();
|
||||
if (keyAction==AKEY_EVENT_ACTION_DOWN) {
|
||||
if (unicodeKey>0) {
|
||||
Fl::e_text = buf;
|
||||
Fl::e_length = len;
|
||||
} else {
|
||||
Fl::e_text = (char*)"";
|
||||
Fl::e_length = 0;
|
||||
}
|
||||
Fl::handle(FL_KEYBOARD, win);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: different inputs may be able to request different keyboards
|
||||
// TODO: knowing the position of the widget, we may be able to avoid
|
||||
// obstructing it with the on-screen keyboard
|
||||
void Fl_Android_Screen_Driver::request_keyboard( /*o->rect(), o->type()*/ )
|
||||
{
|
||||
if (pKeyboardCount==0) {
|
||||
/*
|
||||
* The following line does not work as of March 2018. The pseudo-Java
|
||||
* code that follows is needed to make the virtaul keyboard show.
|
||||
*
|
||||
ANativeActivity_showSoftInput(Fl_Android_Application::get_activity(),
|
||||
ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT);
|
||||
*
|
||||
* This is the actual Java code that we recreate in C++
|
||||
*
|
||||
InputMethodManager imm = ( InputMethodManager )getSystemService( Context.INPUT_METHOD_SERVICE );
|
||||
imm.showSoftInput( this.getWindow().getDecorView(), InputMethodManager.SHOW_FORCED );
|
||||
*/
|
||||
|
||||
Fl_Android_Java java;
|
||||
if (java.is_attached()) {
|
||||
|
||||
jint lFlags = 0;
|
||||
|
||||
// Retrieves Context.INPUT_METHOD_SERVICE.
|
||||
jclass ClassContext = java.env()->FindClass("android/content/Context");
|
||||
jfieldID FieldINPUT_METHOD_SERVICE = java.env()->GetStaticFieldID(
|
||||
ClassContext,
|
||||
"INPUT_METHOD_SERVICE",
|
||||
"Ljava/lang/String;");
|
||||
jobject INPUT_METHOD_SERVICE = java.env()->GetStaticObjectField(
|
||||
ClassContext,
|
||||
FieldINPUT_METHOD_SERVICE);
|
||||
|
||||
// Runs getSystemService(Context.INPUT_METHOD_SERVICE).
|
||||
jclass ClassInputMethodManager = java.env()->FindClass(
|
||||
"android/view/inputmethod/InputMethodManager");
|
||||
jmethodID MethodGetSystemService = java.env()->GetMethodID(
|
||||
java.native_activity_class(), "getSystemService",
|
||||
"(Ljava/lang/String;)Ljava/lang/Object;");
|
||||
jobject lInputMethodManager = java.env()->CallObjectMethod(
|
||||
java.native_ativity(), MethodGetSystemService,
|
||||
INPUT_METHOD_SERVICE);
|
||||
|
||||
// Runs getWindow().getDecorView().
|
||||
jmethodID MethodGetWindow = java.env()->GetMethodID(
|
||||
java.native_activity_class(), "getWindow",
|
||||
"()Landroid/view/Window;");
|
||||
jobject lWindow = java.env()->CallObjectMethod(
|
||||
java.native_ativity(),
|
||||
MethodGetWindow);
|
||||
jclass ClassWindow = java.env()->FindClass(
|
||||
"android/view/Window");
|
||||
jmethodID MethodGetDecorView = java.env()->GetMethodID(
|
||||
ClassWindow, "getDecorView", "()Landroid/view/View;");
|
||||
jobject lDecorView = java.env()->CallObjectMethod(
|
||||
lWindow,
|
||||
MethodGetDecorView);
|
||||
|
||||
// Runs lInputMethodManager.showSoftInput(...).
|
||||
jmethodID MethodShowSoftInput = java.env()->GetMethodID(
|
||||
ClassInputMethodManager, "showSoftInput",
|
||||
"(Landroid/view/View;I)Z");
|
||||
jboolean lResult = java.env()->CallBooleanMethod(
|
||||
lInputMethodManager, MethodShowSoftInput,
|
||||
lDecorView, lFlags);
|
||||
|
||||
java.env()->DeleteLocalRef(ClassContext);
|
||||
java.env()->DeleteLocalRef(ClassInputMethodManager);
|
||||
java.env()->DeleteLocalRef(ClassWindow);
|
||||
|
||||
java.env()->DeleteLocalRef(INPUT_METHOD_SERVICE);
|
||||
java.env()->DeleteLocalRef(lInputMethodManager);
|
||||
java.env()->DeleteLocalRef(lWindow);
|
||||
java.env()->DeleteLocalRef(lDecorView);
|
||||
}
|
||||
}
|
||||
pKeyboardCount++;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Screen_Driver::release_keyboard()
|
||||
{
|
||||
pKeyboardCount--;
|
||||
if (pKeyboardCount==0) {
|
||||
ANativeActivity_hideSoftInput(Fl_Android_Application::get_activity(),
|
||||
ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS);
|
||||
}
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
//
|
||||
// Definition of Android system driver for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2020 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_Android_System_Driver.H
|
||||
\brief Definition of Android system driver.
|
||||
*/
|
||||
|
||||
#ifndef FL_ANDROID_SYSTEM_DRIVER_H
|
||||
#define FL_ANDROID_SYSTEM_DRIVER_H
|
||||
|
||||
#include <string.h>
|
||||
#include <FL/fl_string_functions.h>
|
||||
#include "../../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(const char *var) { return ::putenv(fl_strdup(var)); }
|
||||
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);
|
||||
virtual int clocale_snprintf(char *output, size_t output_size, const char *format, va_list args);
|
||||
virtual int clocale_sscanf(const char *input, 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 **),
|
||||
char *errmsg, int errmsg_sz);
|
||||
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,
|
||||
char *errmsg=NULL, int errmsg_sz=0);
|
||||
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
|
||||
virtual char *strdup(const char *s) {return ::strdup(s);}
|
||||
};
|
||||
|
||||
#endif // FL_ANDROID_SYSTEM_DRIVER_H
|
@ -1,957 +0,0 @@
|
||||
//
|
||||
// Definition of Android system driver.
|
||||
//
|
||||
// Copyright 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_Android_System_Driver.H"
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_utf8.h>
|
||||
#include <FL/fl_string_functions.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::clocale_snprintf(char *output, size_t output_size, const char *format, va_list args) {
|
||||
//... write me
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::clocale_sscanf(const char *input, const char *format, va_list args) {
|
||||
//... write me
|
||||
}
|
||||
|
||||
int Fl_WinAPI_System_Driver::filename_list(const char *d, dirent ***list,
|
||||
int (*sort)(struct dirent **, struct dirent **),
|
||||
char *errmsg, int errmsg_sz ) {
|
||||
// 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, errmsg, errmsg_sz);
|
||||
}
|
||||
|
||||
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 = fl_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,
|
||||
char *errmsg, int errmsg_sz)
|
||||
{
|
||||
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, errmsg, errmsg_sz);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Note: `prefs` can be NULL!
|
||||
*/
|
||||
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&Fl_Preferences::ROOT_MASK) {
|
||||
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
|
@ -1,143 +0,0 @@
|
||||
//
|
||||
// Definition of Android window driver
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_Android_Window_Driver.H
|
||||
\brief Definition of Android window driver.
|
||||
*/
|
||||
|
||||
#ifndef FL_ANDROID_WINDOW_DRIVER_H
|
||||
#define FL_ANDROID_WINDOW_DRIVER_H
|
||||
|
||||
#include "../../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 *effective_bitmap_; ///< auxiliary bitmap image
|
||||
};
|
||||
|
||||
class FL_EXPORT Fl_Android_Window_Driver : public Fl_Window_Driver
|
||||
{
|
||||
#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:
|
||||
static inline Fl_Android_Window_Driver* driver(const Fl_Window *w) {
|
||||
return (Fl_Android_Window_Driver*)Fl_Window_Driver::driver(w);
|
||||
}
|
||||
|
||||
Fl_Android_Window_Driver(Fl_Window *w) : Fl_Window_Driver(w) {}
|
||||
virtual ~Fl_Android_Window_Driver() override {}
|
||||
|
||||
virtual void make_current() override;
|
||||
virtual void show() override;
|
||||
virtual void hide() override;
|
||||
|
||||
#if 0
|
||||
HDC private_dc; // used for OpenGL
|
||||
RECT border_width_title_bar_height(int &bx, int &by, int &bt);
|
||||
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 label(const char *name,const char *iname);
|
||||
#endif
|
||||
virtual void resize(int X,int Y,int W,int H) override;
|
||||
#if 0
|
||||
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);
|
||||
#endif
|
||||
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) override;
|
||||
#if 0
|
||||
static void resize_after_screen_change(void *data);
|
||||
|
||||
#endif
|
||||
|
||||
virtual void wait_for_expose() override { wait_for_expose_value = 1; }
|
||||
static void expose_all();
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_ANDROID_WINDOW_DRIVER_H
|
@ -1,826 +0,0 @@
|
||||
//
|
||||
// Definition of Android window driver for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2018-2021 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.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 <math.h>
|
||||
#include "Fl_Android_Window_Driver.H"
|
||||
#include "Fl_Android_Screen_Driver.H"
|
||||
#include "Fl_Android_Graphics_Driver.H"
|
||||
#include "Fl_Android_Application.H"
|
||||
|
||||
|
||||
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w)
|
||||
{
|
||||
return new Fl_Android_Window_Driver(w);
|
||||
}
|
||||
|
||||
|
||||
Window fl_window = 0;
|
||||
|
||||
|
||||
void Fl_Android_Window_Driver::show()
|
||||
{
|
||||
if (!shown()) {
|
||||
// make window
|
||||
fl_open_display();
|
||||
if (pWindow->parent() && !Fl_X::i(pWindow->window())) {
|
||||
pWindow->set_visible();
|
||||
return;
|
||||
}
|
||||
pWindow->set_visible();
|
||||
Fl_X *x = new Fl_X;
|
||||
x->w = pWindow;
|
||||
i(x);
|
||||
x->next = Fl_X::first;
|
||||
Fl_X::first = x;
|
||||
// position window
|
||||
// TODO: we want to scale the screen to hold all windows
|
||||
// TODO: we want to allow for screen size hints to make apps look perfect, even if the screen is rotated
|
||||
if (force_position()) {
|
||||
// TODO: make sure that we are on a screen if this is just a regular window
|
||||
} else {
|
||||
// Center any new window on screen
|
||||
pWindow->position(
|
||||
(600-pWindow->w())/2,
|
||||
(800-pWindow->h())/2
|
||||
);
|
||||
}
|
||||
// show window or defer showing window
|
||||
if (Fl_Android_Application::native_window()) {
|
||||
pWindow->redraw();
|
||||
} else {
|
||||
pWindow->wait_for_expose();
|
||||
}
|
||||
} else {
|
||||
// bring window to front
|
||||
if (!pWindow->parent())
|
||||
Fl::first_window(pWindow); // TODO: does this really work?
|
||||
expose_all();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Window_Driver::hide()
|
||||
{
|
||||
Fl_X* ip = Fl_X::i(pWindow);
|
||||
if (hide_common()) return;
|
||||
if (ip->region) {
|
||||
delete ip->region;
|
||||
ip->region = nullptr;
|
||||
}
|
||||
delete ip;
|
||||
expose_all();
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Window_Driver::expose_all()
|
||||
{
|
||||
for (Fl_X *x = Fl_X::first; x; x = x->next) {
|
||||
Fl_Window *win = x->w;
|
||||
Fl_Android_Window_Driver::driver(win)->wait_for_expose_value = 0;
|
||||
win->damage(FL_DAMAGE_EXPOSE);
|
||||
win->redraw();
|
||||
}
|
||||
((Fl_Android_Screen_Driver*)Fl::screen_driver())->pClearDesktop = true;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Window_Driver::make_current()
|
||||
{
|
||||
// FXIME: that is quite a cludge:
|
||||
((Fl_Android_Screen_Driver*)Fl::screen_driver())->pContentChanged = true;
|
||||
|
||||
Fl_Android_Graphics_Driver *gd = dynamic_cast<Fl_Android_Graphics_Driver*>(fl_graphics_driver);
|
||||
if (gd) {
|
||||
gd->make_current(pWindow);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Fl_Android_Window_Driver::resize(int X,int Y,int W,int H)
|
||||
{
|
||||
int is_a_resize = (W != w() || H != h() || Fl_Window::is_a_rescale());
|
||||
if (X != x() || Y != y() || Fl_Window::is_a_rescale()) {
|
||||
force_position(1);
|
||||
} else {
|
||||
if (!is_a_resize)
|
||||
return;
|
||||
}
|
||||
if (is_a_resize) {
|
||||
pWindow->Fl_Group::resize(X, Y, W, H);
|
||||
if (visible_r()) {
|
||||
pWindow->redraw();
|
||||
// only wait for exposure if this window has a size - a window
|
||||
// with no width or height will never get an exposure event
|
||||
Fl_X *i = Fl_X::i(pWindow);
|
||||
if (i && W > 0 && H > 0)
|
||||
wait_for_expose_value = 1;
|
||||
}
|
||||
} else {
|
||||
x(X);
|
||||
y(Y);
|
||||
}
|
||||
if (shown()) {
|
||||
if (!pWindow->resizable())
|
||||
pWindow->size_range(w(), h(), w(), h());
|
||||
// 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);
|
||||
// if (scaledW <= 0)
|
||||
// scaledW = 1;
|
||||
// if (scaledH <= 0)
|
||||
// scaledH = 1;
|
||||
// //SetWindowPos(fl_xid(pWindow), 0, scaledX, scaledY, scaledW, scaledH, flags);
|
||||
expose_all();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Scroll a portion of the window.
|
||||
FIXME: We are currently taking the easy way out, basically telling the caller that we don;t know how to scroll
|
||||
and asking FLTK to draw the new area from scratch. It would be nice if clipping provides all calls
|
||||
that we need to implement a more efficient scrolling code.
|
||||
*/
|
||||
int Fl_Android_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)
|
||||
{
|
||||
#if 0
|
||||
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;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#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_->effective_bitmap_;
|
||||
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_->effective_bitmap_ = bitmap;
|
||||
}
|
||||
|
||||
void Fl_WinAPI_Window_Driver::shape(const Fl_Image* img) {
|
||||
if (shape_data_) {
|
||||
if (shape_data_->effective_bitmap_) { delete shape_data_->effective_bitmap_; }
|
||||
}
|
||||
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 = 0, Y = 0, W = 0, H = 0;
|
||||
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 = 0, Y = 0, W = 0, H = 0;
|
||||
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_HAVE_CAIROEXT
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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
|
@ -1,12 +0,0 @@
|
||||
|
||||
|
||||
WonkoBook:Android matt$ svn ps svn:keywords "author date id revision" Fl_Android_Application.*
|
||||
property 'svn:keywords' set on 'Fl_Android_Application.cpp'
|
||||
property 'svn:keywords' set on 'Fl_Android_Application.h'
|
||||
WonkoBook:Android matt$ svn pg svn:eol-style Fl_Font.H
|
||||
native
|
||||
WonkoBook:Android matt$ svn ps svn:eol-style "native" Fl_Android_Application.*
|
||||
property 'svn:eol-style' set on 'Fl_Android_Application.cpp'
|
||||
property 'svn:eol-style' set on 'Fl_Android_Application.h'
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
|
@ -1,211 +0,0 @@
|
||||
//
|
||||
// Definition of the Pico minimal graphics driver
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_Pico_Graphics_Driver.H
|
||||
\brief Definition of Pico minimal graphics driver.
|
||||
*/
|
||||
|
||||
#ifndef FL_PICO_GRAPHICS_DRIVER_H
|
||||
#define FL_PICO_GRAPHICS_DRIVER_H
|
||||
|
||||
#include <FL/Fl_Graphics_Driver.H>
|
||||
|
||||
|
||||
/**
|
||||
\brief The Pico minimal graphics class.
|
||||
|
||||
This class is implemented as a base class for minimal core drivers.
|
||||
*/
|
||||
class Fl_Pico_Graphics_Driver : public Fl_Graphics_Driver {
|
||||
// friend class Fl_Surface_Device;
|
||||
// friend class Fl_Pixmap;
|
||||
// friend class Fl_Bitmap;
|
||||
// friend class Fl_RGB_Image;
|
||||
// friend int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg);
|
||||
//public:
|
||||
// // The following functions create the various graphics drivers that are required
|
||||
// // for core operations. They must be implemented as members of Fl_Graphics_Driver,
|
||||
// // but located in the device driver module that is linked to the core library
|
||||
// static Fl_Graphics_Driver *newMainGraphicsDriver();
|
||||
// //static Fl_Graphics_Driver *newOpenGLGraphicsDriver();
|
||||
// //static Fl_Graphics_Driver *newPrinterGraphicsDriver();
|
||||
// //static Fl_Graphics_Driver *new...;
|
||||
//public:
|
||||
// /** A 2D coordinate transformation matrix */
|
||||
// struct matrix {double a, b, c, d, x, y;};
|
||||
// /** Features that a derived class may possess. */
|
||||
// typedef enum {
|
||||
// NATIVE = 1, /**< native graphics driver for the platform */
|
||||
// PRINTER = 2 /**< graphics driver for a printer drawing surface */
|
||||
// } driver_feature;
|
||||
//
|
||||
// int fl_clip_state_number;
|
||||
//protected:
|
||||
// static const matrix m0;
|
||||
// Fl_Font font_; // current font
|
||||
// Fl_Fontsize size_; // current font size
|
||||
// Fl_Color color_; // current color
|
||||
// int sptr;
|
||||
// static const int matrix_stack_size = FL_MATRIX_STACK_SIZE;
|
||||
// matrix stack[FL_MATRIX_STACK_SIZE];
|
||||
// matrix m;
|
||||
// int n, p_size, gap_;
|
||||
// XPOINT *p;
|
||||
// int what;
|
||||
// int rstackptr;
|
||||
// static const int region_stack_max = FL_REGION_STACK_SIZE - 1;
|
||||
// Fl_Region rstack[FL_REGION_STACK_SIZE];
|
||||
// Fl_Font_Descriptor *font_descriptor_;
|
||||
//#ifndef FL_DOXYGEN
|
||||
// enum {LINE, LOOP, POLYGON, POINT_};
|
||||
// inline int vertex_no() { return n; }
|
||||
// inline XPOINT *vertices() {return p;}
|
||||
// inline int vertex_kind() {return what;}
|
||||
//#endif
|
||||
// matrix *fl_matrix; /**< Points to the current coordinate transformation matrix */
|
||||
//
|
||||
//public:
|
||||
// Fl_Graphics_Driver();
|
||||
// virtual ~Fl_Graphics_Driver() { if (p) free(p); }
|
||||
// virtual char can_do_alpha_blending() { return 0; }
|
||||
// // --- implementation is in src/fl_rect.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_rect.cxx
|
||||
virtual void point(int x, int y);
|
||||
virtual void rect(int x, int y, int w, int h);
|
||||
// virtual void focus_rect(int x, int y, int w, int h);
|
||||
virtual void rectf(int x, int y, int w, int h);
|
||||
virtual void line(int x, int y, int x1, int y1);
|
||||
virtual void line(int x, int y, int x1, int y1, int x2, int y2);
|
||||
virtual void xyline(int x, int y, int x1);
|
||||
virtual void xyline(int x, int y, int x1, int y2);
|
||||
virtual void xyline(int x, int y, int x1, int y2, int x3) ;
|
||||
virtual void yxline(int x, int y, int y1) ;
|
||||
virtual void yxline(int x, int y, int y1, int x2) ;
|
||||
virtual void yxline(int x, int y, int y1, int x2, int y3) ;
|
||||
virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2) ;
|
||||
virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) ;
|
||||
virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2) ;
|
||||
virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) ;
|
||||
// // --- clipping
|
||||
virtual void push_clip(int x, int y, int w, int h) ;
|
||||
virtual int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) ;
|
||||
virtual int not_clipped(int x, int y, int w, int h) ;
|
||||
virtual void push_no_clip() ;
|
||||
virtual void pop_clip() ;
|
||||
// virtual Fl_Region clip_region(); // has default implementation
|
||||
// virtual void clip_region(Fl_Region r); // has default implementation
|
||||
// virtual void restore_clip();
|
||||
// // --- implementation is in src/fl_vertex.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_vertex.cxx
|
||||
// virtual void push_matrix();
|
||||
// virtual void pop_matrix();
|
||||
// virtual void mult_matrix(double a, double b, double c, double d, double x, double y);
|
||||
// virtual void rotate(double d);
|
||||
// virtual void scale(double x, double y);
|
||||
// virtual void scale(double x);
|
||||
// virtual void translate(double x,double y);
|
||||
virtual void begin_points();
|
||||
virtual void begin_line();
|
||||
virtual void begin_loop();
|
||||
virtual void begin_polygon();
|
||||
virtual void begin_complex_polygon() ;
|
||||
// virtual double transform_x(double x, double y);
|
||||
// virtual double transform_y(double x, double y);
|
||||
// virtual double transform_dx(double x, double y);
|
||||
// virtual double transform_dy(double x, double y);
|
||||
virtual void transformed_vertex(double xf, double yf) ;
|
||||
virtual void vertex(double x, double y) ;
|
||||
virtual void end_points() ;
|
||||
virtual void end_line() ;
|
||||
virtual void end_loop() ;
|
||||
virtual void end_polygon() ;
|
||||
virtual void end_complex_polygon() ;
|
||||
virtual void gap() ;
|
||||
virtual void circle(double x, double y, double r) ;
|
||||
// // --- implementation is in src/fl_arc.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arc.cxx if needed
|
||||
// virtual void arc(double x, double y, double r, double start, double end);
|
||||
// // --- implementation is in src/fl_arci.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_arci.cxx
|
||||
virtual void arc(int x, int y, int w, int h, double a1, double a2) ;
|
||||
virtual void pie(int x, int y, int w, int h, double a1, double a2) ;
|
||||
// // --- implementation is in src/fl_curve.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_curve.cxx if needed
|
||||
// virtual void curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3, double Y3);
|
||||
// // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
|
||||
virtual void line_style(int style, int width=0, char* dashes=0) ;
|
||||
// // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
|
||||
// virtual void color(Fl_Color c) { color_ = c; }
|
||||
// virtual Fl_Color color() { return color_; }
|
||||
virtual void color(uchar r, uchar g, uchar b) ;
|
||||
// // --- implementation is in src/fl_font.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_font.cxx
|
||||
virtual void draw(const char *str, int n, int x, int y) ;
|
||||
// virtual void draw(const char *str, int n, float x, float y) { draw(str, n, (int)(x+0.5), (int)(y+0.5));}
|
||||
// virtual void draw(int angle, const char *str, int n, int x, int y) { draw(str, n, x, y); }
|
||||
// virtual void rtl_draw(const char *str, int n, int x, int y) { draw(str, n, x, y); }
|
||||
// /** Returns non-zero if the graphics driver possesses the \p feature */
|
||||
// virtual int has_feature(driver_feature feature) { return 0; }
|
||||
// virtual void font(Fl_Font face, Fl_Fontsize fsize) {font_ = face; size_ = fsize;}
|
||||
// virtual Fl_Font font() {return font_; }
|
||||
// virtual Fl_Fontsize size() {return size_; }
|
||||
virtual double width(const char *str, int n);
|
||||
// virtual double width(unsigned int c) { char ch = (char)c; return width(&ch, 1); }
|
||||
virtual int height();
|
||||
virtual int descent();
|
||||
// virtual Fl_Font_Descriptor *font_descriptor() { return font_descriptor_;}
|
||||
// virtual void font_descriptor(Fl_Font_Descriptor *d) { font_descriptor_ = d;}
|
||||
// // --- implementation is in src/fl_image.cxx which includes src/drivers/xxx/Fl_xxx_Graphics_Driver_font.cxx
|
||||
virtual Fl_Bitmask create_bitmask(int w, int h, const uchar *array) ;
|
||||
// virtual void cache(Fl_Pixmap *img) { return 0; }
|
||||
// virtual void cache(Fl_Bitmap *img) { return 0; }
|
||||
// virtual void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) { }
|
||||
virtual void delete_bitmask(Fl_Bitmask bm) ;
|
||||
// virtual void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) {}
|
||||
// virtual void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) {}
|
||||
// virtual void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) {}
|
||||
// virtual void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) {}
|
||||
// /** \brief Draws an Fl_RGB_Image object to the device.
|
||||
// *
|
||||
// Specifies a bounding box for the image, with the origin (upper left-hand corner) of
|
||||
// the image offset by the cx and cy arguments.
|
||||
// */
|
||||
// virtual void draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) {}
|
||||
// /** \brief Draws an Fl_Pixmap object to the device.
|
||||
// *
|
||||
// Specifies a bounding box for the image, with the origin (upper left-hand corner) of
|
||||
// the image offset by the cx and cy arguments.
|
||||
// */
|
||||
// virtual void draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy) {}
|
||||
// /** \brief Draws an Fl_Bitmap object to the device.
|
||||
// *
|
||||
// Specifies a bounding box for the image, with the origin (upper left-hand corner) of
|
||||
// the image offset by the cx and cy arguments.
|
||||
// */
|
||||
// virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {}
|
||||
// virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
|
||||
//
|
||||
// /** Sets the value of the driver-specific graphics context. */
|
||||
// virtual void gc(void*) {}
|
||||
// /** Returns the driver-specific graphics context, of NULL if there's none. */
|
||||
// virtual void *gc(void) {return NULL;}
|
||||
// /** Support for pixmap drawing */
|
||||
// virtual uchar **mask_bitmap() { return 0; }
|
||||
// /** Support for pixmap drawing */
|
||||
// virtual void mask_bitmap(uchar **) {}
|
||||
//protected:
|
||||
// // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
|
||||
// virtual void transformed_vertex0(COORD_T x, COORD_T y);
|
||||
// virtual void fixloop();
|
||||
};
|
||||
|
||||
#endif // FL_PICO_GRAPHICS_DRIVER_H
|
@ -1,506 +0,0 @@
|
||||
//
|
||||
// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2020 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_Pico_Graphics_Driver.H"
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/math.h>
|
||||
|
||||
|
||||
static int sign(int x) { return (x>0)-(x<0); }
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::point(int x, int y)
|
||||
{
|
||||
// This is the one method that *must* be overridden in the final driver
|
||||
// class. All other methods can be derived from this one method. The
|
||||
// result should work, but will be slow and inefficient.
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::rect(int x, int y, int w, int h)
|
||||
{
|
||||
int x1 = x+w-1, y1 = y+h-1;
|
||||
xyline(x, y, x1);
|
||||
xyline(x, y1, x1);
|
||||
yxline(x, y, y1);
|
||||
yxline(x1, y, y1);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::rectf(int x, int y, int w, int h)
|
||||
{
|
||||
int i = y, n = y+h, xn = x+w-1;
|
||||
for ( ; i<n; i++) {
|
||||
xyline(x, i, xn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::line(int x, int y, int x1, int y1)
|
||||
{
|
||||
if (x==x1) {
|
||||
return yxline(x, y, y1);
|
||||
}
|
||||
if (y==y1) {
|
||||
return xyline(x, y, x1);
|
||||
}
|
||||
// Bresenham
|
||||
int w = x1 - x, dx = abs(w);
|
||||
int h = y1 - y, dy = abs(h);
|
||||
int dx1 = sign(w), dy1 = sign(h), dx2, dy2;
|
||||
int min, max;
|
||||
if (dx < dy) {
|
||||
min = dx; max = dy;
|
||||
dx2 = 0;
|
||||
dy2 = dy1;
|
||||
} else {
|
||||
min = dy; max = dx;
|
||||
dx2 = dx1;
|
||||
dy2 = 0;
|
||||
}
|
||||
int num = max/2;
|
||||
for (int i=max+1; i>0; i--) {
|
||||
point(x, y);
|
||||
num += min;
|
||||
if (num>=max) {
|
||||
num -= max;
|
||||
x += dx1;
|
||||
y += dy1;
|
||||
} else {
|
||||
x += dx2;
|
||||
y += dy2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
line(x, y, x1, y1);
|
||||
line(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::xyline(int x, int y, int x1)
|
||||
{
|
||||
int i;
|
||||
if (x1<x) {
|
||||
int tmp = x; x = x1; x1 = tmp;
|
||||
}
|
||||
for (i=x; i<=x1; i++) {
|
||||
point(i, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::xyline(int x, int y, int x1, int y2)
|
||||
{
|
||||
xyline(x, y, x1);
|
||||
yxline(x1, y, y2);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3)
|
||||
{
|
||||
xyline(x, y, x1);
|
||||
yxline(x1, y, y2);
|
||||
xyline(x1, y2, x3);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::yxline(int x, int y, int y1)
|
||||
{
|
||||
int i;
|
||||
if (y1<y) {
|
||||
int tmp = y; y = y1; y1 = tmp;
|
||||
}
|
||||
for (i=y; i<=y1; i++) {
|
||||
point(x, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::yxline(int x, int y, int y1, int x2)
|
||||
{
|
||||
yxline(x, y, y1);
|
||||
xyline(x, y1, x2);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3)
|
||||
{
|
||||
yxline(x, y, y1);
|
||||
xyline(x, y1, x2);
|
||||
yxline(x2, y1, y3);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
line(x0, y0, x1, y1);
|
||||
line(x1, y1, x2, y2);
|
||||
line(x2, y2, x0, y0);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
|
||||
{
|
||||
line(x0, y0, x1, y1);
|
||||
line(x1, y1, x2, y2);
|
||||
line(x2, y2, x3, y3);
|
||||
line(x3, y3, x0, y0);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
// FIXME: fill
|
||||
line(x0, y0, x1, y1);
|
||||
line(x1, y1, x2, y2);
|
||||
line(x2, y2, x0, y0);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
|
||||
{
|
||||
// FIXME: fill
|
||||
line(x0, y0, x1, y1);
|
||||
line(x1, y1, x2, y2);
|
||||
line(x2, y2, x3, y3);
|
||||
line(x3, y3, x0, y0);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::push_clip(int x, int y, int w, int h)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H)
|
||||
{
|
||||
X = x; Y = y; W = w; H = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Graphics_Driver::not_clipped(int x, int y, int w, int h)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::push_no_clip()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::pop_clip()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static double px, py; // FIXME: aaaah!
|
||||
static double pxf, pyf;
|
||||
static int pn;
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::begin_points()
|
||||
{
|
||||
what = POINT_;
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::begin_complex_polygon()
|
||||
{
|
||||
what = POLYGON;
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::begin_line()
|
||||
{
|
||||
what = LINE;
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::begin_loop()
|
||||
{
|
||||
what = LOOP;
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::begin_polygon()
|
||||
{
|
||||
what = POLYGON;
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::transformed_vertex(double x, double y)
|
||||
{
|
||||
if (pn>0) {
|
||||
switch (what) {
|
||||
case POINT_: point(x, y); break;
|
||||
case LINE: line(px, py, x, y); break;
|
||||
case LOOP: line(px, py, x, y); break;
|
||||
case POLYGON: line(px, py, x, y); break; // FIXME: fill!
|
||||
}
|
||||
}
|
||||
if (pn==0 ) { pxf = x; pyf = y; }
|
||||
px = x; py = y;
|
||||
pn++;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::vertex(double x, double y)
|
||||
{
|
||||
transformed_vertex(x*m.a + y*m.c + m.x, x*m.b + y*m.d + m.y);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::end_points()
|
||||
{
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::end_line()
|
||||
{
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::end_loop()
|
||||
{
|
||||
line(px, py, pxf, pyf);
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::end_polygon()
|
||||
{
|
||||
line(px, py, pxf, pyf); // FIXME: fill!
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::end_complex_polygon()
|
||||
{
|
||||
line(px, py, pxf, pyf); // FIXME: fill!
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::gap()
|
||||
{
|
||||
pn = 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::circle(double x, double y, double r)
|
||||
{
|
||||
begin_loop();
|
||||
double X = r;
|
||||
double Y = 0;
|
||||
fl_vertex(x+X,y+Y);
|
||||
|
||||
double rx = fabs(transform_dx(r, r));
|
||||
double ry = fabs(transform_dy(r, r));
|
||||
|
||||
double circ = M_PI*0.5*(rx+ry);
|
||||
int segs = circ * 360 / 1000; // every line is about three pixels long
|
||||
if (segs<16) segs = 16;
|
||||
|
||||
double A = 2*M_PI;
|
||||
int i = segs;
|
||||
|
||||
if (i) {
|
||||
double epsilon = A/i; // Arc length for equal-size steps
|
||||
double cos_e = cos(epsilon); // Rotation coefficients
|
||||
double sin_e = sin(epsilon);
|
||||
do {
|
||||
double Xnew = cos_e*X + sin_e*Y;
|
||||
Y = -sin_e*X + cos_e*Y;
|
||||
fl_vertex(x + (X=Xnew), y + Y);
|
||||
} while (--i);
|
||||
}
|
||||
end_loop();
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::arc(int xi, int yi, int w, int h, double a1, double a2)
|
||||
{
|
||||
if (a2<=a1) return;
|
||||
|
||||
double rx = w/2.0;
|
||||
double ry = h/2.0;
|
||||
double x = xi + rx;
|
||||
double y = yi + ry;
|
||||
double circ = M_PI*0.5*(rx+ry);
|
||||
int i, segs = circ * (a2-a1) / 1000; // every line is about three pixels long
|
||||
if (segs<3) segs = 3;
|
||||
|
||||
int px, py;
|
||||
a1 = a1/180*M_PI;
|
||||
a2 = a2/180*M_PI;
|
||||
double step = (a2-a1)/segs;
|
||||
|
||||
int nx = x + sin(a1)*rx;
|
||||
int ny = y - cos(a1)*ry;
|
||||
for (i=segs; i>0; i--) {
|
||||
a1+=step;
|
||||
px = nx; py = ny;
|
||||
nx = x + sin(a1)*rx;
|
||||
ny = y - cos(a1)*ry;
|
||||
line(px, py, nx, ny);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2)
|
||||
{
|
||||
// FIXME: implement this
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::line_style(int style, int width, char* dashes)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::color(uchar r, uchar g, uchar b)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Fl_Bitmask Fl_Pico_Graphics_Driver::create_bitmask(int w, int h, const uchar *array)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::delete_bitmask(Fl_Bitmask bm)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|01234567|
|
||||
-+--------+
|
||||
0| |____
|
||||
1|++++++++|font
|
||||
2|++++++++|
|
||||
3|++++++++|
|
||||
4|++++++++|
|
||||
5|++++++++|____
|
||||
6| |descent
|
||||
7| |
|
||||
-+--------+
|
||||
*/
|
||||
|
||||
|
||||
static const char *font_data[128] = {
|
||||
/*00*/0, /*01*/0, /*02*/0, /*03*/0,
|
||||
/*04*/0, /*05*/0, /*06*/0, /*07*/0,
|
||||
/*08*/0, /*09*/0, /*0A*/0, /*0B*/0,
|
||||
/*0C*/0, /*0D*/0, /*0E*/0, /*0F*/0,
|
||||
/*10*/0, /*11*/0, /*12*/0, /*13*/0,
|
||||
/*14*/0, /*15*/0, /*16*/0, /*17*/0,
|
||||
/*18*/0, /*19*/0, /*1A*/0, /*1B*/0,
|
||||
/*1C*/0, /*1D*/0, /*1E*/0, /*1F*/0,
|
||||
/* */0, /*!*/"\31\34\100\35\36", /*"*/"\31\22\100\51\42", /*#*/"\31\15\100\61\45\100\12\72\100\04\64",
|
||||
/*$*/"\62\51\11\02\13\53\64\55\15\04\100\30\36", /*%*/"\21\11\02\13\23\32\21\100\15\51\100\34\43\53\64\55\45\34", /*&*/"\63\45\15\04\13\52\41\21\12\65", /*'*/"\31\22",
|
||||
/*(*/"\51\32\23\24\35\56", /*)*/"\21\42\53\54\45\26", /***/"\31\33\15\100\33\55\100\02\33\62", /*+*/"\35\31\100\03\63",
|
||||
/*,*/"\35\45\36", /*-*/"\13\53", /*.*/"\35\36", /* / */"\51\15",
|
||||
/*0*/"\21\12\14\25\55\64\62\51\21\100\24\52", /*1*/"\22\41\45", /*2*/"\12\21\51\62\53\24\15\65", /*3*/"\12\21\51\62\53\64\55\25\14\100\53\33",
|
||||
/*4*/"\55\51\04\64", /*5*/"\14\25\55\64\53\13\21\61", /*6*/"\62\51\21\12\14\25\55\64\53\13", /*7*/"\11\61\33\25",
|
||||
/*8*/"\12\21\51\62\53\64\55\25\14\23\12\100\23\53", /*9*/"\14\25\55\64\62\51\21\12\23\63", /*:*/"\32\33\100\35\36", /*;*/"\32\33\100\25\35\26",
|
||||
/*<*/"\62\13\64", /*=*/"\12\62\100\14\64", /*>*/"\12\63\14", /*?*/"\12\21\51\62\43\34\35\100\36\37",
|
||||
/*@*/"\56\16\05\02\11\51\62\64\55\35\24\23\32\52\63", /*A*/"\05\31\65\100\14\54", /*B*/"\11\51\62\53\64\55\15\11\100\13\53", /*C*/"\62\51\11\02\04\15\55\64",
|
||||
/*D*/"\11\51\62\64\55\15\11", /*E*/"\61\11\15\65\100\13\53", /*F*/"\61\11\15\100\13\53", /*G*/"\62\51\11\02\04\15\55\64\63\33",
|
||||
/*H*/"\11\15\100\61\65\100\13\63", /*I*/"\21\41\100\25\45\100\35\31", /*J*/"\51\54\45\15\04", /*K*/"\11\15\100\14\61\100\65\33",
|
||||
/*L*/"\11\15\65", /*M*/"\05\01\35\61\65", /*N*/"\05\01\65\61", /*O*/"\02\11\51\62\64\55\15\04\02",
|
||||
/*P*/"\15\11\51\62\53\13", /*Q*/"\02\11\51\62\64\55\15\04\02\100\65\34", /*R*/"\15\11\51\62\53\13\100\33\65", /*S*/"\62\51\11\02\13\53\64\55\15\04",
|
||||
/*T*/"\01\61\100\31\35", /*U*/"\61\64\55\15\04\01", /*V*/"\01\35\61", /*W*/"\01\15\31\55\61",
|
||||
/*X*/"\01\65\100\05\61", /*Y*/"\01\33\35\100\33\61", /*Z*/"\01\61\05\65", /*[*/"\51\31\36\56",
|
||||
/*\*/"\21\55", /*]*/"\21\41\46\26", /*^*/"\13\31\53", /*_*/"\06\76",
|
||||
/*`*/"\31\42", /*a*/"\22\52\63\65\100\63\23\14\25\55\64", /*b*/"\11\15\100\14\25\55\64\63\52\22\13", /*c*/"\63\52\22\13\14\25\55\64",
|
||||
/*d*/"\61\65\100\64\55\25\14\13\22\52\63", /*e*/"\64\63\52\22\13\14\25\55\100\64\14", /*f*/"\35\32\41\51\100\22\52", /*g*/"\62\65\56\26\100\63\52\22\13\14\25\55\64",
|
||||
/*h*/"\11\15\100\65\63\52\22\13", /*i*/"\31\32\100\33\100\23\33\35\100\25\45", /*j*/"\31\32\100\33\35\26\16", /*k*/"\11\15\100\14\62\100\33\65",
|
||||
/*l*/"\31\34\45\55", /*m*/"\05\02\100\03\12\22\33\35\100\33\42\52\63\65", /*n*/"\12\15\100\13\22\52\63\65", /*o*/"\22\13\14\25\55\64\63\52\22",
|
||||
/*p*/"\16\12\100\13\22\52\63\64\55\25\14", /*q*/"\62\66\100\63\52\22\13\14\25\55\64", /*r*/"\22\25\100\23\32\42\53", /*s*/"\63\52\22\13\64\55\25\14",
|
||||
/*t*/"\31\34\45\55\100\22\42", /*u*/"\12\14\25\55\64\62\100\64\65", /*v*/"\62\35\02", /*w*/"\02\15\32\55\62",
|
||||
/*x*/"\62\15\100\65\12", /*y*/"\12\45\62\100\45\36\16", /*z*/"\12\62\15\65", /*{*/"\51\41\32\33\24\35\36\47\57\100\14\24",
|
||||
/*|*/"\31\37", /*}*/"\21\31\42\43\54\64\100\54\45\46\37\27", /*~*/"\12\21\31\42\52\61", /*7F*/0
|
||||
};
|
||||
|
||||
|
||||
double Fl_Pico_Graphics_Driver::width(const char *str, int n) {
|
||||
return size_*n*0.5;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Graphics_Driver::descent() {
|
||||
return (int)(size_ - size_*0.8);
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Graphics_Driver::height() {
|
||||
return (int)(size_);
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Graphics_Driver::draw(const char *str, int n, int x, int y)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<n; i++) {
|
||||
char c = str[i] & 0x7f;
|
||||
const char *fd = font_data[(int)c];
|
||||
if (fd) {
|
||||
char rendering = 0;
|
||||
float px=0.0f, py=0.0f;
|
||||
for (;;) {
|
||||
char cmd = *fd++;
|
||||
if (cmd==0) {
|
||||
if (rendering) {
|
||||
end_line();
|
||||
rendering = 0;
|
||||
}
|
||||
break;
|
||||
} else if (cmd>63) {
|
||||
if (cmd=='\100' && rendering) {
|
||||
end_line();
|
||||
rendering = 0;
|
||||
}
|
||||
} else {
|
||||
if (!rendering) { begin_line(); rendering = 1; }
|
||||
int vx = (cmd & '\70')>>3;
|
||||
int vy = (cmd & '\07');
|
||||
px = (int)(0.5+x+vx*size_*0.5/8.0);
|
||||
py = (int)(0.5+y+vy*size_/8.0-0.8*size_);
|
||||
vertex(px, py);
|
||||
}
|
||||
}
|
||||
}
|
||||
x += size_*0.5;
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
|
@ -1,58 +0,0 @@
|
||||
//
|
||||
// Definition of Pico Screen interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_Pico_Screen_Driver.H
|
||||
\brief Definition of Pico Screen interface.
|
||||
*/
|
||||
|
||||
#ifndef FL_PICO_SCREEN_DRIVER_H
|
||||
#define FL_PICO_SCREEN_DRIVER_H
|
||||
|
||||
#include "../../Fl_Screen_Driver.H"
|
||||
|
||||
|
||||
class FL_EXPORT Fl_Pico_Screen_Driver : public Fl_Screen_Driver
|
||||
{
|
||||
public:
|
||||
Fl_Pico_Screen_Driver();
|
||||
virtual ~Fl_Pico_Screen_Driver();
|
||||
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);
|
||||
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 int ready();
|
||||
virtual void grab(Fl_Window* win);
|
||||
// --- global colors
|
||||
virtual void get_system_colors();
|
||||
// --- 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);
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_PICO_SCREEN_DRIVER_H
|
@ -1,132 +0,0 @@
|
||||
//
|
||||
// Definition of SDL Screen interface based on Pico
|
||||
//
|
||||
// Copyright 1998-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_Pico_Screen_Driver.H"
|
||||
|
||||
|
||||
|
||||
Fl_Pico_Screen_Driver::Fl_Pico_Screen_Driver()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Fl_Pico_Screen_Driver::~Fl_Pico_Screen_Driver()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::init()
|
||||
{
|
||||
// nothing to do yet
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Screen_Driver::x()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Screen_Driver::y()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Screen_Driver::w()
|
||||
{
|
||||
return 800;
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Screen_Driver::h()
|
||||
{
|
||||
return 600;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::screen_xywh(int &X, int &Y, int &W, int &H, int n)
|
||||
{
|
||||
X = x();
|
||||
Y = y();
|
||||
W = w();
|
||||
H = h();
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::screen_dpi(float &h, float &v, int n)
|
||||
{
|
||||
h = 75.0;
|
||||
v = 75.0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::screen_work_area(int &X, int &Y, int &W, int &H, int n)
|
||||
{
|
||||
X = x();
|
||||
Y = y();
|
||||
W = w();
|
||||
H = h();
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::beep(int type)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::flush()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Screen_Driver::ready()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::grab(Fl_Window* win)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::get_system_colors()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::add_timeout(double time, Fl_Timeout_Handler cb, void *argp)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Screen_Driver::has_timeout(Fl_Timeout_Handler cb, void *argp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Fl_Pico_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void *argp)
|
||||
{
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
//
|
||||
// Definition of Pico system driver
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
#ifndef FL_PICO_SYSTEM_DRIVER_H
|
||||
#define FL_PICO_SYSTEM_DRIVER_H
|
||||
|
||||
#include "../../Fl_System_Driver.H"
|
||||
|
||||
class Fl_Pico_System_Driver : public Fl_System_Driver {
|
||||
public:
|
||||
Fl_Pico_System_Driver() : Fl_System_Driver() {}
|
||||
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);
|
||||
};
|
||||
|
||||
#endif /* FL_PICO_SYSTEM_DRIVER_H */
|
@ -1,19 +0,0 @@
|
||||
//
|
||||
// Definition of Pico system driver
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
#include "Fl_Pico_System_Driver.H"
|
||||
#include "../../flstring.h"
|
@ -1,41 +0,0 @@
|
||||
//
|
||||
// Definition of Pico Window interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_Pico_Window_Driver.H
|
||||
\brief Definition of Pico Window interface.
|
||||
*/
|
||||
|
||||
#ifndef FL_PICO_WINDOW_DRIVER_H
|
||||
#define FL_PICO_WINDOW_DRIVER_H
|
||||
|
||||
#include "../../Fl_Window_Driver.H"
|
||||
|
||||
|
||||
class FL_EXPORT Fl_Pico_Window_Driver : public Fl_Window_Driver
|
||||
{
|
||||
public:
|
||||
Fl_Pico_Window_Driver(Fl_Window *win);
|
||||
virtual ~Fl_Pico_Window_Driver();
|
||||
|
||||
// --- window data
|
||||
virtual int decorated_w();
|
||||
virtual int decorated_h();
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_PICO_WINDOW_DRIVER_H
|
@ -1,46 +0,0 @@
|
||||
//
|
||||
// Definition of SDL Window interface based on Pico
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_Pico_Window_Driver.H"
|
||||
|
||||
#include <FL/platform.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
|
||||
Fl_Pico_Window_Driver::Fl_Pico_Window_Driver(Fl_Window *win)
|
||||
: Fl_Window_Driver(win)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Fl_Pico_Window_Driver::~Fl_Pico_Window_Driver()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Window_Driver::decorated_w()
|
||||
{
|
||||
return w();
|
||||
}
|
||||
|
||||
|
||||
int Fl_Pico_Window_Driver::decorated_h()
|
||||
{
|
||||
return h();
|
||||
}
|
@ -1 +0,0 @@
|
||||
|
@ -1,119 +0,0 @@
|
||||
|
||||
//
|
||||
// Definition of the Pico Android graphics driver
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_PicoAndroid_Graphics_Driver.H
|
||||
\brief Definition of Pico minimal graphics driver.
|
||||
*/
|
||||
|
||||
#ifndef FL_PICOANDROID_GRAPHICS_DRIVER_H
|
||||
#define FL_PICOANDROID_GRAPHICS_DRIVER_H
|
||||
|
||||
#include "../Pico/Fl_Pico_Graphics_Driver.H"
|
||||
|
||||
|
||||
/**
|
||||
\brief The Pico minimal SDL graphics class.
|
||||
|
||||
This class is implemented as a base class for minimal core SDL drivers.
|
||||
*/
|
||||
class Fl_PicoAndroid_Graphics_Driver : public Fl_Pico_Graphics_Driver {
|
||||
protected:
|
||||
// CGContextRef gc_;
|
||||
public:
|
||||
// virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
|
||||
// virtual void gc(void *ctxt) {if (ctxt != gc_) global_gc(); gc_ = (CGContextRef)ctxt; }
|
||||
// virtual void *gc() {return gc_;}
|
||||
// char can_do_alpha_blending();
|
||||
//
|
||||
// // --- bitmap stuff
|
||||
// Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
|
||||
// void delete_bitmask(Fl_Bitmask bm);
|
||||
// void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
// void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
// void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
// void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
|
||||
// void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
|
||||
// void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
|
||||
// void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
|
||||
// void cache(Fl_Pixmap *img);
|
||||
// void cache(Fl_Bitmap *img);
|
||||
// void cache(Fl_RGB_Image *img);
|
||||
// void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
|
||||
// void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
|
||||
// void draw_CGImage(CGImageRef cgimg, int x, int y, int w, int h, int srcx, int srcy, int sw, int sh);
|
||||
//protected:
|
||||
// // --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/quartz_rect.cxx
|
||||
void point(int x, int y);
|
||||
// void rect(int x, int y, int w, int h);
|
||||
void rectf(int x, int y, int w, int h);
|
||||
void line(int x, int y, int x1, int y1);
|
||||
// void line(int x, int y, int x1, int y1, int x2, int y2);
|
||||
// void xyline(int x, int y, int x1);
|
||||
// void xyline(int x, int y, int x1, int y2);
|
||||
// void xyline(int x, int y, int x1, int y2, int x3);
|
||||
// void yxline(int x, int y, int y1);
|
||||
// void yxline(int x, int y, int y1, int x2);
|
||||
// void yxline(int x, int y, int y1, int x2, int y3);
|
||||
// void loop(int x0, int y0, int x1, int y1, int x2, int y2);
|
||||
// void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
// void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
|
||||
// void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int 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();
|
||||
// // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
|
||||
// void begin_complex_polygon();
|
||||
// void transformed_vertex(double xf, double yf);
|
||||
// void vertex(double x, double y);
|
||||
// void end_points();
|
||||
// void end_line();
|
||||
// void end_loop();
|
||||
// void end_polygon();
|
||||
// void end_complex_polygon();
|
||||
// void gap();
|
||||
// void circle(double x, double y, double r);
|
||||
// // --- 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
|
||||
// void arc(int x, int y, int w, int h, double a1, double a2);
|
||||
// void pie(int x, int y, int w, int h, double a1, double a2);
|
||||
// // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
|
||||
// void line_style(int style, int width=0, char* dashes=0);
|
||||
// // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
|
||||
// void color(Fl_Color c);
|
||||
// Fl_Color color() { return color_; }
|
||||
// void color(uchar r, uchar g, uchar b);
|
||||
// // --- implementation is in src/fl_font.cxx which includes src/cfg_gfx/xxx_font.cxx
|
||||
// void draw(const char *str, int n, int x, int y);
|
||||
// void draw(const char *str, int n, float x, float y);
|
||||
// void draw(int angle, const char *str, int n, int x, int y);
|
||||
// void rtl_draw(const char *str, int n, int x, int y);
|
||||
// void font(Fl_Font face, Fl_Fontsize fsize);
|
||||
// double width(const char *str, int n);
|
||||
// double width(unsigned int c);
|
||||
// void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
|
||||
// int height();
|
||||
// int descent();
|
||||
};
|
||||
|
||||
#endif // FL_PICOANDROID_GRAPHICS_DRIVER_H
|
@ -1,97 +0,0 @@
|
||||
//
|
||||
// Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_PicoAndroid_Graphics_Driver.h"
|
||||
|
||||
#include <jni.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <android/log.h>
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
#include <FL/Fl.H>
|
||||
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
|
||||
|
||||
|
||||
/*
|
||||
By linking this module, the following static method will instantiate the
|
||||
PicoSDL Graphics driver as the main display driver.
|
||||
*/
|
||||
Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
|
||||
{
|
||||
return new Fl_PicoAndroid_Graphics_Driver();
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoAndroid_Graphics_Driver::rectf(int x, int y, int w, int h)
|
||||
{
|
||||
GLfloat q3[] = {
|
||||
x, y,
|
||||
x, y+h-3,
|
||||
x+w-3, y+h-3,
|
||||
x+w-3, y
|
||||
};
|
||||
|
||||
uchar r, g, b;
|
||||
Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
|
||||
glColor4ub(r, g, b, 255);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, q3);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoAndroid_Graphics_Driver::line(int x, int y, int x1, int y1)
|
||||
{
|
||||
GLfloat q3[] = {
|
||||
x, y,
|
||||
x1, y1
|
||||
};
|
||||
|
||||
uchar r, g, b;
|
||||
Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
|
||||
glColor4ub(r, g, b, 255);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, q3);
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoAndroid_Graphics_Driver::point(int x, int y)
|
||||
{
|
||||
GLfloat q3[] = {
|
||||
x, y
|
||||
};
|
||||
|
||||
uchar r, g, b;
|
||||
Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
|
||||
glColor4ub(r, g, b, 255);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(2, GL_FLOAT, 0, q3);
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
//
|
||||
// Definition of Android Screen interface based on Pico
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_PicoAndroid_Screen_Driver.H
|
||||
\brief Definition of SDL Screen interface based on Pico.
|
||||
*/
|
||||
|
||||
#ifndef FL_PICOANDROID_SCREEN_DRIVER_H
|
||||
#define FL_PICOANDROID_SCREEN_DRIVER_H
|
||||
|
||||
#include "../Pico/Fl_Pico_Screen_Driver.H"
|
||||
|
||||
#include <jni.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <android/sensor.h>
|
||||
#include <android/log.h>
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
|
||||
class Fl_PicoAndroid_Window_Driver;
|
||||
|
||||
|
||||
class FL_EXPORT Fl_PicoAndroid_Screen_Driver : public Fl_Pico_Screen_Driver
|
||||
{
|
||||
friend class Fl_PicoAndroid_Window_Driver;
|
||||
|
||||
struct android_app* pApp;
|
||||
EGLDisplay pDisplay;
|
||||
EGLSurface pSurface;
|
||||
EGLContext pContext;
|
||||
int32_t pWidth;
|
||||
int32_t pHeight;
|
||||
|
||||
static void handleAppCmdCB(struct android_app* app, int32_t cmd);
|
||||
void handleAppCmd(struct android_app* app, int32_t cmd);
|
||||
static int32_t handleInputEventCB(struct android_app* app, AInputEvent* event);
|
||||
int32_t handleInputEvent(struct android_app* app, AInputEvent* event);
|
||||
void initDisplay();
|
||||
void termDisplay();
|
||||
|
||||
public:
|
||||
void drawFrame();
|
||||
|
||||
public:
|
||||
Fl_PicoAndroid_Screen_Driver();
|
||||
virtual ~Fl_PicoAndroid_Screen_Driver();
|
||||
virtual double wait(double time_to_wait);
|
||||
|
||||
public:
|
||||
void android_main(struct android_app* state);
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_PICOANDROID_SCREEN_DRIVER_H
|
@ -1,562 +0,0 @@
|
||||
//
|
||||
// Definition of Android Screen interface based on Pico
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
// http://developer.android.com/ndk/reference/group___native_activity.html
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_PicoAndroid_Screen_Driver.H"
|
||||
|
||||
#include <android/window.h>
|
||||
|
||||
#include <FL/platform.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include "../../Fl_Window_Driver.H"
|
||||
#include <FL/Fl_Image_Surface.H>
|
||||
#include <FL/Fl_Graphics_Driver.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
|
||||
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
|
||||
|
||||
|
||||
|
||||
void Fl_PicoAndroid_Screen_Driver::initDisplay()
|
||||
{
|
||||
// initialize OpenGL ES and EGL
|
||||
|
||||
/*
|
||||
* Here specify the attributes of the desired configuration.
|
||||
* Below, we select an EGLConfig with at least 8 bits per color
|
||||
* component compatible with on-screen windows
|
||||
*/
|
||||
const EGLint attribs[] = {
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLint w, h, dummy, format;
|
||||
EGLint numConfigs;
|
||||
EGLConfig config;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
|
||||
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
|
||||
eglInitialize(display, 0, 0);
|
||||
|
||||
/* Here, the application chooses the configuration it desires. In this
|
||||
* sample, we have a very simplified selection process, where we pick
|
||||
* the first EGLConfig that matches our criteria */
|
||||
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
|
||||
|
||||
/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
|
||||
* guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
|
||||
* As soon as we picked a EGLConfig, we can safely reconfigure the
|
||||
* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
|
||||
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
|
||||
|
||||
ANativeWindow_setBuffersGeometry(pApp->window, 0, 0, format);
|
||||
|
||||
surface = eglCreateWindowSurface(display, config, pApp->window, NULL);
|
||||
context = eglCreateContext(display, config, NULL, NULL);
|
||||
|
||||
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
|
||||
LOGW("Unable to eglMakeCurrent");
|
||||
return;
|
||||
}
|
||||
|
||||
eglQuerySurface(display, surface, EGL_WIDTH, &w);
|
||||
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
|
||||
|
||||
this->pDisplay = display;
|
||||
pContext = context;
|
||||
pSurface = surface;
|
||||
pWidth = w;
|
||||
pHeight = h;
|
||||
|
||||
// Initialize GL state.
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glViewport(0, 100, w, h-200);
|
||||
|
||||
// make adjustments for screen ratio
|
||||
float ratio = 3.0 * (float) w / h;
|
||||
glMatrixMode(GL_PROJECTION); // set matrix to projection mode
|
||||
glLoadIdentity(); // reset the matrix to its default state
|
||||
// glFrustumf(-ratio, ratio, -3, 3, 3, 30); // apply the projection matrix
|
||||
glOrthof(0, w/3, h/3, 0, -30, 30); // apply the projection matrix
|
||||
glLineWidth(3);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoAndroid_Screen_Driver::termDisplay()
|
||||
{
|
||||
if (pDisplay != EGL_NO_DISPLAY) {
|
||||
eglMakeCurrent(pDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (pContext != EGL_NO_CONTEXT) {
|
||||
eglDestroyContext(pDisplay, pContext);
|
||||
}
|
||||
if (pSurface != EGL_NO_SURFACE) {
|
||||
eglDestroySurface(pDisplay, pSurface);
|
||||
}
|
||||
eglTerminate(pDisplay);
|
||||
}
|
||||
pDisplay = EGL_NO_DISPLAY;
|
||||
pContext = EGL_NO_CONTEXT;
|
||||
pSurface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoAndroid_Screen_Driver::drawFrame()
|
||||
{
|
||||
if (pDisplay == NULL) {
|
||||
return;
|
||||
}
|
||||
eglSwapBuffers(pDisplay, pSurface);
|
||||
// LOGI("Swapping buffers");
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoAndroid_Screen_Driver::handleAppCmdCB(struct android_app* app, int32_t cmd)
|
||||
{
|
||||
Fl_PicoAndroid_Screen_Driver *This = (Fl_PicoAndroid_Screen_Driver*)(app->userData);
|
||||
This->handleAppCmd(app, cmd);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoAndroid_Screen_Driver::handleAppCmd(struct android_app* app, int32_t cmd)
|
||||
{
|
||||
LOGI("CMD %d", cmd);
|
||||
// struct engine* engine = (struct engine*)app->userData;
|
||||
switch (cmd) {
|
||||
case APP_CMD_SAVE_STATE:
|
||||
// The system has asked us to save our current state. Do so.
|
||||
// engine->app->savedState = malloc(sizeof(struct saved_state));
|
||||
// *((struct saved_state*)engine->app->savedState) = engine->state;
|
||||
// engine->app->savedStateSize = sizeof(struct saved_state);
|
||||
break;
|
||||
case APP_CMD_INIT_WINDOW:
|
||||
// The window is being shown, get it ready.
|
||||
if (pApp->window != NULL) {
|
||||
// the flag below allow for easy development and should be removed when
|
||||
// distributing a final app
|
||||
ANativeActivity_setWindowFlags(pApp->activity, AWINDOW_FLAG_KEEP_SCREEN_ON, 0);
|
||||
initDisplay();
|
||||
drawFrame();
|
||||
}
|
||||
break;
|
||||
case APP_CMD_TERM_WINDOW:
|
||||
// The window is being hidden or closed, clean it up.
|
||||
termDisplay();
|
||||
break;
|
||||
case APP_CMD_GAINED_FOCUS:
|
||||
// When our app gains focus, we start monitoring the accelerometer.
|
||||
// if (engine->accelerometerSensor != NULL) {
|
||||
// ASensorEventQueue_enableSensor(engine->sensorEventQueue,
|
||||
// engine->accelerometerSensor);
|
||||
// // We'd like to get 60 events per second (in us).
|
||||
// ASensorEventQueue_setEventRate(engine->sensorEventQueue,
|
||||
// engine->accelerometerSensor, (1000L/60)*1000);
|
||||
// }
|
||||
break;
|
||||
case APP_CMD_LOST_FOCUS:
|
||||
// When our app loses focus, we stop monitoring the accelerometer.
|
||||
// This is to avoid consuming battery while not being used.
|
||||
// if (engine->accelerometerSensor != NULL) {
|
||||
// ASensorEventQueue_disableSensor(engine->sensorEventQueue,
|
||||
// engine->accelerometerSensor);
|
||||
// }
|
||||
// // Also stop animating.
|
||||
// engine->animating = 0;
|
||||
// engine_draw_frame(engine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32_t Fl_PicoAndroid_Screen_Driver::handleInputEventCB(struct android_app* app, AInputEvent* event)
|
||||
{
|
||||
Fl_PicoAndroid_Screen_Driver *This = (Fl_PicoAndroid_Screen_Driver*)(app->userData);
|
||||
This->handleInputEvent(app, event);
|
||||
}
|
||||
|
||||
|
||||
int32_t Fl_PicoAndroid_Screen_Driver::handleInputEvent(struct android_app* app, AInputEvent* event)
|
||||
{
|
||||
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
|
||||
// fl_lock_function();
|
||||
int x = AMotionEvent_getX(event, 0);
|
||||
int y = AMotionEvent_getY(event, 0);
|
||||
int action = AKeyEvent_getAction(event);
|
||||
Fl_Window *window = Fl::first_window();
|
||||
switch (action) {
|
||||
case AMOTION_EVENT_ACTION_DOWN:
|
||||
Fl::e_is_click = 1;
|
||||
Fl::e_x = Fl::e_x_root = x/3;
|
||||
Fl::e_y = Fl::e_y_root = (y-100)/3;
|
||||
if (!window) break;
|
||||
Fl::e_keysym = FL_Button+FL_LEFT_MOUSE;
|
||||
Fl::e_state = FL_BUTTON1;
|
||||
Fl::handle(FL_PUSH, window);
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_MOVE:
|
||||
Fl::e_is_click = 1;
|
||||
Fl::e_x = Fl::e_x_root = x/3;
|
||||
Fl::e_y = Fl::e_y_root = (y-100)/3;
|
||||
if (!window) break;
|
||||
Fl::e_keysym = FL_Button+FL_LEFT_MOUSE;
|
||||
Fl::e_state = FL_BUTTON1;
|
||||
Fl::handle(FL_DRAG, window);
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_UP:
|
||||
case AMOTION_EVENT_ACTION_CANCEL:
|
||||
Fl::e_is_click = 1;
|
||||
Fl::e_x = Fl::e_x_root = x/3;
|
||||
Fl::e_y = Fl::e_y_root = (y-100)/3;
|
||||
if (!window) break;
|
||||
Fl::e_keysym = FL_Button+FL_LEFT_MOUSE;
|
||||
Fl::e_state = 0;
|
||||
Fl::handle(FL_RELEASE, window);
|
||||
break;
|
||||
// case AMOTION_EVENT_ACTION_HOVER_MOVE:
|
||||
// Fl::e_is_click = 1;
|
||||
// Fl::e_x = Fl::e_x_root = x/3;
|
||||
// Fl::e_y = (y-100)/3;
|
||||
// if (!window) break;
|
||||
// Fl::e_keysym = 0;
|
||||
// Fl::e_state = 0;
|
||||
// Fl::handle(FL_MOVE, window);
|
||||
// break;
|
||||
}
|
||||
// AMOTION_EVENT_ACTION_MASK
|
||||
// LOGI("Motion at %d, %d", x, y);
|
||||
// fl_unlock_function();
|
||||
Fl_X::first->w->redraw();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern int main(int argc, const char **argv);
|
||||
|
||||
void android_main(struct android_app* state)
|
||||
{
|
||||
// LOGI("Android Main call");
|
||||
Fl_PicoAndroid_Screen_Driver *This = (Fl_PicoAndroid_Screen_Driver*)Fl::screen_driver();
|
||||
This->android_main(state);
|
||||
static const char *argv[1] = { "native-activity" };
|
||||
main(1, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
This is the main entry point of a native application that is using
|
||||
android_native_app_glue. It runs in its own thread, with its own
|
||||
event loop for receiving input events and doing other things.
|
||||
*/
|
||||
void Fl_PicoAndroid_Screen_Driver::android_main(struct android_app* state)
|
||||
{
|
||||
app_dummy();
|
||||
|
||||
pApp = state;
|
||||
pApp->userData = this;
|
||||
pApp->onAppCmd = handleAppCmdCB;
|
||||
pApp->onInputEvent = handleInputEventCB;
|
||||
|
||||
|
||||
#if 0
|
||||
struct engine engine;
|
||||
|
||||
// Make sure glue isn't stripped.
|
||||
app_dummy();
|
||||
|
||||
memset(&engine, 0, sizeof(engine));
|
||||
state->userData = &engine;
|
||||
state->onAppCmd = engine_handle_cmd;
|
||||
state->onInputEvent = engine_handle_input;
|
||||
engine.app = state;
|
||||
|
||||
// Prepare to monitor accelerometer
|
||||
engine.sensorManager = ASensorManager_getInstance();
|
||||
engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,
|
||||
ASENSOR_TYPE_ACCELEROMETER);
|
||||
engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,
|
||||
state->looper, LOOPER_ID_USER, NULL, NULL);
|
||||
|
||||
if (state->savedState != NULL) {
|
||||
// We are starting with a previous saved state; restore from it.
|
||||
engine.state = *(struct saved_state*)state->savedState;
|
||||
}
|
||||
|
||||
// loop waiting for stuff to do.
|
||||
|
||||
while (1) {
|
||||
// Read all pending events.
|
||||
int ident;
|
||||
int events;
|
||||
struct android_poll_source* source;
|
||||
|
||||
// If not animating, we will block forever waiting for events.
|
||||
// If animating, we loop until all events are read, then continue
|
||||
// to draw the next frame of animation.
|
||||
while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
|
||||
(void**)&source)) >= 0) {
|
||||
|
||||
// Process this event.
|
||||
if (source != NULL) {
|
||||
source->process(state, source);
|
||||
}
|
||||
|
||||
// If a sensor has data, process it now.
|
||||
if (ident == LOOPER_ID_USER) {
|
||||
if (engine.accelerometerSensor != NULL) {
|
||||
ASensorEvent event;
|
||||
while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
|
||||
&event, 1) > 0) {
|
||||
LOGI("accelerometer: x=%f y=%f z=%f",
|
||||
event.acceleration.x, event.acceleration.y,
|
||||
event.acceleration.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we are exiting.
|
||||
if (state->destroyRequested != 0) {
|
||||
engine_term_display(&engine);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (engine.animating) {
|
||||
// Done with events; draw next animation frame.
|
||||
engine.state.angle += .01f;
|
||||
if (engine.state.angle > 1) {
|
||||
engine.state.angle = 0;
|
||||
}
|
||||
|
||||
// Drawing is throttled to the screen update rate, so there
|
||||
// is no need to do timing here.
|
||||
engine_draw_frame(&engine);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Fl_Screen_Driver* Fl_Screen_Driver::newScreenDriver()
|
||||
{
|
||||
return new Fl_PicoAndroid_Screen_Driver();
|
||||
}
|
||||
|
||||
|
||||
Fl_PicoAndroid_Screen_Driver::Fl_PicoAndroid_Screen_Driver()
|
||||
{
|
||||
pDisplay = EGL_NO_DISPLAY;
|
||||
pContext = EGL_NO_CONTEXT;
|
||||
pSurface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
Fl_PicoAndroid_Screen_Driver::~Fl_PicoAndroid_Screen_Driver()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
double Fl_PicoAndroid_Screen_Driver::wait(double time_to_wait)
|
||||
{
|
||||
Fl::flush();
|
||||
// Read all pending events.
|
||||
int ident;
|
||||
int events;
|
||||
struct android_poll_source* source;
|
||||
|
||||
// If not animating, we will block forever waiting for events.
|
||||
// If animating, we loop until all events are read, then continue
|
||||
// to draw the next frame of animation.
|
||||
// int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData)
|
||||
if ((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) {
|
||||
|
||||
// Process this event.
|
||||
if (source != NULL) {
|
||||
source->process(pApp, source);
|
||||
}
|
||||
|
||||
// If a sensor has data, process it now.
|
||||
// if (ident == LOOPER_ID_USER) {
|
||||
// if (engine.accelerometerSensor != NULL) {
|
||||
// ASensorEvent event;
|
||||
// while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
|
||||
// &event, 1) > 0) {
|
||||
// LOGI("accelerometer: x=%f y=%f z=%f",
|
||||
// event.acceleration.x, event.acceleration.y,
|
||||
// event.acceleration.z);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Check if we are exiting.
|
||||
// if (state->destroyRequested != 0) {
|
||||
// engine_term_display(&engine);
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
|
||||
// if (engine.animating) {
|
||||
// // Done with events; draw next animation frame.
|
||||
// engine.state.angle += .01f;
|
||||
// if (engine.state.angle > 1) {
|
||||
// engine.state.angle = 0;
|
||||
// }
|
||||
//
|
||||
// // Drawing is throttled to the screen update rate, so there
|
||||
// // is no need to do timing here.
|
||||
// engine_draw_frame(&engine);
|
||||
// }
|
||||
// }
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
The following code should not be here!
|
||||
All this must be refactored into the driver system!
|
||||
*/
|
||||
|
||||
Fl_Fontdesc* fl_fonts = NULL;
|
||||
|
||||
/*
|
||||
|
||||
The following symbols are not found if we naively compile the core modules and
|
||||
no specific platform implementations. This list is a hint at all the functions
|
||||
and methods that probably need to be refactored into the driver system.
|
||||
|
||||
Undefined symbols for architecture x86_64:
|
||||
*/
|
||||
|
||||
#if !defined(FL_DOXYGEN) // *FIXME* silence Doxygen warnings
|
||||
|
||||
void fl_set_spot(int, int, int, int, int, int, Fl_Window*) { }
|
||||
void fl_reset_spot() { }
|
||||
const char *fl_filename_name(char const*) { return 0; }
|
||||
|
||||
//Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() { return 0; }
|
||||
//Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() { return 0; }
|
||||
//void Fl_Graphics_Driver::global_gc() { }
|
||||
int Fl::dnd() { return 0; }
|
||||
void Fl::copy(char const*, int, int, char const*) { }
|
||||
void Fl::paste(Fl_Widget&, int, char const*) { }
|
||||
void Fl::get_mouse(int&, int&) { }
|
||||
int Fl_X::set_cursor(Fl_Cursor) { return 0; }
|
||||
int Fl_X::set_cursor(Fl_RGB_Image const*, int, int) { return 0; }
|
||||
|
||||
//void Fl_Window::size_range_() { }
|
||||
//void Fl_Window::fullscreen_x() { }
|
||||
|
||||
void Fl_Window::make_current()
|
||||
{
|
||||
fl_window = i->xid;
|
||||
current_ = this;
|
||||
}
|
||||
|
||||
//void Fl_Window::fullscreen_off_x(int, int, int, int) { }
|
||||
|
||||
Window fl_xid(const Fl_Window* w)
|
||||
{
|
||||
Fl_X *temp = Fl_X::i(w);
|
||||
return temp ? temp->xid : 0;
|
||||
}
|
||||
|
||||
void Fl_Window::show() {
|
||||
if (!shown()) {
|
||||
Fl_X::make(this);
|
||||
}
|
||||
}
|
||||
|
||||
Fl_X* Fl_X::make(Fl_Window *w)
|
||||
{
|
||||
return w->driver()->makeWindow();
|
||||
}
|
||||
|
||||
void Fl_Window::label(char const*, char const*) { }
|
||||
void Fl_Window::resize(int, int, int, int) { }
|
||||
Fl_Window *Fl_Window::current_;
|
||||
char fl_show_iconic;
|
||||
Window fl_window;
|
||||
//void Fl_Image_Surface::translate(int x, int y) { }
|
||||
//void Fl_Image_Surface::untranslate() { }
|
||||
|
||||
void Fl::add_fd(int, int, Fl_FD_Handler, void*)
|
||||
{
|
||||
}
|
||||
|
||||
void Fl::add_fd(int, Fl_FD_Handler, void*)
|
||||
{
|
||||
}
|
||||
|
||||
void Fl::remove_fd(int)
|
||||
{
|
||||
}
|
||||
|
||||
// these pointers are set by the Fl::lock() function:
|
||||
static void nothing() {}
|
||||
void (*fl_lock_function)() = nothing;
|
||||
void (*fl_unlock_function)() = nothing;
|
||||
|
||||
Fl_Font_Descriptor::~Fl_Font_Descriptor()
|
||||
{
|
||||
}
|
||||
|
||||
#endif // !defined(FL_DOXYGEN)
|
||||
|
||||
#if 0
|
||||
|
||||
ld: error: ./obj/local/armeabi-v7a/objs/native-activity/src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.o: multiple definition of 'Fl_Window::make_current()'
|
||||
ld: ./obj/local/armeabi-v7a/objs/native-activity/src/Fl_Window.o: previous definition here
|
||||
|
||||
ld: error: ./obj/local/armeabi-v7a/objs/native-activity/src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.o: multiple definition of 'Fl_Window::current_'
|
||||
ld: ./obj/local/armeabi-v7a/objs/native-activity/src/Fl_Window.o: previous definition here
|
||||
|
||||
ld: error: ./obj/local/armeabi-v7a/objs/native-activity/src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.o: multiple definition of 'Fl_Window::show()'
|
||||
ld: ./obj/local/armeabi-v7a/objs/native-activity/src/Fl_Window.o: previous definition here
|
||||
|
||||
ld: error: ./obj/local/armeabi-v7a/objs/native-activity/src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.o: multiple definition of 'Fl_Window::label(char const*, char const*)'
|
||||
ld: ./obj/local/armeabi-v7a/objs/native-activity/src/Fl_Window.o: previous definition here
|
||||
|
||||
ld: error: ./obj/local/armeabi-v7a/objs/native-activity/src/drivers/PicoAndroid/Fl_PicoAndroid_Screen_Driver.o: multiple definition of 'Fl_Window::resize(int, int, int, int)'
|
||||
ld: ./obj/local/armeabi-v7a/objs/native-activity/src/Fl_Window.o: previous definition here
|
||||
|
||||
jni/../../src/Fl.cxx:1520: error: undefined reference to 'Fl_Graphics_Driver::add_rectangle_to_region(void*, int, int, int, int)'
|
||||
jni/../../src/Fl_Printer.cxx:115: error: undefined reference to 'Fl_Paged_Device::newPrinterDriver()'
|
||||
jni/../../src/Fl_Window.cxx:312: error: undefined reference to 'Fl_Window_Driver::default_icons(Fl_RGB_Image const**, int)'
|
||||
jni/../../src/fl_shortcut.cxx:330: error: undefined reference to 'fl_local_ctrl'
|
||||
jni/../../src/fl_shortcut.cxx:330: error: undefined reference to 'fl_local_alt'
|
||||
jni/../../src/fl_shortcut.cxx:330: error: undefined reference to 'fl_local_shift'
|
||||
jni/../../src/fl_shortcut.cxx:330: error: undefined reference to 'fl_local_meta'
|
||||
|
||||
drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.o:Fl_PicoAndroid_Window_Driver.cxx:vtable for Fl_PicoAndroid_Window_Driver: error: undefined reference to 'Fl_PicoAndroid_Window_Driver::flush_double()'
|
||||
drivers/PicoAndroid/Fl_PicoAndroid_Window_Driver.o:Fl_PicoAndroid_Window_Driver.cxx:vtable for Fl_PicoAndroid_Window_Driver: error: undefined reference to 'Fl_PicoAndroid_Window_Driver::flush_overlay()'
|
||||
|
||||
#endif
|
@ -1 +0,0 @@
|
||||
|
@ -1,55 +0,0 @@
|
||||
//
|
||||
// Definition of Android Window interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_PicoAndroid_Window_Driver.H
|
||||
\brief Definition of SDL Window interface.
|
||||
*/
|
||||
|
||||
#ifndef FL_PICOANDROID_WINDOW_DRIVER_H
|
||||
#define FL_PICOANDROID_WINDOW_DRIVER_H
|
||||
|
||||
#include "../Pico/Fl_Pico_Window_Driver.H"
|
||||
|
||||
#include <jni.h>
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
|
||||
class FL_EXPORT Fl_PicoAndroid_Window_Driver : public Fl_Pico_Window_Driver
|
||||
{
|
||||
ANativeWindow *pNativeWindow;
|
||||
public:
|
||||
Fl_PicoAndroid_Window_Driver(Fl_Window *win);
|
||||
virtual ~Fl_PicoAndroid_Window_Driver();
|
||||
|
||||
virtual Fl_X *makeWindow();
|
||||
|
||||
// --- window data
|
||||
// virtual int decorated_w() = 0;
|
||||
// virtual int decorated_h() = 0;
|
||||
|
||||
// --- window management
|
||||
// virtual void take_focus();
|
||||
virtual void flush();
|
||||
virtual void flush_double();
|
||||
virtual void flush_overlay();
|
||||
// virtual void draw_begin();
|
||||
// virtual void draw_end();
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_PICOSDL_WINDOW_DRIVER_H
|
@ -1,122 +0,0 @@
|
||||
//
|
||||
// Definition of Android Window interface based on SDL
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_PicoAndroid_Window_Driver.H"
|
||||
|
||||
#include "Fl_PicoAndroid_Screen_Driver.H"
|
||||
|
||||
#include <jni.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <android/sensor.h>
|
||||
#include <android/log.h>
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
#include <FL/platform.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include "../../Fl_Window_Driver.H"
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
|
||||
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *win)
|
||||
{
|
||||
return new Fl_PicoAndroid_Window_Driver(win);
|
||||
}
|
||||
|
||||
|
||||
Fl_PicoAndroid_Window_Driver::Fl_PicoAndroid_Window_Driver(Fl_Window *win)
|
||||
: Fl_Pico_Window_Driver(win)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Fl_PicoAndroid_Window_Driver::~Fl_PicoAndroid_Window_Driver()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Fl_X *Fl_PicoAndroid_Window_Driver::makeWindow()
|
||||
{
|
||||
Fl_PicoAndroid_Screen_Driver *scr = (Fl_PicoAndroid_Screen_Driver*)Fl::screen_driver();
|
||||
|
||||
Fl_Group::current(0);
|
||||
if (parent() && !Fl_X::i(pWindow->window())) {
|
||||
pWindow->set_visible();
|
||||
return 0L;
|
||||
}
|
||||
Window parent;
|
||||
if (pWindow->parent()) {
|
||||
parent = fl_xid(pWindow->window());
|
||||
} else {
|
||||
parent = 0;
|
||||
}
|
||||
Fl_X *x = new Fl_X;
|
||||
other_xid = 0;
|
||||
x->w = pWindow;
|
||||
x->region = 0;
|
||||
if (!pWindow->force_position()) {
|
||||
// pNativeWindow = SDL_CreateWindow(pWindow->label(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w(), h(), 0);
|
||||
} else {
|
||||
// pNativeWindow = SDL_CreateWindow(pWindow->label(), x(), y(), w(), h(), 0);
|
||||
}
|
||||
pNativeWindow = scr->pApp->window;
|
||||
// x->xid = SDL_CreateRenderer(pNativeWindow, -1, SDL_RENDERER_ACCELERATED);
|
||||
x->next = Fl_X::first;
|
||||
wait_for_expose_value = 0;
|
||||
pWindow->i = x;
|
||||
Fl_X::first = x;
|
||||
|
||||
pWindow->set_visible();
|
||||
pWindow->redraw();
|
||||
pWindow->flush();
|
||||
int old_event = Fl::e_number;
|
||||
pWindow->handle(Fl::e_number = FL_SHOW);
|
||||
Fl::e_number = old_event;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoAndroid_Window_Driver::flush()
|
||||
{
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
Fl_X *i = Fl_X::i(pWindow);
|
||||
if (!i) return;
|
||||
fl_clip_region(i->region);
|
||||
i->region = 0;
|
||||
pWindow->draw();
|
||||
Fl_PicoAndroid_Screen_Driver *scr = (Fl_PicoAndroid_Screen_Driver*)Fl::screen_driver();
|
||||
scr->drawFrame();
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void Fl_PicoAndroid_Window_Driver::flush()
|
||||
{
|
||||
Fl_PicoAndroid_Screen_Driver *scr = (Fl_PicoAndroid_Screen_Driver*)Fl::screen_driver();
|
||||
// LOGI("Flush...");
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
pWindow->flush();
|
||||
// fl_color(FL_RED);
|
||||
// fl_rectf(10, 10, 300, 400);
|
||||
scr->drawFrame();
|
||||
}
|
||||
#endif
|
@ -1 +0,0 @@
|
||||
|
@ -1,118 +0,0 @@
|
||||
|
||||
//
|
||||
// Definition of the Pico minimal SDL graphics driver
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_PicoSDL_Graphics_Driver.H
|
||||
\brief Definition of Pico minimal graphics driver.
|
||||
*/
|
||||
|
||||
#ifndef FL_PICOSDL_GRAPHICS_DRIVER_H
|
||||
#define FL_PICOSDL_GRAPHICS_DRIVER_H
|
||||
|
||||
#include "../Pico/Fl_Pico_Graphics_Driver.H"
|
||||
|
||||
|
||||
/**
|
||||
\brief The Pico minimal SDL graphics class.
|
||||
|
||||
This class is implemented as a base class for minimal core SDL drivers.
|
||||
*/
|
||||
class Fl_PicoSDL_Graphics_Driver : public Fl_Pico_Graphics_Driver {
|
||||
protected:
|
||||
// CGContextRef gc_;
|
||||
public:
|
||||
// virtual int has_feature(driver_feature mask) { return mask & NATIVE; }
|
||||
// virtual void *gc() {return gc_;}
|
||||
// char can_do_alpha_blending();
|
||||
//
|
||||
// // --- bitmap stuff
|
||||
// Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
|
||||
// void delete_bitmask(Fl_Bitmask bm);
|
||||
// void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
// void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
// void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy);
|
||||
// void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0);
|
||||
// void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3);
|
||||
// void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0);
|
||||
// void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1);
|
||||
// void cache(Fl_Pixmap *img);
|
||||
// void cache(Fl_Bitmap *img);
|
||||
// void cache(Fl_RGB_Image *img);
|
||||
// void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_);
|
||||
// void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy);
|
||||
// void draw_CGImage(CGImageRef cgimg, int x, int y, int w, int h, int srcx, int srcy, int sw, int sh);
|
||||
//protected:
|
||||
// // --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/quartz_rect.cxx
|
||||
void point(int x, int y);
|
||||
// void rect(int x, int y, int w, int h);
|
||||
void rectf(int x, int y, int w, int h);
|
||||
void line(int x, int y, int x1, int y1);
|
||||
// void line(int x, int y, int x1, int y1, int x2, int y2);
|
||||
void xyline(int x, int y, int x1) { line(x, y, x1, y); }
|
||||
// void xyline(int x, int y, int x1, int y2);
|
||||
// void xyline(int x, int y, int x1, int y2, int x3);
|
||||
void yxline(int x, int y, int y1) { line(x, y, x, y1); }
|
||||
// void yxline(int x, int y, int y1, int x2);
|
||||
// void yxline(int x, int y, int y1, int x2, int y3);
|
||||
// void loop(int x0, int y0, int x1, int y1, int x2, int y2);
|
||||
// void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
// void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
|
||||
// void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int 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();
|
||||
// // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
|
||||
// void begin_complex_polygon();
|
||||
// void transformed_vertex(double xf, double yf);
|
||||
// void vertex(double x, double y);
|
||||
// void end_points();
|
||||
// void end_line();
|
||||
// void end_loop();
|
||||
// void end_polygon();
|
||||
// void end_complex_polygon();
|
||||
// void gap();
|
||||
// void circle(double x, double y, double r);
|
||||
// // --- 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
|
||||
// void arc(int x, int y, int w, int h, double a1, double a2);
|
||||
// void pie(int x, int y, int w, int h, double a1, double a2);
|
||||
// // --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
|
||||
// void line_style(int style, int width=0, char* dashes=0);
|
||||
// // --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
|
||||
// void color(Fl_Color c);
|
||||
// Fl_Color color() { return color_; }
|
||||
// void color(uchar r, uchar g, uchar b);
|
||||
// // --- implementation is in src/fl_font.cxx which includes src/cfg_gfx/xxx_font.cxx
|
||||
// void draw(const char *str, int n, int x, int y);
|
||||
// void draw(const char *str, int n, float x, float y);
|
||||
// void draw(int angle, const char *str, int n, int x, int y);
|
||||
// void rtl_draw(const char *str, int n, int x, int y);
|
||||
// void font(Fl_Font face, Fl_Fontsize fsize);
|
||||
// double width(const char *str, int n);
|
||||
// double width(unsigned int c);
|
||||
// void text_extents(const char*, int n, int& dx, int& dy, int& w, int& h);
|
||||
// int height();
|
||||
// int descent();
|
||||
};
|
||||
|
||||
#endif // FL_PICOSDL_GRAPHICS_DRIVER_H
|
@ -1,68 +0,0 @@
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_PicoSDL_Graphics_Driver.H"
|
||||
|
||||
#include "Fl_PicoSDL_Screen_Driver.H"
|
||||
#include <FL/platform.H>
|
||||
#include "../../Fl_Window_Driver.H"
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#define __APPLE__
|
||||
#include <SDL2/SDL.h>
|
||||
#undef __APPLE__
|
||||
|
||||
extern Window fl_window;
|
||||
|
||||
|
||||
/*
|
||||
By linking this module, the following static method will instantiate the
|
||||
PicoSDL Graphics driver as the main display driver.
|
||||
*/
|
||||
Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver()
|
||||
{
|
||||
return new Fl_PicoSDL_Graphics_Driver();
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoSDL_Graphics_Driver::rectf(int x, int y, int w, int h)
|
||||
{
|
||||
uchar r, g, b;
|
||||
Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
|
||||
SDL_SetRenderDrawColor((SDL_Renderer*)fl_window, r, g, b, SDL_ALPHA_OPAQUE);
|
||||
SDL_Rect rect = {x, y, w, h};
|
||||
SDL_RenderFillRect((SDL_Renderer*)fl_window, &rect);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoSDL_Graphics_Driver::line(int x, int y, int x1, int y1)
|
||||
{
|
||||
uchar r, g, b;
|
||||
Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
|
||||
SDL_SetRenderDrawColor((SDL_Renderer*)fl_window, r, g, b, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderDrawLine((SDL_Renderer*)fl_window, x, y, x1, y1);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoSDL_Graphics_Driver::point(int x, int y)
|
||||
{
|
||||
uchar r, g, b;
|
||||
Fl::get_color(Fl_Graphics_Driver::color(), r, g, b);
|
||||
SDL_SetRenderDrawColor((SDL_Renderer*)fl_window, r, g, b, SDL_ALPHA_OPAQUE);
|
||||
SDL_RenderDrawPoint((SDL_Renderer*)fl_window, x, y);
|
||||
}
|
@ -1 +0,0 @@
|
||||
|
@ -1,38 +0,0 @@
|
||||
//
|
||||
// Definition of SDL Screen interface based on Pico
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_PicoSDL_Screen_Driver.H
|
||||
\brief Definition of SDL Screen interface based on Pico.
|
||||
*/
|
||||
|
||||
#ifndef FL_PICOSDL_SCREEN_DRIVER_H
|
||||
#define FL_PICOSDL_SCREEN_DRIVER_H
|
||||
|
||||
#include "../Pico/Fl_Pico_Screen_Driver.H"
|
||||
|
||||
|
||||
class FL_EXPORT Fl_PicoSDL_Screen_Driver : public Fl_Pico_Screen_Driver
|
||||
{
|
||||
public:
|
||||
Fl_PicoSDL_Screen_Driver();
|
||||
virtual ~Fl_PicoSDL_Screen_Driver();
|
||||
virtual double wait(double time_to_wait);
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_PICOSDL_SCREEN_DRIVER_H
|
@ -1,135 +0,0 @@
|
||||
//
|
||||
// Definition of SDL Screen interface based on Pico
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_PicoSDL_Screen_Driver.H"
|
||||
|
||||
#include <FL/platform.H>
|
||||
#include "../../Fl_Window_Driver.H"
|
||||
|
||||
#define __APPLE__
|
||||
#include <SDL2/SDL.h>
|
||||
#undef __APPLE__
|
||||
|
||||
|
||||
// FIXME: does that have to be here?
|
||||
Window fl_window;
|
||||
|
||||
|
||||
Fl_Screen_Driver* Fl_Screen_Driver::newScreenDriver()
|
||||
{
|
||||
return new Fl_PicoSDL_Screen_Driver();
|
||||
}
|
||||
|
||||
|
||||
Fl_PicoSDL_Screen_Driver::Fl_PicoSDL_Screen_Driver()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Fl_PicoSDL_Screen_Driver::~Fl_PicoSDL_Screen_Driver()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
double Fl_PicoSDL_Screen_Driver::wait(double time_to_wait)
|
||||
{
|
||||
Fl::flush();
|
||||
SDL_Event e;
|
||||
Fl_Window *window = Fl::first_window();
|
||||
if (SDL_PollEvent(&e)) {
|
||||
switch (e.type) {
|
||||
case SDL_QUIT:
|
||||
exit(0);
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (e.window.event) {
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
case SDL_WINDOWEVENT_SHOWN:
|
||||
{
|
||||
if ( !window ) break;;
|
||||
Fl_Window_Driver *wd = window->driver();
|
||||
Fl_X *i = Fl_X::i(Fl::first_window());
|
||||
wd->wait_for_expose_value = 0;
|
||||
if ( i->region ) {
|
||||
fl_graphics_driver->XDestroyRegion(i->region);
|
||||
i->region = 0;
|
||||
}
|
||||
window->clear_damage(FL_DAMAGE_ALL);
|
||||
wd->flush();
|
||||
window->clear_damage();
|
||||
wd->wait_for_expose_value = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (!window) break;
|
||||
Fl::e_is_click = e.button.clicks;
|
||||
Fl::e_x = e.button.x;
|
||||
Fl::e_y = e.button.y;
|
||||
Fl::e_x_root = e.button.x + window->x();
|
||||
Fl::e_y_root = e.button.y + window->y();
|
||||
switch (e.button.button) {
|
||||
case SDL_BUTTON_LEFT: Fl::e_keysym = FL_Button+FL_LEFT_MOUSE; Fl::e_state |= FL_BUTTON1; break;
|
||||
case SDL_BUTTON_MIDDLE: Fl::e_keysym = FL_Button+FL_MIDDLE_MOUSE; Fl::e_state |= FL_BUTTON2; break;
|
||||
case SDL_BUTTON_RIGHT: Fl::e_keysym = FL_Button+FL_RIGHT_MOUSE; Fl::e_state |= FL_BUTTON3; break;
|
||||
}
|
||||
Fl::handle(FL_PUSH, window);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (!window) break;
|
||||
Fl::e_is_click = e.button.clicks;
|
||||
Fl::e_x = e.button.x;
|
||||
Fl::e_y = e.button.y;
|
||||
Fl::e_x_root = e.button.x + window->x();
|
||||
Fl::e_y_root = e.button.y + window->y();
|
||||
switch (e.button.button) {
|
||||
case SDL_BUTTON_LEFT: Fl::e_keysym = FL_Button+FL_LEFT_MOUSE; Fl::e_state &= ~FL_BUTTON1; break;
|
||||
case SDL_BUTTON_MIDDLE: Fl::e_keysym = FL_Button+FL_MIDDLE_MOUSE; Fl::e_state &= ~FL_BUTTON2; break;
|
||||
case SDL_BUTTON_RIGHT: Fl::e_keysym = FL_Button+FL_RIGHT_MOUSE; Fl::e_state &= ~FL_BUTTON3; break;
|
||||
}
|
||||
Fl::handle(FL_RELEASE, window);
|
||||
break;
|
||||
case SDL_MOUSEMOTION: // SDL_BUTTON_LMASK
|
||||
if (!window) break;
|
||||
Fl::e_is_click = e.motion.state;
|
||||
Fl::e_x = e.motion.x;
|
||||
Fl::e_y = e.motion.y;
|
||||
Fl::e_x_root = e.motion.x + window->x();
|
||||
Fl::e_y_root = e.motion.y + window->y();
|
||||
if (e.motion.state & SDL_BUTTON_LMASK) Fl::e_state |= FL_BUTTON1; else Fl::e_state &= ~FL_BUTTON1;
|
||||
if (e.motion.state & SDL_BUTTON_MMASK) Fl::e_state |= FL_BUTTON2; else Fl::e_state &= ~FL_BUTTON2;
|
||||
if (e.motion.state & SDL_BUTTON_RMASK) Fl::e_state |= FL_BUTTON3; else Fl::e_state &= ~FL_BUTTON3;
|
||||
if ((e.motion.state & (SDL_BUTTON_LMASK|SDL_BUTTON_MMASK|SDL_BUTTON_RMASK)) == 0 )
|
||||
Fl::handle(FL_MOVE, window);
|
||||
else
|
||||
Fl::handle(FL_DRAG, window);
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
break;
|
||||
case SDL_KEYDOWN: // full keyboard support is a lot more complex
|
||||
case SDL_KEYUP:
|
||||
if (e.type==SDL_KEYDOWN) Fl::e_number = FL_KEYDOWN; else Fl::e_number = FL_KEYUP;
|
||||
if (!window) break;
|
||||
if (e.key.keysym.sym==SDLK_ESCAPE) {
|
||||
Fl::e_keysym = FL_Escape;
|
||||
Fl::handle(Fl::e_number, window);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
@ -1 +0,0 @@
|
||||
|
@ -1,30 +0,0 @@
|
||||
//
|
||||
// System routines for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "../../Fl_System_Driver.H"
|
||||
//#include "Fl_PicoSDL_System_Driver.h"
|
||||
|
||||
|
||||
/*
|
||||
By linking this module, the following static method will instantiate the
|
||||
PicoSDL Graphics driver as the main display driver.
|
||||
*/
|
||||
Fl_System_Driver *Fl_System_Driver::newSystemDriver()
|
||||
{
|
||||
return new Fl_System_Driver();
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
//
|
||||
// Definition of SDL Window interface
|
||||
// for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2010-2016 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
/**
|
||||
\file Fl_PicoSDL_Window_Driver.H
|
||||
\brief Definition of SDL Window interface.
|
||||
*/
|
||||
|
||||
#ifndef FL_PICOSDL_WINDOW_DRIVER_H
|
||||
#define FL_PICOSDL_WINDOW_DRIVER_H
|
||||
|
||||
#include "../Pico/Fl_Pico_Window_Driver.H"
|
||||
|
||||
#define __APPLE__
|
||||
#include <SDL2/SDL.h>
|
||||
#undef __APPLE__
|
||||
|
||||
|
||||
class FL_EXPORT Fl_PicoSDL_Window_Driver : public Fl_Pico_Window_Driver
|
||||
{
|
||||
SDL_Window *pNativeWindow;
|
||||
SDL_Texture *pNativeTexture;
|
||||
public:
|
||||
Fl_PicoSDL_Window_Driver(Fl_Window *win);
|
||||
virtual ~Fl_PicoSDL_Window_Driver();
|
||||
|
||||
virtual void show();
|
||||
virtual Fl_X *makeWindow();
|
||||
virtual void make_current();
|
||||
virtual void draw_end();
|
||||
|
||||
// --- window management
|
||||
// virtual void flush();
|
||||
};
|
||||
|
||||
|
||||
#endif // FL_PICOSDL_WINDOW_DRIVER_H
|
@ -1,104 +0,0 @@
|
||||
//
|
||||
// Definition of SDL Window interface based on SDL
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "Fl_PicoSDL_Window_Driver.H"
|
||||
|
||||
#include <FL/platform.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
|
||||
|
||||
Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *win)
|
||||
{
|
||||
return new Fl_PicoSDL_Window_Driver(win);
|
||||
}
|
||||
|
||||
|
||||
Fl_PicoSDL_Window_Driver::Fl_PicoSDL_Window_Driver(Fl_Window *win)
|
||||
: Fl_Pico_Window_Driver(win)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Fl_PicoSDL_Window_Driver::~Fl_PicoSDL_Window_Driver()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Fl_X *Fl_PicoSDL_Window_Driver::makeWindow()
|
||||
{
|
||||
Fl_Group::current(0);
|
||||
if (parent() && !Fl_X::i(pWindow->window())) {
|
||||
pWindow->set_visible();
|
||||
return 0L;
|
||||
}
|
||||
Window parent;
|
||||
if (this->parent()) {
|
||||
parent = fl_xid(pWindow->window());
|
||||
} else {
|
||||
parent = 0;
|
||||
}
|
||||
Fl_X *x = new Fl_X;
|
||||
other_xid = 0;
|
||||
x->w = pWindow;
|
||||
x->region = 0;
|
||||
if (!pWindow->force_position()) {
|
||||
pNativeWindow = SDL_CreateWindow(pWindow->label(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w(), h(), 0);
|
||||
} else {
|
||||
pNativeWindow = SDL_CreateWindow(pWindow->label(), pWindow->x(), pWindow->y(), pWindow->w(), pWindow->h(), 0);
|
||||
}
|
||||
x->xid = SDL_CreateRenderer(pNativeWindow, -1, SDL_RENDERER_ACCELERATED);
|
||||
pNativeTexture = SDL_CreateTexture((SDL_Renderer*)x->xid, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_TARGET, w(), h());
|
||||
x->next = Fl_X::first;
|
||||
wait_for_expose_value = 0;
|
||||
pWindow->i = x;
|
||||
Fl_X::first = x;
|
||||
|
||||
pWindow->set_visible();
|
||||
pWindow->redraw();
|
||||
pWindow->flush();
|
||||
int old_event = Fl::e_number;
|
||||
pWindow->handle(Fl::e_number = FL_SHOW);
|
||||
Fl::e_number = old_event;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoSDL_Window_Driver::draw_end()
|
||||
{
|
||||
Fl_X *i = Fl_X::i(pWindow);
|
||||
SDL_SetRenderTarget((SDL_Renderer*)pWindow->i->xid, 0L);
|
||||
//SDL_RenderClear((SDL_Renderer*)i->xid);
|
||||
SDL_RenderCopy((SDL_Renderer*)i->xid, pNativeTexture, 0L, 0L);
|
||||
SDL_RenderPresent((SDL_Renderer*)i->xid);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoSDL_Window_Driver::make_current()
|
||||
{
|
||||
fl_window = pWindow->i->xid;
|
||||
SDL_SetRenderTarget((SDL_Renderer*)pWindow->i->xid, pNativeTexture);
|
||||
}
|
||||
|
||||
|
||||
void Fl_PicoSDL_Window_Driver::show() {
|
||||
if (!shown()) {
|
||||
makeWindow();
|
||||
}
|
||||
}
|
@ -56,34 +56,30 @@ include_directories(
|
||||
set (extra_tests)
|
||||
|
||||
#######################################################################
|
||||
# Add the ANDROID_OK option if the example can be compiled for Android
|
||||
# as well as for other platforms.
|
||||
|
||||
if (NOT ANDROID)
|
||||
|
||||
CREATE_EXAMPLE (adjuster adjuster.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (arc arc.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (animated animated.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (ask ask.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (bitmap bitmap.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (adjuster adjuster.cxx fltk)
|
||||
CREATE_EXAMPLE (arc arc.cxx fltk)
|
||||
CREATE_EXAMPLE (animated animated.cxx fltk)
|
||||
CREATE_EXAMPLE (ask ask.cxx fltk)
|
||||
CREATE_EXAMPLE (bitmap bitmap.cxx fltk)
|
||||
CREATE_EXAMPLE (blocks "blocks.cxx;blocks.plist;blocks.icns" "fltk;${AUDIOLIBS}")
|
||||
CREATE_EXAMPLE (boxtype boxtype.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (browser browser.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (button button.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (buttons buttons.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (checkers "checkers.cxx;checkers_pieces.fl;checkers.icns" "fltk_images;fltk" ANDROID_OK)
|
||||
CREATE_EXAMPLE (boxtype boxtype.cxx fltk)
|
||||
CREATE_EXAMPLE (browser browser.cxx fltk)
|
||||
CREATE_EXAMPLE (button button.cxx fltk)
|
||||
CREATE_EXAMPLE (buttons buttons.cxx fltk)
|
||||
CREATE_EXAMPLE (checkers "checkers.cxx;checkers_pieces.fl;checkers.icns" "fltk_images;fltk")
|
||||
CREATE_EXAMPLE (clipboard clipboard.cxx "fltk_images;fltk")
|
||||
CREATE_EXAMPLE (clock clock.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (clock clock.cxx fltk)
|
||||
CREATE_EXAMPLE (colbrowser colbrowser.cxx fltk)
|
||||
CREATE_EXAMPLE (color_chooser color_chooser.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (color_chooser color_chooser.cxx fltk)
|
||||
CREATE_EXAMPLE (coordinates coordinates.cxx fltk)
|
||||
CREATE_EXAMPLE (cursor cursor.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (curve curve.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (cursor cursor.cxx fltk)
|
||||
CREATE_EXAMPLE (curve curve.cxx fltk)
|
||||
CREATE_EXAMPLE (demo demo.cxx fltk)
|
||||
CREATE_EXAMPLE (device device.cxx "fltk_images;fltk")
|
||||
CREATE_EXAMPLE (doublebuffer doublebuffer.cxx fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (editor "editor.cxx;editor.plist" fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (fast_slow fast_slow.fl fltk ANDROID_OK)
|
||||
CREATE_EXAMPLE (doublebuffer doublebuffer.cxx fltk)
|
||||
CREATE_EXAMPLE (editor "editor.cxx;editor.plist" fltk)
|
||||
CREATE_EXAMPLE (fast_slow fast_slow.fl fltk)
|
||||
CREATE_EXAMPLE (file_chooser file_chooser.cxx "fltk_images;fltk")
|
||||
CREATE_EXAMPLE (fltk-versions fltk-versions.cxx fltk)
|
||||
CREATE_EXAMPLE (fonts fonts.cxx fltk)
|
||||
@ -238,8 +234,6 @@ if (OPTION_BUILD_SHARED_LIBS)
|
||||
|
||||
endif (OPTION_BUILD_SHARED_LIBS)
|
||||
|
||||
endif (NOT ANDROID)
|
||||
|
||||
#####################################################
|
||||
# We need some support files for the demo programs
|
||||
#####################################################
|
||||
|
Loading…
Reference in New Issue
Block a user