Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • PantyNabber/fc-pregmod
  • pregmodfan/fc-pregmod
  • Alice.Grant/fc-pregmod
  • powerfful/fc-pregmod
  • elstumpo/fc-pregmod
  • Y/fc-pregmod
  • floer/fc-pregmod
  • oidocrop/fc-pregmod
  • hawk5005/fc-pregmod
  • nn/fc-pregmod
  • latios298/fc-pregmod
  • brpregmodfan/fc-pregmod
  • SomeoneTookMyUserName/fc-pregmod
  • 000-250-006/fc-pregmod
  • rewrica/fc-pregmod
  • Stuffedgame/fc-pregmod
  • wisepants314/fc-pregmod
  • fcanon/fc-pregmod
  • randomanon1/pregmod-mod-cyberfurry
  • teddy.buckland/fc-pregmod
  • farsinian_591b7a2d8b49d/fc-pregmod
  • FCShotadev/fc-pregmod
  • uselessartifact/fc-pregmod
  • irina_90/fc-pregmod
  • thaumx/fc-pregmod
  • MouseOfLight/fc-pregmod
  • empresssela/fc-pregmod
  • MasterAaran/fc-pregmod
  • ishy/fc-pregmod
  • psychofox/fc-pregmod
  • shadomancer/fc-pregmod
  • tycrakgg/fc-pregmod
  • azktaawc/fc-pregmod
  • andonno07/fc-pregmod
  • Onithyr/fc-pregmod
  • redneck987.jl/fc-pregmod
  • Farseeker/fc-pregmod
  • milliarc/fc-pregmod
  • BeefimusMaximus/fc-pregmod
  • magicknight79/fc-pregmod
  • hexall90/fc-pregmod
  • cantworkforever/fc-pregmod
  • jc052005/fc-pregmod
  • klorpa/fc-pregmod
  • doku/fc-pregmod
  • samhradh/fc-pregmod
  • scientist/fc-pregmod
  • albania420/fc-pregmod
  • Editoranon/fc-pregmod
  • Anony/fc-pregmod
  • deimios666/fc-pregmod
  • IvoHoe/fc-pregmod
  • bitty/fc-pregmod
  • RealAnon1800/fc-pregmod
  • brankirk/fc-pregmod
  • Amygdalan/fc-pregmod
  • DankWolf/fc-pregmod
  • Supot1951/fc-pregmod
  • bcy603/fc-pregmod
  • pwfxjpuv/fc-pregmod
  • ThreadAnon/fc-pregmod
  • Anon1800/fc-pregmod
  • Echoart/fc-pregmod
  • Dingotush/fc-pregmod
  • anonman/fc-pregmod
  • Arkerthan/fc-pregmod
  • svornost/fc-pregmod
  • wierdwierdos/fc-pregmod
  • wetwareAnon/fc-pregmod
  • QuartzHat/fc-pregmod
  • IchthysdeKilt/fc-pregmod
  • AnonAnonFC/fc-pregmod
  • Alexsis/fc-pregmod
  • LoyalTreeWP/fc-pregmod
  • aerialace/fc-pregmod
  • NurseryAnon/fc-pregmod
  • drakeashordcataclysm/fc-pregmod
  • AshVaris/fc-pregmod
  • purely0nothing/fc-pregmod
  • alex2011/fc-pregmod
  • Lindontree/fc-pregmod
  • FCaa/fc-pregmod
  • TR-8R/fc-pregmod
  • Jones/fc-pregmod
  • brr99/fc-pregmod
  • WriteAnon101/fc-pregmod
  • Drosil/fc-pregmod
  • Bob1221/fc-pregmod
  • vas/fc-pregmod
  • gitgud.user.937/fc-pregmod
  • D-K/fc-pregmod
  • AnonDev/fc-pregmod
  • madman23456/fc-pregmod
  • InarusLynx/fc-pregmod
  • Sonofrevvan/fc-pregmod
  • Randoisrando/fc-pregmod
  • cheez94/fc-pregmod
  • dldldl/fc-pregmod
  • alice321/fc-pregmod
  • Alexei91/fc-pregmod
  • darkcy/fc-pregmod
  • MapleMAD/fc-pregmod
  • pillarofsalt/fc-pregmod
  • vultureangels/fc-pregmod
  • kernel/fc-pregmod
  • nooneman/fc-pregmod
  • deepmurk/fc-pregmod
  • uglybead/fc-pregmod
  • lemongrab/fc-pregmod
  • temperence-chan/fc-pregmod
  • hcommenter/fc-pregmod
  • SpedeMemerson/fc-pregmod
  • qwijqwsf/fc-pregmod
  • BuDClow/fc-pregmod
  • HiveBro/fc-pregmod
  • shoku/fc-pregmod
  • ezsh/fc-pregmod
  • Blank/fc-pregmod
  • randoralcissian/fc-pregmod
  • benito92/fc-pregmod
  • balakart/fc-pregmod
  • wedonotsaw/fc-pregmod
  • Cayleth/fc-pregmod
  • Khip/fc-pregmod
  • Zfair/fc-pregmod
  • promethium/fc-pregmod
  • scyne/fc-pregmod
  • ZZC/fc-pregmod
  • SilverJanine/fc-pregmod
  • joxosix654email-9.co/fc-pregmod
  • Littlefootlittleguy/fc-pregmod
  • FelipeBA/fc-pregmod
  • bigtiddygothbf/fc-pregmod
  • Qotsafan/fc-pregmod
  • Zachpocalypse/fc-pregmod
  • milkanon66/fc-pregmod
  • GreGGoZZ/fc-pregmod
  • drsnarf86/fc-pregmod
  • valen102938/fc-pregmod
  • pregspammer/fc-pregmod
  • ponderin94/fc-pregmod
  • nook/fc-pregmod
  • carnifex34/fc-pregmod-mod-carni
  • SyntheticHigh/fc-pregmod
  • bob112211/fc-pregmod
  • amomynous0/fc-pregmod
  • oxone/fc-pregmod
  • MaxEuwe/fc-pregmod
  • nekoanon/fc-pregmod
  • preglocke/fc-pregmod
  • valen10293847/fc-pregmod
  • 2hu4u/fc-pregmod
  • mayibrad/fc-pregmod
  • Screm/fc-pregmod
  • Ansopedi/fc-pregmod
  • mrchaosbones/fc-pregmod
  • putrid/fc-pregmod
  • Kinnerman/fc-pregmod
  • gungrave1155/fc-pregmod
  • prndev/fc-pregmod
  • weresmilodon/fc-pregmod
  • auxxigobin/fc-pregmod
  • alice-chan/fc-pregmod
  • wigglie/fc-pregmod
  • jrliltfgb/fc-pregmod
  • Lord.alek.shade/fc-pregmod
  • truetailthesquire/fc-pregmod
  • lowercasedonkey/fc-pregmod
  • alice-chan9/fc-pregmod
  • eroglyphics/fc-pregmod
  • taliyent/fc-pregmod
  • zenzombie90/fc-pregmod
  • kjarik/fc-pregmod
  • wriggler/fc-pregmod
  • midnightblue/fc-pregmod
  • faraen/fc-pregmod
  • sigurd.cole/fc-pregmod
  • FCbuganon/fc-pregmod
  • kidkinster/fc-pregmod
  • Kar_Dragon/fc-pregmod
  • Zhafier/fc-pregmod
  • crcaretti/fc-pregmod
  • anond/fc-pregmod
  • tempmania/fc-pregmod
  • Dhanze/fc-pregmod
  • EstaUnCachucha/fc-pregmod
  • oniAnon/fc-pregmod
  • plebian/fc-pregmod
  • maxd569/fc-pregmod
  • Levarn/fc-pregmod
  • pumpkinspice/fc-pregmod
  • GammaXai/fc-pregmod
  • DanBackslide/fc-pregmod
  • i107760/fc-pregmod
  • Absimiliard/fc-pregmod
  • AmbrosiaCheesecake/fc-pregmod
  • fuguer/fc-pregmod
  • Azurel/fc-pregmod
  • Fake_Dev/fc-pregmod
  • ddongsanda/fc-pregmod
  • Combine456/fc-pregmod
  • UnwrappedGodiva/fc-pregmod
  • toyRuberDucky/fc-pregmod
  • zmobie/fc-pregmod
  • chuongk/fc-pregmod
  • BigWalnuts/fc-pregmod
  • Birdstrike/fc-pregmod
  • r3d/fc-pregmod
  • mawspa/fc-pregmod
  • sushila/fc-pregmod
  • DeathShip/fc-pregmod
  • eggrollsandwich/fc-pregmod
  • krayken/fc-pregmod
  • Reman/fc-pregmod
  • dwiafgts/fc-pregmod
  • jort93/fc-pregmod
  • teruterubouzu/fc-pregmod
  • flut/fc-pregmod
  • john-normal/fc-pregmod
  • Jonathan2405/fc-pregmod
  • Tyrgalon/fc-pregmod
  • NovX/fc-pregmod
  • Star1/fc-pregmod
  • Transhumanist01/fc-pregmod
  • m1017242/fc-pregmod
  • Rizal98798/fc-pregmod
  • jamezu369/fc-pregmod
  • thisisawittyname/fc-pregmod
  • KnightBoulegard/fc-pregmod
  • jblack/fc-pregmod
  • Souldrainr/fc-pregmod
  • torbjornhub/fc-pregmod
  • turnop/fc-pregmod
  • breadedpigeon/fc-pregmod
  • fire.maker/fc-pregmod
  • Inahaze/fc-pregmod
  • Waerjak/fc-pregmod
  • Trashman1138/fc-pregmod
  • supanintendo/fc-pregmod
  • _no0neman/fc-pregmod
  • Weslo/fc-pregmod
  • qw89/fc-pregmod
  • EvilDruid/fc-pregmod
  • dt25/fc-pregmod
  • Raou/fc-pregmod
  • DDouFu/fc-pregmod
  • Mauno/fc-pregmod
  • PandemoniumPenguin/fc-pregmod
  • AngelPuppet/fc-pregmod
  • DasUser79/fc-pregmod
  • Keaeag3s/fc-pregmod
  • HazeHazeHaze/fc-pregmod
  • hpotato/fc-pregmod
  • owouchthatbloodyhurt/fc-pregmod
  • v7Silent/fc-pregmod
  • nickylass/fc-pregmod
  • ThePrimer/fc-pregmod
  • PineCone/fc-pregmod
  • bruhmomentum17/fc-pregmod
  • CheatDude/fc-pregmod
  • synnove/fc-pregmod
  • en_bees/fc-pregmod
  • seronis/fc-pregmod
  • Nepidinepnep/fc-pregmod
  • Titanninja/fc-pregmod
  • Elohiem/fc-pregmod
  • cocoajazz/fc-pregmod
  • tfwncagf/fc-pregmod
  • ChunkyMonke/fc-pregmod
  • Dracoman671/fc-pregmod
  • jgl/fc-pregmod
  • Inev/fc-pregmod
  • jbige/fc-pregmod
  • MonsterMate/fc-pregmod
  • Konstantin6961/fc-pregmod
  • darth_ashi/fc-pregmod
  • shinx/fc-pregmod
  • Anu/fc-pregmod
  • Greytide/fc-pregmod
  • Bonafidemetal/fc-pregmod
  • Peje/fc-pregmod
  • Hexfy98/fc-pregmod
  • TooSlow/fc-pregmod
  • SoGu/fc-pregmod
  • CloudyCoffee/fc-pregmod
  • Welptard/fc-pregmod
  • Ploc/fc-pregmod-ploc
  • rain-/fc-pregmod
  • Pecanus/fc-pregmod
  • Jhortrax/fc-pregmod
  • valleytwo/fc-pregmod
  • QCmd/fc-pregmod
  • kung-wada/fc-pregmod
  • LolGaye/fc-pregmod
  • Exspiravit1/fc-pregmod
  • jadeddog/fc-pregmod
  • buster-scruggs/fs-antebellum-revivalism
  • policia123/fc-pregmod
  • evrgentesee/fc-pregmod
  • rko127/fc-pregmod
  • ExcalGrip12/fc-pregmod
  • BlackAion/fc-pregmod
  • Boss2020/fc-pregmod
  • Lawled/fc-pregmod
  • shiro/fc-pregmod
  • Skavenkeri/fc-pregmod
  • PooPooDooDooHead/fc-pregmod
  • Dugee/fc-pregmod
  • Portal124/fc-pregmod-vore
  • Fekenol/fc-pregmod
  • elGuapo/fc-pregmod
  • KelioSteel/fc-pregmod
  • sldlddk/fc-pregmod
  • lumepanter/fc-pregmod
  • ryuhana/fc-pregmod
  • Nene1009yb/fc-pregmod
  • DontAskDontTell/fc-pregmod-extra-events
  • Dulgi/fc-pregmod
  • Jate/fc-pregmod
  • percy365/fc-pregmod
  • franklygeorge/fc-pregmod
  • Dragneel117/fc-pregmod
  • vl96/fc-pregmod
  • Gorlom/fc-economicmod
  • NotAlive/fc-pregmod
  • Heretek/fc-pregmod
  • joeshmo828282/fc-pregmod
  • deswes/fc-pregmod
  • Nanana21/fc-pregmod
  • Gbr6/fc-pregmod
  • RandomNecro/fc-pregmod
  • Trinidad/fc-pregmod
  • anonymousey/fc-pregmod
  • macaronideath/fc-pregmod
  • fcbleh/fc-pregmod
  • jk3000/fc-pregmod
  • Akane/fc-pregmod
  • TheBoi/fc-pregmod
  • Sheenariel/fc-pregmod
  • Metapod/multi-custom
  • Banyanael/fc-pregmod
  • frogge/fc-pregmod
  • idkkk12385/fc-pregmod
  • Mirarara/fc-pregmod
  • DeaDa/fc-pregmod-thedeal
  • CobraCommander/fc-pregmod
  • bicobus/fc-pregmod
  • CardcaptorRLH85/fc-pregmod
  • temp-ui-start/fc-pregmod
  • PresidentConvert/fc-pregmod
  • delizious/fc-pregmod
  • Ducati/fc-pregmod
  • DerangedLoner/fc-pregmod-development-fork
  • ProjectVictory/fc-pregmod
  • forecastle/fc-pregmod
  • Apathy/fc-pregmod
  • indf/fc-pregmod-dev
  • GavAndAlt/fc-pregmod
  • hagamablabla/fc-pregmod
  • Alaco/fc-pregmod
  • DCoded/fc-pregmod
  • LittlePlague/fc-pregmod
  • MissOnahole/fc-pregmod
  • ishy2317/fc-pregmod
  • nielkazama/fc-pregmod
  • Phobos/fc-pregmod
  • kraster/fc-pregmod
  • JasWS/fc-pregmod
  • FelixJS/fc-pregmod
  • NCherfaoui/fc-pregmod
  • MidnightMoose/fc-pregmod
  • jjjjjj/fc-pregmod
  • Cl0ver/fc-pregmod
  • Pythoniqus/fc-pregmod
  • JohnMolotov/fc-pregmod
  • anonymouspregmodder/fc-pregmod-anonymouspregmodder
  • Fanatey/fc-pregmod
  • Mizako/fc-pregmod
  • Nithhogg/fc-pregmod
  • Bluecoffee/fc-pregmod
380 results
Show changes
Showing
with 831 additions and 1071 deletions
# How to Build
## BUILD REQUIREMENTS
The below requirements must be met to build this project.
- CMake version 2.8.12.1 or newer
- Ensure the CMake binary folder is added to your path (e.g. for Windows `C:\Program Files\CMake\bin`)
- Chromium Embedded Framework (CEF) 126.1 or newer
- Running CMake will automatically download this so there is no need to configure it yourself
### Windows
Visual Studio 2019 (the community edition will work fine) or newer with the "Desktop development with C++" workload installed.
### Linux
Ensure you have a C++ compiler installed. On Debian/Ubuntu this can be installed with:
```bash
sudo apt install build-essential
```
## BUILD STEPS
### Windows
Assuming that Visual Studio 2019/2022 is being used, run the following command:
```bash
# For Visual Studio 2019
# Alternatively run `cmake_vs2019.bat`
cmake -G "Visual Studio 16" .
# For Visual Studio 2022
# Alternatively run `cmake_vs2022.bat`
cmake -G "Visual Studio 17" .
```
Open the generated `fchost.sln` file in Visual Studio. Then build the project by either:
- Selecting **Build > Build Solution** on the menu bar
- Pressing **Ctrl + Shift + B**
### Linux
Run the following commands:
```bash
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release .
make -j4
```
### Output
The resulting binary and supporting files will be in `FCHost/fchost/Debug` or `FCHost/fchost/Release` depending on the configuration selected in Visual Studio via the drop down found under the Build and Debug tool bar headers.
You should be able to zip up the contents of the Release folder and distribute them to another machine or user if desired. Due to space and privacy concerns it is suggested that you remove `*.html` and `fchost.ilk` files (if present) prior to distribution.
<!-- cSpell:ignore fchost, Shokusku's -->
# FCHost
FCHost is an alternative HTML renderer for playing Pregmod based on Chromium. It has multiple advantages compared to normal browsers:
- No browser cache limits, allowing arbitrarily large save files.
- Saves are stored in an easily accessible way on disk, allowing for easy manual editing.
- No lost saves due to accidentally cleared cookies.
- Can be noticeable faster.
A Windows build is available for [download](https://mega.nz/file/kY5GmLRa#jwwgshNuKz0yAQDDeSs-jbPOOGX4Ap1ha_EKlWp-9-M).
If you are developing FC using the advanced tooling then you can run `FCHost.bat` (Windows) or `FCHost.sh` (Mac/Linux) to download and setup FCHost automatically.
## Initial setup
### HTML files
Place `FC_pregmod.html` next to the FCHost executable. This is usually `fchost.exe`, but it may be a file named `fchost` on Mac/Linux.
### Art resources
Art resources work the same way as with other browser. For embedded art no actions are necessary, while for the others
the art resources have to be placed in a `resources` directory next to the HTML file.
Elohiem's interactive WebGL:
- fchost.exe
- resources/
- webgl
Shokusku's rendered image pack
- fchost.exe
- resources/
- dynamic
- renders
If making changes while the game is open make sure to refresh or restart FCHost before trying the art styles.
## Keybinds
| Action | Key Combination |
| --------- | ---------------- |
| Zoom In | Ctrl + Plus |
| Zoom Out | Ctrl + Minus |
| Dev Tools | Ctrl + Shift + J |
## Save file locations
| Platform | Location |
| -------- | -------------------------------------------------------------- |
| Windows | `%User%\Documents\FreeCities_Pregmod\FCHostPersistentStorage\` |
| Linux | `~/.local/share/FreeCities_Pregmod/FCHostPersistentStorage/` |
## Building FCHost
If you want to build FCHost yourself please refer to [FCHost/HowToBuild.md](FCHost/HowToBuild.md).
# Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
# reserved. Use of this source code is governed by a BSD-style license that
# can be found in the LICENSE file.
# Download the CEF binary distribution for |platform| and |version| to
# |download_dir|. The |CEF_ROOT| variable will be set in global scope pointing
# to the extracted location.
# Visit https://cef-builds.spotifycdn.com/index.html for the list of
# supported platforms and versions.
function(DownloadCEF platform version download_dir)
# Specify the binary distribution type and download directory.
set(CEF_DISTRIBUTION "cef_binary_${version}_${platform}")
set(CEF_DOWNLOAD_DIR "${download_dir}")
# The location where we expect the extracted binary distribution.
set(CEF_ROOT "${CEF_DOWNLOAD_DIR}/${CEF_DISTRIBUTION}" CACHE INTERNAL "CEF_ROOT")
# Download and/or extract the binary distribution if necessary.
if(NOT IS_DIRECTORY "${CEF_ROOT}")
set(CEF_DOWNLOAD_FILENAME "${CEF_DISTRIBUTION}.tar.bz2")
set(CEF_DOWNLOAD_PATH "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}")
if(NOT EXISTS "${CEF_DOWNLOAD_PATH}")
set(CEF_DOWNLOAD_URL "https://cef-builds.spotifycdn.com/${CEF_DOWNLOAD_FILENAME}")
string(REPLACE "+" "%2B" CEF_DOWNLOAD_URL_ESCAPED ${CEF_DOWNLOAD_URL})
# Download the SHA1 hash for the binary distribution.
message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}.sha1 from ${CEF_DOWNLOAD_URL_ESCAPED}...")
file(DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}.sha1" "${CEF_DOWNLOAD_PATH}.sha1")
file(READ "${CEF_DOWNLOAD_PATH}.sha1" CEF_SHA1)
# Download the binary distribution and verify the hash.
message(STATUS "Downloading ${CEF_DOWNLOAD_PATH}...")
file(
DOWNLOAD "${CEF_DOWNLOAD_URL_ESCAPED}" "${CEF_DOWNLOAD_PATH}"
EXPECTED_HASH SHA1=${CEF_SHA1}
SHOW_PROGRESS
)
endif()
# Extract the binary distribution.
message(STATUS "Extracting ${CEF_DOWNLOAD_PATH}...")
execute_process(
COMMAND ${CMAKE_COMMAND} -E tar xzf "${CEF_DOWNLOAD_DIR}/${CEF_DOWNLOAD_FILENAME}"
WORKING_DIRECTORY ${CEF_DOWNLOAD_DIR}
)
endif()
endfunction()
\ No newline at end of file
# Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
# reserved. Use of this source code is governed by a BSD-style license that
# can be found in the LICENSE file.
#
# This file is the CEF CMake configuration entry point and should be loaded
# using `find_package(CEF REQUIRED)`. See the top-level CMakeLists.txt file
# included with the CEF binary distribution for usage information.
#
# Find the CEF binary distribution root directory.
set(_CEF_ROOT "")
if(CEF_ROOT AND IS_DIRECTORY "${CEF_ROOT}")
set(_CEF_ROOT "${CEF_ROOT}")
set(_CEF_ROOT_EXPLICIT 1)
else()
set(_ENV_CEF_ROOT "")
if(DEFINED ENV{CEF_ROOT})
file(TO_CMAKE_PATH "$ENV{CEF_ROOT}" _ENV_CEF_ROOT)
endif()
if(_ENV_CEF_ROOT AND IS_DIRECTORY "${_ENV_CEF_ROOT}")
set(_CEF_ROOT "${_ENV_CEF_ROOT}")
set(_CEF_ROOT_EXPLICIT 1)
endif()
unset(_ENV_CEF_ROOT)
endif()
if(NOT DEFINED _CEF_ROOT_EXPLICIT)
message(FATAL_ERROR "Must specify a CEF_ROOT value via CMake or environment variable.")
endif()
if(NOT IS_DIRECTORY "${_CEF_ROOT}/cmake")
message(FATAL_ERROR "No CMake bootstrap found for CEF binary distribution at: ${CEF_ROOT}.")
endif()
# Execute additional cmake files from the CEF binary distribution.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${_CEF_ROOT}/cmake")
include("cef_variables")
include("cef_macros")
# Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
# reserved. Use of this source code is governed by a BSD-style license that
# can be found in the LICENSE file.
# Must be loaded via FindCEF.cmake.
if(NOT DEFINED _CEF_ROOT_EXPLICIT)
message(FATAL_ERROR "Use find_package(CEF) to load this file.")
endif()
#
# Shared macros.
#
# Print the current CEF configuration.
macro(PRINT_CEF_CONFIG)
message(STATUS "*** CEF CONFIGURATION SETTINGS ***")
message(STATUS "Generator: ${CMAKE_GENERATOR}")
message(STATUS "Platform: ${CMAKE_SYSTEM_NAME}")
message(STATUS "Project architecture: ${PROJECT_ARCH}")
if(GEN_NINJA OR GEN_MAKEFILES)
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
endif()
message(STATUS "Binary distribution root: ${_CEF_ROOT}")
if(OS_MACOSX)
message(STATUS "Base SDK: ${CMAKE_OSX_SYSROOT}")
message(STATUS "Target SDK: ${CEF_TARGET_SDK}")
endif()
if(OS_WINDOWS)
message(STATUS "Visual Studio ATL support: ${USE_ATL}")
endif()
message(STATUS "CEF sandbox: ${USE_SANDBOX}")
set(_libraries ${CEF_STANDARD_LIBS})
if(OS_WINDOWS AND USE_SANDBOX)
list(APPEND _libraries ${CEF_SANDBOX_STANDARD_LIBS})
endif()
message(STATUS "Standard libraries: ${_libraries}")
message(STATUS "Compile defines: ${CEF_COMPILER_DEFINES}")
message(STATUS "Compile defines (Debug): ${CEF_COMPILER_DEFINES_DEBUG}")
message(STATUS "Compile defines (Release): ${CEF_COMPILER_DEFINES_RELEASE}")
message(STATUS "C compile flags: ${CEF_COMPILER_FLAGS} ${CEF_C_COMPILER_FLAGS}")
message(STATUS "C compile flags (Debug): ${CEF_COMPILER_FLAGS_DEBUG} ${CEF_C_COMPILER_FLAGS_DEBUG}")
message(STATUS "C compile flags (Release): ${CEF_COMPILER_FLAGS_RELEASE} ${CEF_C_COMPILER_FLAGS_RELEASE}")
message(STATUS "C++ compile flags: ${CEF_COMPILER_FLAGS} ${CEF_CXX_COMPILER_FLAGS}")
message(STATUS "C++ compile flags (Debug): ${CEF_COMPILER_FLAGS_DEBUG} ${CEF_CXX_COMPILER_FLAGS_DEBUG}")
message(STATUS "C++ compile flags (Release): ${CEF_COMPILER_FLAGS_RELEASE} ${CEF_CXX_COMPILER_FLAGS_RELEASE}")
message(STATUS "Exe link flags: ${CEF_LINKER_FLAGS} ${CEF_EXE_LINKER_FLAGS}")
message(STATUS "Exe link flags (Debug): ${CEF_LINKER_FLAGS_DEBUG} ${CEF_EXE_LINKER_FLAGS_DEBUG}")
message(STATUS "Exe link flags (Release): ${CEF_LINKER_FLAGS_RELEASE} ${CEF_EXE_LINKER_FLAGS_RELEASE}")
message(STATUS "Shared link flags: ${CEF_LINKER_FLAGS} ${CEF_SHARED_LINKER_FLAGS}")
message(STATUS "Shared link flags (Debug): ${CEF_LINKER_FLAGS_DEBUG} ${CEF_SHARED_LINKER_FLAGS_DEBUG}")
message(STATUS "Shared link flags (Release): ${CEF_LINKER_FLAGS_RELEASE} ${CEF_SHARED_LINKER_FLAGS_RELEASE}")
if(OS_LINUX OR OS_WINDOWS)
message(STATUS "CEF Binary files: ${CEF_BINARY_FILES}")
message(STATUS "CEF Resource files: ${CEF_RESOURCE_FILES}")
endif()
endmacro()
# Append platform specific sources to a list of sources.
macro(APPEND_PLATFORM_SOURCES name_of_list)
if(OS_LINUX AND ${name_of_list}_LINUX)
list(APPEND ${name_of_list} ${${name_of_list}_LINUX})
endif()
if(OS_POSIX AND ${name_of_list}_POSIX)
list(APPEND ${name_of_list} ${${name_of_list}_POSIX})
endif()
if(OS_WINDOWS AND ${name_of_list}_WINDOWS)
list(APPEND ${name_of_list} ${${name_of_list}_WINDOWS})
endif()
if(OS_MACOSX AND ${name_of_list}_MACOSX)
list(APPEND ${name_of_list} ${${name_of_list}_MACOSX})
endif()
endmacro()
# Determine the target output directory based on platform and generator.
macro(SET_CEF_TARGET_OUT_DIR)
if(GEN_NINJA OR GEN_MAKEFILES)
# By default Ninja and Make builds don't create a subdirectory named after
# the configuration.
set(CEF_TARGET_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
# Output binaries (executables, libraries) to the correct directory.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CEF_TARGET_OUT_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CEF_TARGET_OUT_DIR})
else()
set(CEF_TARGET_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>")
endif()
endmacro()
# Copy a list of files from one directory to another. Relative files paths are maintained.
# The path component of the source |file_list| will be removed.
macro(COPY_FILES target file_list source_dir target_dir)
foreach(FILENAME ${file_list})
set(source_file ${source_dir}/${FILENAME})
get_filename_component(target_name ${FILENAME} NAME)
set(target_file ${target_dir}/${target_name})
string(FIND ${source_file} "$<CONFIGURATION>" _pos)
if(NOT ${_pos} EQUAL -1)
# Must test with an actual configuration directory.
string(REPLACE "$<CONFIGURATION>" "Release" existing_source_file ${source_file})
if(NOT EXISTS ${existing_source_file})
string(REPLACE "$<CONFIGURATION>" "Debug" existing_source_file ${source_file})
endif()
else()
set(existing_source_file ${source_file})
endif()
if(IS_DIRECTORY ${existing_source_file})
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory "${source_file}" "${target_file}"
VERBATIM
)
else()
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${source_file}" "${target_file}"
VERBATIM
)
endif()
endforeach()
endmacro()
#
# Linux macros.
#
if(OS_LINUX)
# Use pkg-config to find Linux libraries and update compiler/linker variables.
macro(FIND_LINUX_LIBRARIES libraries)
# Read pkg-config info into variables.
execute_process(COMMAND pkg-config --cflags ${libraries} OUTPUT_VARIABLE FLL_CFLAGS)
execute_process(COMMAND pkg-config --libs-only-L --libs-only-other ${libraries} OUTPUT_VARIABLE FLL_LDFLAGS)
execute_process(COMMAND pkg-config --libs-only-l ${libraries} OUTPUT_VARIABLE FLL_LIBS)
# Strip leading and trailing whitepspace.
STRING(STRIP "${FLL_CFLAGS}" FLL_CFLAGS)
STRING(STRIP "${FLL_LDFLAGS}" FLL_LDFLAGS)
STRING(STRIP "${FLL_LIBS}" FLL_LIBS)
# Convert to a list.
separate_arguments(FLL_CFLAGS)
separate_arguments(FLL_LDFLAGS)
separate_arguments(FLL_LIBS)
# Update build variables.
list(APPEND CEF_C_COMPILER_FLAGS ${FLL_CFLAGS})
list(APPEND CEF_CXX_COMPILER_FLAGS ${FLL_CFLAGS})
list(APPEND CEF_EXE_LINKER_FLAGS ${FLL_LDFLAGS})
list(APPEND CEF_SHARED_LINKER_FLAGS ${FLL_LDFLAGS})
list(APPEND CEF_STANDARD_LIBS ${FLL_LIBS})
endmacro()
# Set SUID permissions on the specified executable.
macro(SET_LINUX_SUID_PERMISSIONS target executable)
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo ""
COMMAND ${CMAKE_COMMAND} -E echo "*** Run the following command manually to set SUID permissions ***"
COMMAND ${CMAKE_COMMAND} -E echo "EXE=\"${executable}\" && sudo -- chown root:root $EXE && sudo -- chmod 4755 $EXE"
COMMAND ${CMAKE_COMMAND} -E echo ""
VERBATIM
)
endmacro()
endif(OS_LINUX)
#
# Mac OS X macros.
#
if(OS_MACOSX)
# Manually process and copy over resource files.
macro(COPY_MACOSX_RESOURCES resource_list prefix_list target source_dir app_path)
foreach(FILENAME ${resource_list})
# Remove one or more prefixes from the source paths.
set(TARGET_FILENAME "${FILENAME}")
foreach(PREFIX ${prefix_list})
string(REGEX REPLACE "^.*${PREFIX}" "" TARGET_FILENAME ${TARGET_FILENAME})
endforeach()
# Determine the absolute source and target paths.
set(TARGET_PATH "${app_path}/Contents/Resources/${TARGET_FILENAME}")
if(IS_ABSOLUTE ${FILENAME})
set(SOURCE_PATH ${FILENAME})
else()
set(SOURCE_PATH "${source_dir}/${FILENAME}")
endif()
if(${FILENAME} MATCHES ".xib$")
# Change the target file extension.
string(REGEX REPLACE ".xib$" ".nib" TARGET_PATH ${TARGET_PATH})
get_filename_component(TARGET_DIRECTORY ${TARGET_PATH} PATH)
add_custom_command(
TARGET ${target}
POST_BUILD
# Create the target directory.
COMMAND ${CMAKE_COMMAND} -E make_directory "${TARGET_DIRECTORY}"
# Compile the XIB file to a NIB.
COMMAND /usr/bin/ibtool --output-format binary1 --compile "${TARGET_PATH}" "${SOURCE_PATH}"
VERBATIM
)
elseif(NOT ${TARGET_FILENAME} STREQUAL "Info.plist")
# Copy the file as-is.
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${SOURCE_PATH}" "${TARGET_PATH}"
VERBATIM
)
endif()
endforeach()
endmacro()
endif(OS_MACOSX)
#
# Windows macros.
#
if(OS_WINDOWS)
# Add custom manifest files to an executable target.
macro(ADD_WINDOWS_MANIFEST manifest_path target extension)
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND "mt.exe" -nologo
-manifest \"${manifest_path}/${target}.${extension}.manifest\" \"${manifest_path}/compatibility.manifest\"
-outputresource:"${CEF_TARGET_OUT_DIR}/${target}.${extension}"\;\#1
COMMENT "Adding manifest..."
)
endmacro()
endif(OS_WINDOWS)
#
# Target configuration macros.
#
# Add a logical target that can be used to link the specified libraries into an
# executable target.
macro(ADD_LOGICAL_TARGET target debug_lib release_lib)
add_library(${target} ${CEF_LIBTYPE} IMPORTED)
set_target_properties(${target} PROPERTIES
IMPORTED_LOCATION "${release_lib}"
IMPORTED_LOCATION_DEBUG "${debug_lib}"
IMPORTED_LOCATION_RELEASE "${release_lib}"
)
endmacro()
# Set common target properties. Use SET_LIBRARY_TARGET_PROPERTIES() or
# SET_EXECUTABLE_TARGET_PROPERTIES() instead of calling this macro directly.
macro(SET_COMMON_TARGET_PROPERTIES target)
# Compile flags.
target_compile_options(${target} PRIVATE ${CEF_COMPILER_FLAGS} ${CEF_CXX_COMPILER_FLAGS})
target_compile_options(${target} PRIVATE $<$<CONFIG:Debug>:${CEF_COMPILER_FLAGS_DEBUG} ${CEF_CXX_COMPILER_FLAGS_DEBUG}>)
target_compile_options(${target} PRIVATE $<$<CONFIG:Release>:${CEF_COMPILER_FLAGS_RELEASE} ${CEF_CXX_COMPILER_FLAGS_RELEASE}>)
# Compile definitions.
target_compile_definitions(${target} PRIVATE ${CEF_COMPILER_DEFINES})
target_compile_definitions(${target} PRIVATE $<$<CONFIG:Debug>:${CEF_COMPILER_DEFINES_DEBUG}>)
target_compile_definitions(${target} PRIVATE $<$<CONFIG:Release>:${CEF_COMPILER_DEFINES_RELEASE}>)
# Include directories.
target_include_directories(${target} PRIVATE ${CEF_INCLUDE_PATH})
# Linker flags.
if(CEF_LINKER_FLAGS)
string(REPLACE ";" " " _flags_str "${CEF_LINKER_FLAGS}")
set_property(TARGET ${target} PROPERTY LINK_FLAGS ${_flags_str})
endif()
if(CEF_LINKER_FLAGS_DEBUG)
string(REPLACE ";" " " _flags_str "${CEF_LINKER_FLAGS_DEBUG}")
set_property(TARGET ${target} PROPERTY LINK_FLAGS_DEBUG ${_flags_str})
endif()
if(CEF_LINKER_FLAGS_RELEASE)
string(REPLACE ";" " " _flags_str "${CEF_LINKER_FLAGS_RELEASE}")
set_property(TARGET ${target} PROPERTY LINK_FLAGS_RELEASE ${_flags_str})
endif()
if(OS_MACOSX)
# Set Xcode target properties.
set_target_properties(${target} PROPERTIES
XCODE_ATTRIBUTE_ALWAYS_SEARCH_USER_PATHS NO
XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "gnu++11" # -std=gnu++11
XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO # -fno-objc-link-runtime
XCODE_ATTRIBUTE_CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS YES # -Wobjc-missing-property-synthesis
XCODE_ATTRIBUTE_COPY_PHASE_STRIP NO
XCODE_ATTRIBUTE_DEAD_CODE_STRIPPING[variant=Release] YES # -Wl,-dead_strip
XCODE_ATTRIBUTE_GCC_C_LANGUAGE_STANDARD "c99" # -std=c99
XCODE_ATTRIBUTE_GCC_CW_ASM_SYNTAX NO # No -fasm-blocks
XCODE_ATTRIBUTE_GCC_DYNAMIC_NO_PIC NO
XCODE_ATTRIBUTE_GCC_ENABLE_CPP_EXCEPTIONS NO # -fno-exceptions
XCODE_ATTRIBUTE_GCC_ENABLE_CPP_RTTI NO # -fno-rtti
XCODE_ATTRIBUTE_GCC_ENABLE_PASCAL_STRINGS NO # No -mpascal-strings
XCODE_ATTRIBUTE_GCC_INLINES_ARE_PRIVATE_EXTERN YES # -fvisibility-inlines-hidden
XCODE_ATTRIBUTE_GCC_OBJC_CALL_CXX_CDTORS YES # -fobjc-call-cxx-cdtors
XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN YES # -fvisibility=hidden
XCODE_ATTRIBUTE_GCC_THREADSAFE_STATICS NO # -fno-threadsafe-statics
XCODE_ATTRIBUTE_GCC_TREAT_WARNINGS_AS_ERRORS YES # -Werror
XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0"
XCODE_ATTRIBUTE_GCC_WARN_ABOUT_MISSING_NEWLINE YES # -Wnewline-eof
XCODE_ATTRIBUTE_USE_HEADERMAP NO
OSX_ARCHITECTURES_DEBUG "${CMAKE_OSX_ARCHITECTURES}"
OSX_ARCHITECTURES_RELEASE "${CMAKE_OSX_ARCHITECTURES}"
)
endif()
endmacro()
# Set library-specific properties.
macro(SET_LIBRARY_TARGET_PROPERTIES target)
SET_COMMON_TARGET_PROPERTIES(${target})
# Shared library linker flags.
if(CEF_SHARED_LINKER_FLAGS)
string(REPLACE ";" " " _flags_str "${CEF_SHARED_LINKER_FLAGS}")
set_property(TARGET ${target} PROPERTY LINK_FLAGS ${_flags_str})
endif()
if(CEF_SHARED_LINKER_FLAGS_DEBUG)
string(REPLACE ";" " " _flags_str "${CEF_SHARED_LINKER_FLAGS_DEBUG}")
set_property(TARGET ${target} PROPERTY LINK_FLAGS_DEBUG ${_flags_str})
endif()
if(CEF_SHARED_LINKER_FLAGS_RELEASE)
string(REPLACE ";" " " _flags_str "${CEF_SHARED_LINKER_FLAGS_RELEASE}")
set_property(TARGET ${target} PROPERTY LINK_FLAGS_RELEASE ${_flags_str})
endif()
endmacro()
# Set executable-specific properties.
macro(SET_EXECUTABLE_TARGET_PROPERTIES target)
SET_COMMON_TARGET_PROPERTIES(${target})
# Executable linker flags.
if(CEF_EXE_LINKER_FLAGS)
string(REPLACE ";" " " _flags_str "${CEF_EXE_LINKER_FLAGS}")
set_property(TARGET ${target} PROPERTY LINK_FLAGS ${_flags_str})
endif()
if(CEF_EXE_LINKER_FLAGS_DEBUG)
string(REPLACE ";" " " _flags_str "${CEF_EXE_LINKER_FLAGS_DEBUG}")
set_property(TARGET ${target} PROPERTY LINK_FLAGS_DEBUG ${_flags_str})
endif()
if(CEF_EXE_LINKER_FLAGS_RELEASE)
string(REPLACE ";" " " _flags_str "${CEF_EXE_LINKER_FLAGS_RELEASE}")
set_property(TARGET ${target} PROPERTY LINK_FLAGS_RELEASE ${_flags_str})
endif()
endmacro()
# Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
# reserved. Use of this source code is governed by a BSD-style license that
# can be found in the LICENSE file.
# Must be loaded via FindCEF.cmake.
if(NOT DEFINED _CEF_ROOT_EXPLICIT)
message(FATAL_ERROR "Use find_package(CEF) to load this file.")
endif()
#
# Shared configuration.
#
# Determine the platform.
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
set(OS_MACOSX 1)
set(OS_POSIX 1)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(OS_LINUX 1)
set(OS_POSIX 1)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
set(OS_WINDOWS 1)
endif()
# Determine the project architecture.
if(NOT DEFINED PROJECT_ARCH)
if(CMAKE_SIZEOF_VOID_P MATCHES 8)
set(PROJECT_ARCH "x86_64")
else()
set(PROJECT_ARCH "x86")
endif()
if(OS_MACOSX)
# PROJECT_ARCH should be specified on Mac OS X.
message(WARNING "No PROJECT_ARCH value specified, using ${PROJECT_ARCH}")
endif()
endif()
if(${CMAKE_GENERATOR} STREQUAL "Ninja")
set(GEN_NINJA 1)
elseif(${CMAKE_GENERATOR} STREQUAL "Unix Makefiles")
set(GEN_MAKEFILES 1)
endif()
# Determine the build type.
if(NOT CMAKE_BUILD_TYPE AND (GEN_NINJA OR GEN_MAKEFILES))
# CMAKE_BUILD_TYPE should be specified when using Ninja or Unix Makefiles.
set(CMAKE_BUILD_TYPE Release)
message(WARNING "No CMAKE_BUILD_TYPE value selected, using ${CMAKE_BUILD_TYPE}")
endif()
# Path to the include directory.
set(CEF_INCLUDE_PATH "${_CEF_ROOT}")
# Path to the libcef_dll_wrapper target.
set(CEF_LIBCEF_DLL_WRAPPER_PATH "${_CEF_ROOT}/libcef_dll")
# Shared compiler/linker flags.
list(APPEND CEF_COMPILER_DEFINES
# Allow C++ programs to use stdint.h macros specified in the C99 standard that aren't
# in the C++ standard (e.g. UINT8_MAX, INT64_MIN, etc)
__STDC_CONSTANT_MACROS __STDC_FORMAT_MACROS
)
# Configure use of the sandbox.
option(USE_SANDBOX "Enable or disable use of the sandbox." ON)
#
# Linux configuration.
#
if(OS_LINUX)
# Platform-specific compiler/linker flags.
set(CEF_LIBTYPE SHARED)
list(APPEND CEF_COMPILER_FLAGS
-fno-strict-aliasing # Avoid assumptions regarding non-aliasing of objects of different types
-fPIC # Generate position-independent code for shared libraries
-fstack-protector # Protect some vulnerable functions from stack-smashing (security feature)
-funwind-tables # Support stack unwinding for backtrace()
-fvisibility=hidden # Give hidden visibility to declarations that are not explicitly marked as visible
--param=ssp-buffer-size=4 # Set the minimum buffer size protected by SSP (security feature, related to stack-protector)
-pipe # Use pipes rather than temporary files for communication between build stages
-pthread # Use the pthread library
-Wall # Enable all warnings
-Werror # Treat warnings as errors
-Wno-missing-field-initializers # Don't warn about missing field initializers
-Wno-unused-parameter # Don't warn about unused parameters
-Wno-error=comment # Don't warn about code in comments
-Wno-comment # Don't warn about code in comments
)
list(APPEND CEF_C_COMPILER_FLAGS
-std=c99 # Use the C99 language standard
)
list(APPEND CEF_CXX_COMPILER_FLAGS
-fno-exceptions # Disable exceptions
-fno-rtti # Disable real-time type information
-fno-threadsafe-statics # Don't generate thread-safe statics
-fvisibility-inlines-hidden # Give hidden visibility to inlined class member functions
-std=gnu++11 # Use the C++11 language standard including GNU extensions
-Wsign-compare # Warn about mixed signed/unsigned type comparisons
)
list(APPEND CEF_COMPILER_FLAGS_DEBUG
-O0 # Disable optimizations
-g # Generate debug information
)
list(APPEND CEF_COMPILER_FLAGS_RELEASE
-O2 # Optimize for maximum speed
-fdata-sections # Enable linker optimizations to improve locality of reference for data sections
-ffunction-sections # Enable linker optimizations to improve locality of reference for function sections
-fno-ident # Ignore the #ident directive
-U_FORTIFY_SOURCE # Undefine _FORTIFY_SOURCE in case it was previously defined
-D_FORTIFY_SOURCE=2 # Add memory and string function protection (security feature, related to stack-protector)
)
list(APPEND CEF_LINKER_FLAGS
-fPIC # Generate position-independent code for shared libraries
-pthread # Use the pthread library
-Wl,--disable-new-dtags # Don't generate new-style dynamic tags in ELF
-Wl,--fatal-warnings # Treat warnings as errors
-Wl,-rpath,. # Set rpath so that libraries can be placed next to the executable
-Wl,-z,noexecstack # Mark the stack as non-executable (security feature)
-Wl,-z,now # Resolve symbols on program start instead of on first use (security feature)
-Wl,-z,relro # Mark relocation sections as read-only (security feature)
)
list(APPEND CEF_LINKER_FLAGS_RELEASE
-Wl,-O1 # Enable linker optimizations
-Wl,--as-needed # Only link libraries that export symbols used by the binary
-Wl,--gc-sections # Remove unused code resulting from -fdata-sections and -function-sections
)
list(APPEND CEF_COMPILER_DEFINES
_FILE_OFFSET_BITS=64 # Allow the Large File Support (LFS) interface to replace the old interface
)
list(APPEND CEF_COMPILER_DEFINES_RELEASE
NDEBUG # Not a debug build
)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG(-Wno-undefined-var-template COMPILER_SUPPORTS_NO_UNDEFINED_VAR_TEMPLATE)
if(COMPILER_SUPPORTS_NO_UNDEFINED_VAR_TEMPLATE)
list(APPEND CEF_CXX_COMPILER_FLAGS
-Wno-undefined-var-template # Don't warn about potentially uninstantiated static members
)
endif()
CHECK_C_COMPILER_FLAG(-Wno-unused-local-typedefs COMPILER_SUPPORTS_NO_UNUSED_LOCAL_TYPEDEFS)
if(COMPILER_SUPPORTS_NO_UNUSED_LOCAL_TYPEDEFS)
list(APPEND CEF_C_COMPILER_FLAGS
-Wno-unused-local-typedefs # Don't warn about unused local typedefs
)
endif()
CHECK_CXX_COMPILER_FLAG(-Wno-literal-suffix COMPILER_SUPPORTS_NO_LITERAL_SUFFIX)
if(COMPILER_SUPPORTS_NO_LITERAL_SUFFIX)
list(APPEND CEF_CXX_COMPILER_FLAGS
-Wno-literal-suffix # Don't warn about invalid suffixes on literals
)
endif()
CHECK_CXX_COMPILER_FLAG(-Wno-narrowing COMPILER_SUPPORTS_NO_NARROWING)
if(COMPILER_SUPPORTS_NO_NARROWING)
list(APPEND CEF_CXX_COMPILER_FLAGS
-Wno-narrowing # Don't warn about type narrowing
)
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
list(APPEND CEF_CXX_COMPILER_FLAGS
-Wno-attributes # The cfi-icall attribute is not supported by the GNU C++ compiler
)
endif()
if(PROJECT_ARCH STREQUAL "x86_64")
# 64-bit architecture.
list(APPEND CEF_COMPILER_FLAGS
-m64
-march=x86-64
)
list(APPEND CEF_LINKER_FLAGS
-m64
)
elseif(PROJECT_ARCH STREQUAL "x86")
# 32-bit architecture.
list(APPEND CEF_COMPILER_FLAGS
-msse2
-mfpmath=sse
-mmmx
-m32
)
list(APPEND CEF_LINKER_FLAGS
-m32
)
endif()
# Standard libraries.
set(CEF_STANDARD_LIBS
X11
)
# CEF directory paths.
set(CEF_RESOURCE_DIR "${_CEF_ROOT}/Resources")
set(CEF_BINARY_DIR "${_CEF_ROOT}/${CMAKE_BUILD_TYPE}")
set(CEF_BINARY_DIR_DEBUG "${_CEF_ROOT}/Debug")
set(CEF_BINARY_DIR_RELEASE "${_CEF_ROOT}/Release")
# CEF library paths.
set(CEF_LIB_DEBUG "${CEF_BINARY_DIR_DEBUG}/libcef.so")
set(CEF_LIB_RELEASE "${CEF_BINARY_DIR_RELEASE}/libcef.so")
# List of CEF binary files.
set(CEF_BINARY_FILES
chrome-sandbox
libcef.so
libEGL.so
libGLESv2.so
natives_blob.bin
snapshot_blob.bin
v8_context_snapshot.bin
swiftshader
)
# List of CEF resource files.
set(CEF_RESOURCE_FILES
cef.pak
cef_100_percent.pak
cef_200_percent.pak
cef_extensions.pak
devtools_resources.pak
icudtl.dat
locales
)
if(USE_SANDBOX)
list(APPEND CEF_COMPILER_DEFINES
CEF_USE_SANDBOX # Used by apps to test if the sandbox is enabled
)
endif()
endif()
#
# Mac OS X configuration.
#
if(OS_MACOSX)
# Platform-specific compiler/linker flags.
# See also Xcode target properties in cef_macros.cmake.
set(CEF_LIBTYPE SHARED)
list(APPEND CEF_COMPILER_FLAGS
-fno-strict-aliasing # Avoid assumptions regarding non-aliasing of objects of different types
-fstack-protector # Protect some vulnerable functions from stack-smashing (security feature)
-funwind-tables # Support stack unwinding for backtrace()
-fvisibility=hidden # Give hidden visibility to declarations that are not explicitly marked as visible
-Wall # Enable all warnings
-Werror # Treat warnings as errors
-Wextra # Enable additional warnings
-Wendif-labels # Warn whenever an #else or an #endif is followed by text
-Wnewline-eof # Warn about no newline at end of file
-Wno-missing-field-initializers # Don't warn about missing field initializers
-Wno-unused-parameter # Don't warn about unused parameters
)
list(APPEND CEF_C_COMPILER_FLAGS
-std=c99 # Use the C99 language standard
)
list(APPEND CEF_CXX_COMPILER_FLAGS
-fno-exceptions # Disable exceptions
-fno-rtti # Disable real-time type information
-fno-threadsafe-statics # Don't generate thread-safe statics
-fobjc-call-cxx-cdtors # Call the constructor/destructor of C++ instance variables in ObjC objects
-fvisibility-inlines-hidden # Give hidden visibility to inlined class member functions
-std=gnu++11 # Use the C++11 language standard including GNU extensions
-Wno-narrowing # Don't warn about type narrowing
-Wsign-compare # Warn about mixed signed/unsigned type comparisons
)
list(APPEND CEF_COMPILER_FLAGS_DEBUG
-O0 # Disable optimizations
-g # Generate debug information
)
list(APPEND CEF_COMPILER_FLAGS_RELEASE
-O3 # Optimize for maximum speed plus a few extras
)
list(APPEND CEF_LINKER_FLAGS
-Wl,-search_paths_first # Search for static or shared library versions in the same pass
-Wl,-ObjC # Support creation of ObjC static libraries
-Wl,-pie # Generate position-independent code suitable for executables only
)
list(APPEND CEF_LINKER_FLAGS_RELEASE
-Wl,-dead_strip # Strip dead code
)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG(-Wno-undefined-var-template COMPILER_SUPPORTS_NO_UNDEFINED_VAR_TEMPLATE)
if(COMPILER_SUPPORTS_NO_UNDEFINED_VAR_TEMPLATE)
list(APPEND CEF_CXX_COMPILER_FLAGS
-Wno-undefined-var-template # Don't warn about potentially uninstantiated static members
)
endif()
# Standard libraries.
set(CEF_STANDARD_LIBS
-lpthread
"-framework Cocoa"
"-framework AppKit"
)
# Find the newest available base SDK.
execute_process(COMMAND xcode-select --print-path OUTPUT_VARIABLE XCODE_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
foreach(OS_VERSION 10.11 10.10 10.9)
set(SDK "${XCODE_PATH}/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${OS_VERSION}.sdk")
if(NOT "${CMAKE_OSX_SYSROOT}" AND EXISTS "${SDK}" AND IS_DIRECTORY "${SDK}")
set(CMAKE_OSX_SYSROOT ${SDK})
endif()
endforeach()
# Target SDK.
set(CEF_TARGET_SDK "10.9")
list(APPEND CEF_COMPILER_FLAGS
-mmacosx-version-min=${CEF_TARGET_SDK}
)
set(CMAKE_OSX_DEPLOYMENT_TARGET ${CEF_TARGET_SDK})
# Target architecture.
if(PROJECT_ARCH STREQUAL "x86_64")
set(CMAKE_OSX_ARCHITECTURES "x86_64")
else()
set(CMAKE_OSX_ARCHITECTURES "i386")
endif()
# CEF directory paths.
set(CEF_BINARY_DIR "${_CEF_ROOT}/$<CONFIGURATION>")
set(CEF_BINARY_DIR_DEBUG "${_CEF_ROOT}/Debug")
set(CEF_BINARY_DIR_RELEASE "${_CEF_ROOT}/Release")
if(USE_SANDBOX)
list(APPEND CEF_COMPILER_DEFINES
CEF_USE_SANDBOX # Used by apps to test if the sandbox is enabled
)
# CEF sandbox library paths.
set(CEF_SANDBOX_LIB_DEBUG "${CEF_BINARY_DIR_DEBUG}/cef_sandbox.a")
set(CEF_SANDBOX_LIB_RELEASE "${CEF_BINARY_DIR_RELEASE}/cef_sandbox.a")
endif()
endif()
#
# Windows configuration.
#
if(OS_WINDOWS)
if (GEN_NINJA)
# When using the Ninja generator clear the CMake defaults to avoid excessive
# console warnings (see issue #2120).
set(CMAKE_CXX_FLAGS "")
set(CMAKE_CXX_FLAGS_DEBUG "")
set(CMAKE_CXX_FLAGS_RELEASE "")
endif()
if(USE_SANDBOX)
# Check if the current MSVC version is compatible with the cef_sandbox.lib
# static library. For a list of all version numbers see
# https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
list(APPEND supported_msvc_versions
1900 # VS2015 and updates 1, 2, & 3
1910 # VS2017 version 15.1 & 15.2
1911 # VS2017 version 15.3 & 15.4
1912 # VS2017 version 15.5
1913 # VS2017 version 15.6
1914 # VS2017 version 15.7
1915 # VS2017 version 15.8
1916 # VS2017 version 15.9
1920 # VS2019 version 16.0
1921 # VS2018 version 16.1
)
list(FIND supported_msvc_versions ${MSVC_VERSION} _index)
if (${_index} EQUAL -1)
message(WARNING "CEF sandbox is not compatible with the current MSVC version (${MSVC_VERSION})")
set(USE_SANDBOX OFF)
endif()
endif()
# Consumers who run into LNK4099 warnings can pass /Z7 instead (see issue #385).
set(CEF_DEBUG_INFO_FLAG "/Zi" CACHE STRING "Optional flag specifying specific /Z flag to use")
# Consumers using different runtime types may want to pass different flags
set(CEF_RUNTIME_LIBRARY_FLAG "/MT" CACHE STRING "Optional flag specifying which runtime to use")
if (CEF_RUNTIME_LIBRARY_FLAG)
list(APPEND CEF_COMPILER_FLAGS_DEBUG ${CEF_RUNTIME_LIBRARY_FLAG}d)
list(APPEND CEF_COMPILER_FLAGS_RELEASE ${CEF_RUNTIME_LIBRARY_FLAG})
endif()
# Platform-specific compiler/linker flags.
set(CEF_LIBTYPE STATIC)
list(APPEND CEF_COMPILER_FLAGS
/MP # Multiprocess compilation
/Gy # Enable function-level linking
/GR- # Disable run-time type information
/W4 # Warning level 4
/WX # Treat warnings as errors
/wd4100 # Ignore "unreferenced formal parameter" warning
/wd4127 # Ignore "conditional expression is constant" warning
/wd4244 # Ignore "conversion possible loss of data" warning
/wd4481 # Ignore "nonstandard extension used: override" warning
/wd4512 # Ignore "assignment operator could not be generated" warning
/wd4701 # Ignore "potentially uninitialized local variable" warning
/wd4702 # Ignore "unreachable code" warning
/wd4996 # Ignore "function or variable may be unsafe" warning
${CEF_DEBUG_INFO_FLAG}
)
list(APPEND CEF_COMPILER_FLAGS_DEBUG
/RTC1 # Disable optimizations
/Od # Enable basic run-time checks
)
list(APPEND CEF_COMPILER_FLAGS_RELEASE
/O2 # Optimize for maximum speed
/Ob2 # Inline any suitable function
/GF # Enable string pooling
)
list(APPEND CEF_LINKER_FLAGS_DEBUG
/DEBUG # Generate debug information
)
list(APPEND CEF_EXE_LINKER_FLAGS
/MANIFEST:NO # No default manifest (see ADD_WINDOWS_MANIFEST macro usage)
/LARGEADDRESSAWARE # Allow 32-bit processes to access 3GB of RAM
)
list(APPEND CEF_COMPILER_DEFINES
WIN32 _WIN32 _WINDOWS # Windows platform
UNICODE _UNICODE # Unicode build
WINVER=0x0601 _WIN32_WINNT=0x601 # Targeting Windows 7
NOMINMAX # Use the standard's templated min/max
WIN32_LEAN_AND_MEAN # Exclude less common API declarations
_HAS_EXCEPTIONS=0 # Disable exceptions
)
list(APPEND CEF_COMPILER_DEFINES_RELEASE
NDEBUG _NDEBUG # Not a debug build
)
# Standard libraries.
set(CEF_STANDARD_LIBS
comctl32.lib
rpcrt4.lib
shlwapi.lib
ws2_32.lib
)
# CEF directory paths.
set(CEF_RESOURCE_DIR "${_CEF_ROOT}/Resources")
set(CEF_BINARY_DIR "${_CEF_ROOT}/$<CONFIGURATION>")
set(CEF_BINARY_DIR_DEBUG "${_CEF_ROOT}/Debug")
set(CEF_BINARY_DIR_RELEASE "${_CEF_ROOT}/Release")
# CEF library paths.
set(CEF_LIB_DEBUG "${CEF_BINARY_DIR_DEBUG}/libcef.lib")
set(CEF_LIB_RELEASE "${CEF_BINARY_DIR_RELEASE}/libcef.lib")
# List of CEF binary files.
set(CEF_BINARY_FILES
chrome_elf.dll
d3dcompiler_47.dll
libcef.dll
libEGL.dll
libGLESv2.dll
snapshot_blob.bin
v8_context_snapshot.bin
swiftshader
)
# List of CEF resource files.
set(CEF_RESOURCE_FILES
cef.pak
cef_100_percent.pak
cef_200_percent.pak
cef_extensions.pak
devtools_resources.pak
icudtl.dat
locales
)
if(USE_SANDBOX)
list(APPEND CEF_COMPILER_DEFINES
PSAPI_VERSION=1 # Required by cef_sandbox.lib
CEF_USE_SANDBOX # Used by apps to test if the sandbox is enabled
)
# Libraries required by cef_sandbox.lib.
set(CEF_SANDBOX_STANDARD_LIBS
dbghelp.lib
psapi.lib
version.lib
wbemuuid.lib
winmm.lib
)
# CEF sandbox library paths.
set(CEF_SANDBOX_LIB_DEBUG "${CEF_BINARY_DIR_DEBUG}/cef_sandbox.lib")
set(CEF_SANDBOX_LIB_RELEASE "${CEF_BINARY_DIR_RELEASE}/cef_sandbox.lib")
endif()
# Configure use of ATL.
option(USE_ATL "Enable or disable use of ATL." ON)
if(USE_ATL)
# Locate the atlmfc directory if it exists. It may be at any depth inside
# the VC directory. The cl.exe path returned by CMAKE_CXX_COMPILER may also
# be at different depths depending on the toolchain version
# (e.g. "VC/bin/cl.exe", "VC/bin/amd64_x86/cl.exe",
# "VC/Tools/MSVC/14.10.25017/bin/HostX86/x86/cl.exe", etc).
set(HAS_ATLMFC 0)
get_filename_component(VC_DIR ${CMAKE_CXX_COMPILER} DIRECTORY)
get_filename_component(VC_DIR_NAME ${VC_DIR} NAME)
while(NOT ${VC_DIR_NAME} STREQUAL "VC")
get_filename_component(VC_DIR ${VC_DIR} DIRECTORY)
if(IS_DIRECTORY "${VC_DIR}/atlmfc")
set(HAS_ATLMFC 1)
break()
endif()
get_filename_component(VC_DIR_NAME ${VC_DIR} NAME)
endwhile()
# Determine if the Visual Studio install supports ATL.
if(NOT HAS_ATLMFC)
message(WARNING "ATL is not supported by your VC installation.")
set(USE_ATL OFF)
endif()
endif()
if(USE_ATL)
list(APPEND CEF_COMPILER_DEFINES
CEF_USE_ATL # Used by apps to test if ATL support is enabled
)
endif()
endif()
@ECHO OFF
REM Quickly rebuild 64-bit VS2015 solution/project files from the CMake files.
cmake -G "Visual Studio 14 Win64"
pause
\ No newline at end of file
@ECHO OFF
REM Quickly rebuild 64-bit VS2019 solution/project files from the CMake files.
cmake -G "Visual Studio 16" -A x64
pause
\ No newline at end of file
@ECHO OFF
REM Quickly rebuild 64-bit VS2022 solution/project files from the CMake files.
cmake -G "Visual Studio 17" -A x64
pause
\ No newline at end of file
......@@ -16,6 +16,8 @@ set(FCHOST_SRCS
fchost_storage.h
fchost_storage_js.cc
fchost_storage_js.h
utility.cc
utility.h
)
set(FCHOST_SRCS_LINUX
fchost_linux.cc
......@@ -73,6 +75,18 @@ set(FCHOST_RESOURCES_SRCS
${FCHOST_RESOURCES_MAC_ENGLISH_LPROJ_SRCS}
)
function (symlink_or_copy_to_binary_dir _target _srcFile)
get_filename_component(_fileName "${_srcFile}" NAME)
if (WIN32)
set(action copy_if_different)
else()
set(action create_symlink)
endif()
add_custom_command(POST_BUILD
TARGET ${_target}
COMMAND ${CMAKE_COMMAND} -E ${action} "${_srcFile}" "$<TARGET_FILE_DIR:${_target}>/${_fileName}"
)
endfunction()
#
# Shared configuration.
......@@ -91,14 +105,19 @@ endif()
# Determine the target output directory.
SET_CEF_TARGET_OUT_DIR()
# Executable target.
add_executable(${CEF_TARGET} MACOSX_BUNDLE WIN32 ${FCHOST_SRCS})
set(gameHTMLFile "FC_pregmod.html")
# Link the HTML where the executable expects to find it
symlink_or_copy_to_binary_dir(${CEF_TARGET} "${CMAKE_SOURCE_DIR}/../bin/${gameHTMLFile}")
#
# Linux configuration.
#
if(OS_LINUX)
# Executable target.
add_executable(${CEF_TARGET} ${FCHOST_SRCS})
SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET})
add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
......@@ -108,11 +127,14 @@ if(OS_LINUX)
set_target_properties(${CEF_TARGET} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
set_target_properties(${CEF_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CEF_TARGET_OUT_DIR})
# Copy binary and resource files to the target output directory.
COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
# Copy binary files to the target output directory.
#COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
foreach(cefBinaryFile IN LISTS CEF_BINARY_FILES)
symlink_or_copy_to_binary_dir(${CEF_TARGET} "${CEF_BINARY_DIR}/${cefBinaryFile}")
endforeach()
COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
if (EXISTS "${CEF_BINARY_DIR}/libminigbm.so")
COPY_FILES("${CEF_TARGET}" "libminigbm.so" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
symlink_or_copy_to_binary_dir(${CEF_TARGET} "${CEF_BINARY_DIR}/libminigbm.so")
endif()
endif()
......@@ -150,7 +172,7 @@ if(OS_MACOSX)
)
# Main executable target.
add_executable(${CEF_TARGET} MACOSX_BUNDLE ${FCHOST_RESOURCES_SRCS} ${FCHOST_SRCS})
target_sources(${CEF_TARGET} ${FCHOST_RESOURCES_SRCS})
SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET})
add_dependencies(${CEF_TARGET} libcef_dll_wrapper "${CEF_HELPER_TARGET}")
target_link_libraries(${CEF_TARGET} libcef_dll_wrapper ${CEF_STANDARD_LIBS})
......@@ -188,7 +210,6 @@ endif()
if(OS_WINDOWS)
# Executable target.
add_executable(${CEF_TARGET} WIN32 ${FCHOST_SRCS})
add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
SET_EXECUTABLE_TARGET_PROPERTIES(${CEF_TARGET})
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
......@@ -199,5 +220,4 @@ if(OS_WINDOWS)
# Copy binary and resource files to the target output directory.
COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
COPY_FILES("${CEF_TARGET}" "FC_pregmod.html" "../../bin" "${CEF_TARGET_OUT_DIR}")
endif()
......@@ -4,7 +4,7 @@
#include "fchost_app.h"
#include <string>
#include "./utility.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
......@@ -14,6 +14,13 @@
#include "fchost_handler.h"
#include "fchost_storage_js.h"
#include <filesystem>
#include <string>
#if defined(OS_LINUX)
#include <unistd.h>
#endif
namespace {
// When using the Views framework this object provides the delegate
......@@ -23,7 +30,7 @@ class SimpleWindowDelegate : public CefWindowDelegate {
explicit SimpleWindowDelegate(CefRefPtr<CefBrowserView> browser_view)
: browser_view_(browser_view) {}
void OnWindowCreated(CefRefPtr<CefWindow> window) OVERRIDE {
void OnWindowCreated(CefRefPtr<CefWindow> window) override {
// Add the browser view and show the window.
window->AddChildView(browser_view_);
window->Show();
......@@ -32,11 +39,11 @@ class SimpleWindowDelegate : public CefWindowDelegate {
browser_view_->RequestFocus();
}
void OnWindowDestroyed(CefRefPtr<CefWindow> window) OVERRIDE {
browser_view_ = NULL;
void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
browser_view_ = nullptr;
}
bool CanClose(CefRefPtr<CefWindow> window) OVERRIDE {
bool CanClose(CefRefPtr<CefWindow> window) override {
// Allow the window to close if the browser says it's OK.
CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
if (browser)
......@@ -44,7 +51,7 @@ class SimpleWindowDelegate : public CefWindowDelegate {
return true;
}
CefSize GetPreferredSize(CefRefPtr<CefView> view) OVERRIDE {
CefSize GetPreferredSize(CefRefPtr<CefView> view) override {
return CefSize(800, 600);
}
......@@ -55,6 +62,36 @@ class SimpleWindowDelegate : public CefWindowDelegate {
DISALLOW_COPY_AND_ASSIGN(SimpleWindowDelegate);
};
std::filesystem::path executablePath() {
#if defined(OS_WIN)
wchar_t target_path[_MAX_PATH];
GetModuleFileNameW(NULL, target_path, _MAX_PATH);
return std::filesystem::path(target_path);
#elif defined(OS_LINUX)
std::string buf;
buf.resize(32); // initial size estimate
for (;; ) {
ssize_t ret = readlink("/proc/self/exe", buf.data(), buf.size());
if (ret == -1) {
perror("getexename() failed");
break;
}
if (static_cast<std::size_t>(ret) >= buf.size()) { // >= because we need the terminating NUL too
buf.resize(buf.size() * 2);
continue;
}
return buf;
}
return {};
#else
#error "Platform-specific code required"
#endif
}
} // namespace
FCHostApp::FCHostApp() {}
......@@ -86,25 +123,17 @@ void FCHostApp::OnContextInitialized() {
// For now, read from external file. Probably want to make this a resource
// at least on Windows.
std::filesystem::path gameHTML = executablePath().parent_path() / "FC_pregmod.html";
#if defined(OS_WIN)
wchar_t target_path[_MAX_PATH];
GetModuleFileNameW(NULL, target_path, _MAX_PATH);
std::wstring url = target_path;
size_t pos = url.find_last_of(L"\\/");
url = url.substr(0, pos);
url += L"/FC_pregmod.html";
std::wstring url = gameHTML.native();
#else
#error "Platform-specific code needed"
std::string url = "file://" + gameHTML.string();
#endif
// Allow some access flexibility for our local file
browser_settings.file_access_from_file_urls = STATE_ENABLED;
browser_settings.universal_access_from_file_urls = STATE_ENABLED;
if (use_views) {
// Create the BrowserView.
CefRefPtr<CefBrowserView> browser_view = CefBrowserView::CreateBrowserView(
handler, url, browser_settings, NULL, NULL, NULL);
handler, url, browser_settings, nullptr, nullptr, nullptr);
// Create the Window. It will show itself after creation.
CefWindow::CreateTopLevelWindow(new SimpleWindowDelegate(browser_view));
......@@ -120,11 +149,43 @@ void FCHostApp::OnContextInitialized() {
// Create the first browser window.
CefBrowserHost::CreateBrowser(window_info, handler, url, browser_settings,
NULL, NULL);
nullptr, nullptr);
}
}
void FCHostApp::OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) {
FCHostStorageRegister(GetLocalStorePath().ToWString() + L"/FCHostPersistentStorage", context->GetGlobal());
FCHostStorageRegister(GetLocalStorePath() / "FCHostPersistentStorage", context->GetGlobal());
}
int FCHostApp::main(const CefMainArgs& args, CefCommandLine* commandLine)
{
// Specify CEF global settings here.
CefSettings settings;
if (commandLine->HasSwitch("enable-chrome-runtime")) {
// Enable experimental Chrome runtime. See issue #2969 for details.
settings.chrome_runtime = true;
}
// Cache location is required for local storage
cef_string_from_path(this->GetLocalStorePath(), &settings.cache_path);
// When generating projects with CMake the CEF_USE_SANDBOX value will be defined
// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable
// use of the sandbox.
#if !defined(CEF_USE_SANDBOX)
settings.no_sandbox = true;
#endif
// Initialize CEF for the browser process.
CefInitialize(args, settings, this, nullptr);
// Run the CEF message loop. This will block until CefQuitMessageLoop() is
// called.
CefRunMessageLoop();
// Shut down CEF.
CefShutdown();
return 0;
}
......@@ -6,6 +6,11 @@
#include "include/cef_app.h"
#include <filesystem>
class CefMainArgs;
class CefCommandLine;
// Implement application-level callbacks for the browser process.
class FCHostApp : public CefApp, public CefBrowserProcessHandler, public CefRenderProcessHandler {
public:
......@@ -13,19 +18,21 @@ class FCHostApp : public CefApp, public CefBrowserProcessHandler, public CefRend
// CefApp methods:
virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()
OVERRIDE {
override {
return this;
}
virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler()
OVERRIDE {
override {
return this;
}
// CefBrowserProcessHandler methods:
virtual void OnContextInitialized() OVERRIDE;
virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) OVERRIDE;
virtual void OnContextInitialized() override;
virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) override;
std::filesystem::path GetLocalStorePath();
CefString GetLocalStorePath();
int main(const CefMainArgs& args, CefCommandLine* commandLine);
private:
// Include the default reference counting implementation.
......
......@@ -9,6 +9,7 @@
#include <fstream>
#include "include/base/cef_bind.h"
#include "include/base/cef_callback.h"
#include "include/cef_app.h"
#include "include/cef_parser.h"
#include "include/views/cef_browser_view.h"
......@@ -173,7 +174,7 @@ void FCHostHandler::OnLoadEnd(CefRefPtr<CefBrowser> browser,
}", frame->GetURL(), 0);
}
void FCHostHandler::OnBeforeDownload(CefRefPtr<CefBrowser> browser,
bool FCHostHandler::OnBeforeDownload(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDownloadItem> download_item,
const CefString& suggested_name,
CefRefPtr< CefBeforeDownloadCallback > callback)
......@@ -181,6 +182,8 @@ void FCHostHandler::OnBeforeDownload(CefRefPtr<CefBrowser> browser,
CEF_REQUIRE_UI_THREAD();
callback->Continue(suggested_name, true);
return true;
}
bool FCHostHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
......@@ -190,35 +193,90 @@ bool FCHostHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
{
CEF_REQUIRE_UI_THREAD();
if (event.type == cef_key_event_type_t::KEYEVENT_CHAR)
// for nonwindows platforms, we need to know the windows equivalent keycode, because CEF will convert to them for us
const int key_f = 0x46;
const int key_j = 0x4A;
const int key_plus = 0xBB;
const int key_numpad_plus = 0x6B;
const int key_minus = 0xBD;
const int key_numpad_minus = 0x6D;
if (event.type == cef_key_event_type_t::KEYEVENT_RAWKEYDOWN)
{
// CTRL+SHIFT+J - bring up the Javascript debugger
if ((event.modifiers == (cef_event_flags_t::EVENTFLAG_CONTROL_DOWN | cef_event_flags_t::EVENTFLAG_SHIFT_DOWN)) && event.unmodified_character == 10 /* j? maybe only on windows? whatever */)
if ((event.modifiers == (cef_event_flags_t::EVENTFLAG_CONTROL_DOWN | cef_event_flags_t::EVENTFLAG_SHIFT_DOWN)) && event.windows_key_code == key_j)
{
CefWindowInfo windowInfo;
CefBrowserSettings settings;
CefPoint point;
#if defined (OS_WIN)
windowInfo.SetAsPopup(browser->GetHost()->GetWindowHandle(), "DevTools");
#elif defined(OS_LINUX)
windowInfo.SetAsChild(browser->GetHost()->GetWindowHandle(), CefRect(100, 100, 800, 600));
#else
#error "Platform-specific code required"
#endif
browser->GetHost()->ShowDevTools(windowInfo, browser->GetHost()->GetClient(), settings, point);
return true;
}
// CTRL+F - bring up Find In Page
else if (event.modifiers == cef_event_flags_t::EVENTFLAG_CONTROL_DOWN && event.unmodified_character == 6 /* f? maybe only on windows? whatever */)
else if (event.modifiers == cef_event_flags_t::EVENTFLAG_CONTROL_DOWN && event.windows_key_code == key_f)
{
// probably can do this at some point by ripping off code from the full-fat cefclient, but damn there's a lot of it...
// return true;
}
// CTRL++ - zoom in
else if (event.modifiers == cef_event_flags_t::EVENTFLAG_CONTROL_DOWN && (event.windows_key_code == key_plus || event.windows_key_code == key_numpad_plus))
{
double curZoom = browser->GetHost()->GetZoomLevel();
browser->GetHost()->SetZoomLevel(curZoom + 1.0);
}
// CTRL+- - zoom out
else if (event.modifiers == cef_event_flags_t::EVENTFLAG_CONTROL_DOWN && (event.windows_key_code == key_minus || event.windows_key_code == key_numpad_minus))
{
double curZoom = browser->GetHost()->GetZoomLevel();
browser->GetHost()->SetZoomLevel(curZoom - 1.0);
}
}
return false;
}
void FCHostHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model)
{
CEF_REQUIRE_UI_THREAD();
if (params->HasImageContents() && params->GetSourceUrl() != "")
model->AddItem(MENU_ID_USER_FIRST, "Save Image...");
}
bool FCHostHandler::OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
int command_id,
EventFlags event_flags)
{
CEF_REQUIRE_UI_THREAD();
switch (command_id) {
case MENU_ID_USER_FIRST:
browser->GetHost()->StartDownload(params->GetSourceUrl());
return true;
default:
return false;
}
}
void FCHostHandler::CloseAllBrowsers(bool force_close) {
if (!CefCurrentlyOn(TID_UI)) {
// Execute on the UI thread.
CefPostTask(TID_UI, base::Bind(&FCHostHandler::CloseAllBrowsers, this,
CefPostTask(TID_UI, base::BindOnce(&FCHostHandler::CloseAllBrowsers, this,
force_close));
return;
}
......
......@@ -13,7 +13,9 @@ class FCHostHandler : public CefClient,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefDownloadHandler,
public CefKeyboardHandler {
public CefKeyboardHandler,
public CefContextMenuHandler,
private CefDialogHandler {
public:
explicit FCHostHandler(bool use_views);
~FCHostHandler();
......@@ -22,52 +24,73 @@ class FCHostHandler : public CefClient,
static FCHostHandler* GetInstance();
// CefClient methods:
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() override {
return this;
}
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override {
return this;
}
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE { return this; }
virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler() OVERRIDE { return this; }
virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() OVERRIDE { return this; }
virtual CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler() override { return this; }
virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() override { return this; }
virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override { return this; }
CefRefPtr< CefDialogHandler > GetDialogHandler() override { return this; }
bool OnFileDialog(CefRefPtr<CefBrowser> browser,
CefDialogHandler::FileDialogMode mode,
const CefString& title,
const CefString& default_file_path,
const std::vector<CefString>& accept_filters,
const std::vector<CefString>& accept_extensions,
const std::vector<CefString>& accept_descriptions,
CefRefPtr<CefFileDialogCallback> callback) override;
// CefDisplayHandler methods:
virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) OVERRIDE;
const CefString& title) override;
virtual bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,
cef_log_severity_t level,
const CefString& message,
const CefString& source,
int line) OVERRIDE;
int line) override;
// CefLifeSpanHandler methods:
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
virtual bool DoClose(CefRefPtr<CefBrowser> browser) override;
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
// CefLoadHandler methods:
virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;
const CefString& failedUrl) override;
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) OVERRIDE;
int httpStatusCode) override;
// CefDownloadHandler methods:
virtual void OnBeforeDownload(CefRefPtr<CefBrowser> browser,
virtual bool OnBeforeDownload(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDownloadItem> download_item,
const CefString& suggested_name,
CefRefPtr< CefBeforeDownloadCallback > callback) OVERRIDE;
CefRefPtr< CefBeforeDownloadCallback > callback) override;
// CefKeyboardHandler methods:
virtual bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event,
CefEventHandle os_event,
bool* is_keyboard_shortcut) OVERRIDE;
bool* is_keyboard_shortcut) override;
// CefContextMenuHandler methods:
virtual void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) override;
virtual bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
int command_id,
EventFlags event_flags) override;
// Request that all existing browser windows close.
void CloseAllBrowsers(bool force_close);
......
// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "fchost_handler.h"
#if defined(CEF_X11)
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#endif
#include "include/base/cef_logging.h"
#include "include/cef_browser.h"
#include <cstdlib>
#include <cstdio>
#include <filesystem>
#include <iomanip>
#include <memory>
#include <sstream>
#include <string>
// #define TRACE
#ifdef TRACE
#include <iostream>
#endif
namespace {
std::string executeProcessAndReadStdOut(const std::string& command)
{
#ifdef TRACE
std::cerr << "Command: " << command << std::endl;
#endif
auto closer = [](FILE* fp) { ::pclose(fp); };
std::unique_ptr<FILE, decltype(closer)> f(::popen(command.c_str(), "r"), closer);
std::ostringstream output;
const int BUF_SIZE = 1024;
char buf[BUF_SIZE];
while(!std::feof(f.get())){
std::size_t read = std::fread(buf, 1, BUF_SIZE, f.get());
output.write(buf, static_cast<std::streamsize>(read));
}
std::string res = output.str();
return res.substr(0, res.size() - 1); // to clear out CR
}
std::string runKDialog(CefDialogHandler::FileDialogMode mode, const CefString& title, const CefString& default_file_path,
const std::vector<CefString>& accept_filters)
{
std::ostringstream cmdLine;
cmdLine << "kdialog";
if (!title.empty()) {
cmdLine << " --title " << std::quoted(title.ToString());
}
#ifdef TRACE
std::cerr << "mode: " << std::hex << mode << std::dec << std::endl
<< "default_file_path: " << default_file_path << std::endl
<< "accept_filters: " << std::endl;
for (const auto& f: accept_filters) {
std::cerr << f.ToString() << std::endl;
}
#endif
switch (mode) {
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN_MULTIPLE:
cmdLine << " --multiple"; [[fallthrough]];
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN:
cmdLine << " --getopenfilename";
break;
case CefDialogHandler::FileDialogMode::FILE_DIALOG_SAVE:
cmdLine << " --getsavefilename";
break;
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN_FOLDER:
cmdLine << " --getexistingdirectory";
break;
default:
break; // TODO
}
const std::string dsp = default_file_path.ToString();
if (dsp.find('/') != std::string::npos) {
cmdLine << ' ' << std::quoted(dsp);
} else {
// TODO save last used directory and put it here instead of $HOME
cmdLine << ' ' << std::quoted(std::string(getenv("HOME")) + '/' + dsp);
}
if (accept_filters.size()) {
cmdLine << " \'";
for (const auto& f: accept_filters) {
const auto s = f.ToString();
cmdLine << " |" << s << " file(*" << s << ')';
}
cmdLine << '\'';
}
return executeProcessAndReadStdOut(cmdLine.str());
}
std::string runZenity(CefDialogHandler::FileDialogMode mode, const CefString& title, const CefString& default_file_path,
const std::vector<CefString>& accept_filters)
{
std::ostringstream cmdLine;
cmdLine << "zenity --file-selection --confirm-overwrite";
switch (mode) {
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN_MULTIPLE:
cmdLine << " --multiple";
break;
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN:
// this is the implicit default mode for zenity
break;
case CefDialogHandler::FileDialogMode::FILE_DIALOG_SAVE:
cmdLine << " --save";
break;
case CefDialogHandler::FileDialogMode::FILE_DIALOG_OPEN_FOLDER:
cmdLine << " --directory";
break;
default:
break; // TODO ?
}
const std::string dsp = default_file_path.ToString();
if (dsp.find('/') != std::string::npos) {
cmdLine << " --filename=" << std::quoted(dsp);
} else {
// TODO save last used directory and put it here instead of $HOME
cmdLine << " --filename=" << std::quoted(std::string(getenv("HOME")) + '/' + dsp);
}
for (const auto& f: accept_filters) {
const auto s = f.ToString();
cmdLine << " --file-filter=\"" << s << " file | *" << s << '"';
}
return executeProcessAndReadStdOut(cmdLine.str());
}
using DialogRunFunc = std::string (*)(CefDialogHandler::FileDialogMode mode, const CefString& title, const CefString& default_file_path,
const std::vector<CefString>& accept_filters);
class DialogHelper {
public:
DialogHelper();
std::string operator()(CefDialogHandler::FileDialogMode mode, const CefString& title, const CefString& default_file_path,
const std::vector<CefString>& accept_filters) const
{
return func_ ? func_(mode, title, default_file_path, accept_filters) : "";
}
private:
DialogRunFunc func_;
};
DialogHelper::DialogHelper()
{
// we will try to launch kdialog or zenity
std::string dialogExecutable;
// try to determine which environment we run inside
const char* desktop_env = getenv("XDG_CURRENT_DESKTOP");
std::string desktop = desktop_env == nullptr ? "" : desktop_env;
const auto checkExeExists = [](const char* name) {
int ec = ::system((std::string(name) + " --help > /dev/null").c_str());
return ec >= 0 && ec < 127;
};
if (desktop == "KDE") {
dialogExecutable = "kdialog";
} else if (desktop == "GNOME") {
dialogExecutable = "zenity";
} else {
// well, let's check executables
if (checkExeExists("zenity")) {
dialogExecutable = "zenity";
} else if (checkExeExists("kdialog")){
dialogExecutable = "kdialog";
}
}
#ifdef TRACE
std::cerr << "dialogExecutable: " << dialogExecutable << std::endl
<< "checkExeExists: " << checkExeExists(dialogExecutable.c_str()) << std::endl;
#endif
if (!dialogExecutable.empty() && checkExeExists(dialogExecutable.c_str())) {
if (dialogExecutable == "kdialog") {
func_ = &runKDialog;
} else if (dialogExecutable == "zenity") {
func_ = &runZenity;
} else {
func_ = nullptr;
}
}
}
}
void FCHostHandler::PlatformTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title) {
std::string titleStr(title);
#if defined(CEF_X11)
// Retrieve the X11 display shared with Chromium.
::Display* display = cef_get_xdisplay();
DCHECK(display);
// Retrieve the X11 window handle for the browser.
::Window window = browser->GetHost()->GetWindowHandle();
if (window == kNullWindowHandle)
return;
// Retrieve the atoms required by the below XChangeProperty call.
const char* kAtoms[] = {"_NET_WM_NAME", "UTF8_STRING"};
Atom atoms[2];
int result =
XInternAtoms(display, const_cast<char**>(kAtoms), 2, false, atoms);
if (!result)
NOTREACHED();
// Set the window title.
XChangeProperty(display, window, atoms[0], atoms[1], 8, PropModeReplace,
reinterpret_cast<const unsigned char*>(titleStr.c_str()),
titleStr.size());
// TODO(erg): This is technically wrong. So XStoreName and friends expect
// this in Host Portable Character Encoding instead of UTF-8, which I believe
// is Compound Text. This shouldn't matter 90% of the time since this is the
// fallback to the UTF8 property above.
XStoreName(display, browser->GetHost()->GetWindowHandle(), titleStr.c_str());
#endif // defined(CEF_X11)
}
bool FCHostHandler::OnFileDialog(CefRefPtr<CefBrowser> /* browser */,
CefDialogHandler::FileDialogMode mode,
const CefString& title,
const CefString& default_file_path,
const std::vector<CefString>& accept_filters,
const std::vector<CefString>& /* accept_extensions */,
const std::vector<CefString>& /* accept_descriptions */,
CefRefPtr<CefFileDialogCallback> callback)
{
static DialogHelper helper;
std::string fn = helper(mode, title, default_file_path, accept_filters);
#ifdef TRACE
std::cerr << "fn: " << fn << std::endl;
#endif
if (fn.empty()) {
callback->Cancel();
return false;
}
std::vector<CefString> selected;
selected.push_back(fn);
callback->Continue(selected);
return true;
}
......@@ -26,3 +26,15 @@ void FCHostHandler::PlatformTitleChange(CefRefPtr<CefBrowser> browser,
SetWindowText(hwnd, std::wstring(title).c_str());
}
bool FCHostHandler::OnFileDialog(CefRefPtr<CefBrowser> /* browser */,
CefDialogHandler::FileDialogMode /* mode */,
const CefString& /* title */,
const CefString& /* default_file_path */,
const std::vector<CefString>& /* accept_filters */,
const std::vector<CefString>& /* accept_extensions */,
const std::vector<CefString>& /* accept_descriptions */,
CefRefPtr<CefFileDialogCallback> /* callback */)
{
return false; // to display the default dialog
}
// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "fchost_app.h"
#if defined(CEF_X11)
#include <X11/Xlib.h>
#endif
#include "include/base/cef_logging.h"
#include "include/cef_command_line.h"
#include <filesystem>
std::filesystem::path FCHostApp::GetLocalStorePath()
{
return std::filesystem::path{getenv("HOME")} / ".local" / "share" / "FreeCities_Pregmod";
}
#if defined(CEF_X11)
namespace {
int XErrorHandlerImpl(Display* display, XErrorEvent* event) {
LOG(WARNING) << "X error received: "
<< "type " << event->type << ", "
<< "serial " << event->serial << ", "
<< "error_code " << static_cast<int>(event->error_code) << ", "
<< "request_code " << static_cast<int>(event->request_code)
<< ", "
<< "minor_code " << static_cast<int>(event->minor_code);
return 0;
}
int XIOErrorHandlerImpl(Display* display) {
return 0;
}
} // namespace
#endif // defined(CEF_X11)
// Entry point function for all processes.
int main(int argc, char* argv[]) {
// Provide CEF with command-line arguments.
CefMainArgs main_args(argc, argv);
// It will create the first browser instance in OnContextInitialized() after
// CEF has initialized.
CefRefPtr<FCHostApp> app(new FCHostApp);
// CEF applications have multiple sub-processes (render, plugin, GPU, etc)
// that share the same executable. This function checks the command-line and,
// if this is a sub-process, executes the appropriate logic.
int exit_code = CefExecuteProcess(main_args, app, nullptr);
if (exit_code >= 0) {
// The sub-process has completed so return here.
return exit_code;
}
#if defined(CEF_X11)
// Install xlib error handlers so that the application won't be terminated
// on non-fatal errors.
XSetErrorHandler(XErrorHandlerImpl);
XSetIOErrorHandler(XIOErrorHandlerImpl);
#endif
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->InitFromArgv(argc, argv);
return app->main(main_args, command_line.get());
}
#include "fchost_storage.h"
#include <algorithm>
#if defined(OS_WIN)
#include "shlwapi.h"
#endif
#include <cstdio>
#include <memory>
#include <vector>
static_assert(CEF_STRING_TYPE_UTF16);
namespace fs = std::filesystem;
namespace {
struct closeFile {
void operator()(std::FILE* f) const noexcept
{
std::fclose(f);
}
};
}
CefRefPtr<CefV8Value> FCHostSessionStorage::keys() const
{
......@@ -17,7 +30,6 @@ CefRefPtr<CefV8Value> FCHostSessionStorage::keys() const
return ret;
}
#if defined(OS_WIN)
/* This shouldn't happen, so don't waste time on it. Sugarcube really only writes simple alphanumeric keys.
static bool SanitizePath(std::wstring& inpath)
{
......@@ -31,96 +43,100 @@ static bool SanitizePath(std::wstring& inpath)
}
*/
FCHostPersistentStorage::FCHostPersistentStorage(const std::filesystem::path& _path)
: path{_path}
{
ensure_folder_exists();
load();
}
void FCHostPersistentStorage::set(const CefString& key, CefRefPtr<CefV8Value> val)
{
__super::set(key, val);
base::set(key, val);
// only strings get persisted (should be OK, Sugarcube will serialize first)
if (val->IsString())
{
// we should probably be doing this async but TBT Sugarcube is the slow part, not the file IO
DWORD written;
HANDLE fh = CreateFile(get_filename(key).c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
std::unique_ptr<std::FILE, closeFile> fh;
#if defined(OS_WIN)
fh.reset(_wfopen(get_filename(key).c_str(), L"wb"));
#else
fh.reset(std::fopen(get_filename(key).c_str(), "wb"));
#endif
CefString valStr = val->GetStringValue();
if (valStr.size() > 0)
{
WriteFile(fh, valStr.c_str(), static_cast<DWORD>(valStr.size() * sizeof(valStr.c_str()[0])), &written, NULL);
if (valStr.size() > 0) {
std::fwrite(valStr.c_str(), static_cast<size_t>(valStr.size() * sizeof(valStr.c_str()[0])), 1, fh.get());
}
CloseHandle(fh);
}
}
bool FCHostPersistentStorage::remove(const CefString& key)
{
bool retval = __super::remove(key);
DeleteFile(get_filename(key).c_str());
return retval;
fs::remove(get_filename(key));
return base::remove(key);
}
void FCHostPersistentStorage::clear()
{
__super::clear();
WIN32_FIND_DATAW w32fd;
HANDLE hFind = FindFirstFile((path + L"\\*").c_str(), &w32fd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if (w32fd.dwFileAttributes & ~(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE))
{
DeleteFile(get_filename(w32fd.cFileName).c_str());
}
} while (FindNextFile(hFind, &w32fd));
FindClose(hFind);
for (const auto& entry: fs::directory_iterator(path)) {
if (fs::is_regular_file(entry.path())) {
fs::remove_all(entry.path());
}
}
base::clear();
}
void FCHostPersistentStorage::load()
{
constexpr size_t bufsize = 1024 * 1024 * 1024; // 1gb should be enough
char* readbuf = new char[bufsize];
WIN32_FIND_DATAW w32fd;
HANDLE hFind = FindFirstFile((path + L"\\*").c_str(), &w32fd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if (w32fd.dwFileAttributes & ~(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE))
{
DWORD bytesread = 0;
HANDLE fh = CreateFile(get_filename(w32fd.cFileName).c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh)
{
BOOL success = ReadFile(fh, readbuf, static_cast<DWORD>(bufsize - 1), &bytesread, NULL);
if (success)
{
readbuf[bytesread] = L'\0';
readbuf[bytesread+1] = L'\0'; // null terminate
CefString val = reinterpret_cast<wchar_t*>(readbuf);
storage.emplace(w32fd.cFileName, CefV8Value::CreateString(val));
}
CloseHandle(fh);
std::vector<char> readbuf;
std::unique_ptr<std::FILE, closeFile> fh;
for (const auto& entry: fs::directory_iterator(path)) {
if (fs::is_regular_file(entry.path())) {
const auto entrySize = fs::file_size(entry.path());
readbuf.resize(static_cast<std::size_t>(entrySize + 2)); // +1 char16
#if defined(OS_WIN)
fh.reset(_wfopen(entry.path().c_str(), L"rb"));
#else
fh.reset(std::fopen(entry.path().c_str(), "rb"));
#endif
if (std::fread(&readbuf[0], entrySize, 1, fh.get())) {
readbuf[entrySize + 1] = readbuf[entrySize] = 0; // null terminate
CefString val;
val.FromString16(static_cast<const char16_t*>(static_cast<const void*>(readbuf.data())));
auto sKey = entry.path().filename().native();
#if defined(OS_WIN)
// put the fucking colon back in it
const size_t loc = sKey.find(L'#', 0);
if (loc != std::wstring::npos) {
sKey.replace(loc, static_cast<size_t>(1), L":");
}
#endif
storage.emplace(sKey, CefV8Value::CreateString(val));
}
} while (FindNextFile(hFind, &w32fd));
FindClose(hFind);
}
}
delete[] readbuf;
}
std::wstring FCHostPersistentStorage::get_filename(const CefString& key) const
fs::path FCHostPersistentStorage::get_filename(const CefString& key) const
{
return path + L"\\" + key.c_str();
#if defined (OS_WIN)
std::wstring sKey = key.ToWString();
// some fool decided to use a fucking colon as a key separator for SC V3 saves...can't have that in a filename on windows...
const size_t loc = sKey.find(L':', 0);
if (loc != std::wstring::npos) {
sKey.replace(loc, static_cast<size_t>(1), L"#");
}
return path / sKey;
#else
return path / key.ToString();
#endif
}
void FCHostPersistentStorage::ensure_folder_exists() const
{
// ignore returned errors
CreateDirectory(path.c_str(), NULL);
fs::create_directories(path);
}
#else
#error "Platform-specific persistent storage implementation required."
#endif
#pragma once
#include "include/cef_app.h" // probably excessive
#include <filesystem>
#include <map>
#include <string>
......@@ -30,8 +32,9 @@ protected:
// memory-backed, disk-persistent local storage
class FCHostPersistentStorage : public FCHostSessionStorage
{
using base = FCHostSessionStorage;
public:
FCHostPersistentStorage(const std::wstring& _path) : path(_path) { ensure_folder_exists(); load(); };
FCHostPersistentStorage(const std::filesystem::path& _path);
virtual void set(const CefString& key, CefRefPtr<CefV8Value> val) override;
virtual bool remove(const CefString& key) override;
......@@ -40,7 +43,7 @@ public:
private:
void load();
void ensure_folder_exists() const;
std::wstring get_filename(const CefString& key) const;
std::filesystem::path get_filename(const CefString& key) const;
std::wstring path;
std::filesystem::path path;
};
......@@ -24,7 +24,7 @@ static void AttachStorageFunctions(CefRefPtr<CefV8Value> object, CefRefPtr<CefV8
REGJSFUNC("clear");
}
void FCHostStorageRegister(const CefString& persistPath, CefRefPtr<CefV8Value> object) {
void FCHostStorageRegister(const std::filesystem::path& persistPath, CefRefPtr<CefV8Value> object) {
// New context, reset everything (don't try to run more than one app at once!)
if (persist) persist.reset(NULL);
if (session) session.reset(NULL);
......@@ -33,12 +33,12 @@ void FCHostStorageRegister(const CefString& persistPath, CefRefPtr<CefV8Value> o
session = std::make_unique<FCHostSessionStorage>();
CefRefPtr<CefV8Handler> sess_handler = new FCHostStorageHandler(false);
CefRefPtr<CefV8Value> obj_sess = CefV8Value::CreateObject(NULL, NULL);
CefRefPtr<CefV8Value> obj_sess = CefV8Value::CreateObject(nullptr, nullptr);
object->SetValue("FCHostSession", obj_sess, V8_PROPERTY_ATTRIBUTE_NONE);
AttachStorageFunctions(obj_sess, sess_handler);
CefRefPtr<CefV8Handler> pers_handler = new FCHostStorageHandler(true);
CefRefPtr<CefV8Value> obj_pers = CefV8Value::CreateObject(NULL, NULL);
CefRefPtr<CefV8Value> obj_pers = CefV8Value::CreateObject(nullptr, nullptr);
object->SetValue("FCHostPersistent", obj_pers, V8_PROPERTY_ATTRIBUTE_NONE);
AttachStorageFunctions(obj_pers, pers_handler);
}
......@@ -52,7 +52,7 @@ bool FCHostStorageHandler::Execute(const CefString& name, CefRefPtr<CefV8Value>
if (name == "size") {
// no arguments
retval = CefV8Value::CreateInt(static_cast<int32>(storage->size()));
retval = CefV8Value::CreateInt(static_cast<int32_t>(storage->size()));
return true;
}
else if (name == "keys") {
......