├── .gitignore ├── .gitmodules ├── .travis.yml ├── .ycm_extra_conf.py ├── CMakeLists.txt ├── LICENSE.md ├── README.md ├── Tests ├── CMakeLists.txt ├── Controls.Button.CheckAndRadio │ └── Controls.Button.CheckAndRadio.cpp ├── Controls.Button.EnableDisable │ └── Controls.Button.EnableDisable.cpp ├── Controls.DatePicker.DateAndLocale │ └── Controls.DatePicker.DateAndLocale.cpp ├── Controls.ListBox.NameSelector │ └── Controls.ListBox.NameSelector.cpp ├── Controls.ListBox.VirtualMode │ └── Controls.ListBox.VirtualMode.cpp ├── Controls.Scroll.ColorPicker │ └── Controls.Scroll.ColorPicker.cpp └── HelloWorld │ ├── HelloWorld.cpp │ └── HelloWorld.h └── X11Cairo ├── GraphicsElement ├── CairoPangoIncludes.h ├── GuiGraphicsX11Cairo.cpp ├── GuiGraphicsX11Cairo.h ├── Renderers │ ├── CairoHelpers.cpp │ ├── CairoHelpers.h │ ├── GuiGradientBackgroundElementRenderer.cpp │ ├── GuiGradientBackgroundElementRenderer.h │ ├── GuiPolygonElementRenderer.cpp │ ├── GuiPolygonElementRenderer.h │ ├── GuiSolidBackgroundElementRenderer.cpp │ ├── GuiSolidBackgroundElementRenderer.h │ ├── GuiSolidBorderElementRenderer.cpp │ ├── GuiSolidBorderElementRenderer.h │ ├── GuiSolidLabelElementRenderer.cpp │ ├── GuiSolidLabelElementRenderer.h │ └── X11CairoRenderers.h ├── X11CairoRenderTarget.cpp ├── X11CairoRenderTarget.h ├── X11CairoResourceManager.cpp └── X11CairoResourceManager.h ├── NativeWindow ├── Common │ ├── ServicesImpl │ │ ├── PosixAsyncService.cpp │ │ └── PosixAsyncService.h │ └── X11Window.h └── Xlib │ ├── ServicesImpl │ ├── XlibNativeCallbackService.cpp │ ├── XlibNativeCallbackService.h │ ├── XlibNativeInputService.cpp │ ├── XlibNativeInputService.h │ ├── XlibNativeResourceService.cpp │ ├── XlibNativeResourceService.h │ ├── XlibNativeScreenService.cpp │ ├── XlibNativeScreenService.h │ ├── XlibNativeWindowService.cpp │ └── XlibNativeWindowService.h │ ├── XlibAtoms.cpp │ ├── XlibAtoms.h │ ├── XlibCommon.cpp │ ├── XlibCommon.h │ ├── XlibIncludes.h │ ├── XlibNativeController.cpp │ ├── XlibNativeController.h │ ├── XlibScreen.cpp │ ├── XlibScreen.h │ ├── XlibWindow.cpp │ ├── XlibWindow.h │ ├── XlibXRecordMouseHookHelper.cpp │ └── XlibXRecordMouseHookHelper.h ├── X11CairoIncludes.h ├── X11CairoSetup.cpp └── X11CairoSetup.h /.gitignore: -------------------------------------------------------------------------------- 1 | Tests/.idea 2 | .idea 3 | *.pyc 4 | *.swp 5 | *.DS_Store 6 | *.o 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "GacLib"] 2 | path = GacLib 3 | url = https://github.com/vczh-libraries/Release 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | compiler: 4 | - clang 5 | - gcc 6 | 7 | before_install: 8 | - if [ "$CXX" == "g++" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi; 9 | - sudo apt-get update -qq; 10 | - sudo apt-get install -qq libcairo2-dev libx11-dev libxtst-dev libpango1.0-dev cmake; 11 | - mkdir ../xgac-build 12 | 13 | 14 | install: 15 | - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.9; export CC="gcc-4.9"; export CXX="g++-4.9"; fi; 16 | 17 | 18 | script: 19 | - cd ../xgac-build 20 | - cmake ../XGac 21 | - make 22 | 23 | -------------------------------------------------------------------------------- /.ycm_extra_conf.py: -------------------------------------------------------------------------------- 1 | # Modified from Standard YCM Config 2 | 3 | import os 4 | import ycm_core 5 | 6 | flags = [ 7 | '-Wall', 8 | '-Wextra', 9 | '-Wno-long-long', 10 | '-Wno-variadic-macros', 11 | '-fexceptions', 12 | '-Wno-unused-variable', 13 | '-Wno-unused-parameter', 14 | '-Wno-unknown-pragmas', 15 | '-Wno-overloaded-virtual', 16 | '-std=c++11', 17 | '-x', 18 | 'c++', 19 | '-isystem', 20 | '/usr/include', 21 | '-isystem', 22 | '/usr/local/include', 23 | '-isystem', 24 | '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1', 25 | '-isystem', 26 | '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include', 27 | '-isystem', 28 | '/opt/X11/include', 29 | '-isystem', 30 | '/usr/local/include/pango-1.0', 31 | '-isystem', 32 | '/usr/local/include/glib-2.0', 33 | '-isystem', 34 | '/usr/local/lib/glib-2.0/include', 35 | '-isystem', 36 | '/usr/include/cairo', 37 | '-isystem', 38 | '/usr/include/pango-1.0', 39 | '-isystem', 40 | '/usr/include/glib-2.0', 41 | '-isystem', 42 | '/usr/lib/glib-2.0/include', 43 | '-isystem', 44 | '/usr/include/cairo', 45 | '-I', 46 | './GacLib/Import', 47 | '-I', 48 | './X11Cairo', 49 | ] 50 | 51 | 52 | # Set this to the absolute path to the folder (NOT the file!) containing the 53 | # compile_commands.json file to use that instead of 'flags'. See here for 54 | # more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html 55 | # 56 | # You can get CMake to generate this file for you by adding: 57 | # set( CMAKE_EXPORT_COMPILE_COMMANDS 1 ) 58 | # to your CMakeLists.txt file. 59 | # 60 | # Most projects will NOT need to set this to anything; you can just change the 61 | # 'flags' list of compilation flags. Notice that YCM itself uses that approach. 62 | compilation_database_folder = '' 63 | 64 | if os.path.exists( compilation_database_folder ): 65 | database = ycm_core.CompilationDatabase( compilation_database_folder ) 66 | else: 67 | database = None 68 | 69 | SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ] 70 | 71 | def DirectoryOfThisScript(): 72 | return os.path.dirname( os.path.abspath( __file__ ) ) 73 | 74 | 75 | def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): 76 | if not working_directory: 77 | return list( flags ) 78 | new_flags = [] 79 | make_next_absolute = False 80 | path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] 81 | for flag in flags: 82 | new_flag = flag 83 | 84 | if make_next_absolute: 85 | make_next_absolute = False 86 | if not flag.startswith( '/' ): 87 | new_flag = os.path.join( working_directory, flag ) 88 | 89 | for path_flag in path_flags: 90 | if flag == path_flag: 91 | make_next_absolute = True 92 | break 93 | 94 | if flag.startswith( path_flag ): 95 | path = flag[ len( path_flag ): ] 96 | new_flag = path_flag + os.path.join( working_directory, path ) 97 | break 98 | 99 | if new_flag: 100 | new_flags.append( new_flag ) 101 | return new_flags 102 | 103 | 104 | def IsHeaderFile( filename ): 105 | extension = os.path.splitext( filename )[ 1 ] 106 | return extension in [ '.h', '.hxx', '.hpp', '.hh' ] 107 | 108 | 109 | def GetCompilationInfoForFile( filename ): 110 | # The compilation_commands.json file generated by CMake does not have entries 111 | # for header files. So we do our best by asking the db for flags for a 112 | # corresponding source file, if any. If one exists, the flags for that file 113 | # should be good enough. 114 | if IsHeaderFile( filename ): 115 | basename = os.path.splitext( filename )[ 0 ] 116 | for extension in SOURCE_EXTENSIONS: 117 | replacement_file = basename + extension 118 | if os.path.exists( replacement_file ): 119 | compilation_info = database.GetCompilationInfoForFile( 120 | replacement_file ) 121 | if compilation_info.compiler_flags_: 122 | return compilation_info 123 | return None 124 | return database.GetCompilationInfoForFile( filename ) 125 | 126 | 127 | def FlagsForFile( filename, **kwargs ): 128 | if database: 129 | # Bear in mind that compilation_info.compiler_flags_ does NOT return a 130 | # python list, but a "list-like" StringVec object 131 | compilation_info = GetCompilationInfoForFile( filename ) 132 | if not compilation_info: 133 | return None 134 | 135 | final_flags = MakeRelativePathsInFlagsAbsolute( 136 | compilation_info.compiler_flags_, 137 | compilation_info.compiler_working_dir_ ) 138 | 139 | else: 140 | relative_to = DirectoryOfThisScript() 141 | final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) 142 | 143 | return { 144 | 'flags': final_flags, 145 | 'do_cache': True 146 | } 147 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.4) 2 | project(XGac) 3 | find_package(PkgConfig REQUIRED) 4 | 5 | add_subdirectory(Tests) 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | See https://github.com/vczh-libraries/License/blob/master/README.md for the detail. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XGac: a X11/Cairo/Pango port of GacLib 2 | 3 | [![Build Status](https://travis-ci.org/vczh-libraries/XGac.svg?branch=master)](https://travis-ci.org/vczh-libraries/XGac) 4 | 5 | ## License 6 | 7 | **Read the [LICENSE](https://github.com/vczh-libraries/XGac/blob/master/LICENSE.md) first.** 8 | 9 | Rendering components of XGac depends on [Cairo](http://cairographics.org/) and [Pango](http://www.pango.org/), which are licensed under the GNU Lesser General Public License (LGPL). Please follow the requirements of these libraries when distributing your application. 10 | 11 | ## Status 12 | 13 | XGac is still in early development stage. It is definitely not ready for production usage. 14 | 15 | Pull requests and issue reports are welcomed. 16 | 17 | ## Dependencies 18 | 19 | - Xlib (libx11) with extensions 20 | - Cairo and its Xlib backend 21 | - Pango and its Cairo backend 22 | 23 | ## Requirements 24 | 25 | Gaclib uses a global mouse hook to handle pop-up windows. To implement these hook function, XGac requires XRecord extension enabled on X Server. 26 | 27 | XDBE (Double Buffer Extension) is used for double buffering. Without this extension XGac will still work but without double buffering. 28 | 29 | ## Build instructions 30 | 31 | Included CMake makefiles can be used to build the examples on Linux/OSX systems. 32 | 33 | Instructions on how to use XGac in production will be given once XGac reaches stable. 34 | 35 | ## TODOs 36 | 37 | - Window related functions 38 | - Bitmap/Image handling 39 | - TextBox/RichTextEditor renderer 40 | - Multi-monitor handling (Xinerama/Xrandr) 41 | - Cairo-GL based, hardware accelerated backend 42 | - Input method support 43 | 44 | ## Known issues 45 | 46 | - Double buffering causes problem while resizing windows 47 | - Pop-up windows flash on left-top under XQuartz before showing up on right position 48 | - Pop-up windows would not hide in Window Manager's list 49 | - Pop-up windows would not keep on top of stack 50 | -------------------------------------------------------------------------------- /Tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.7) 2 | project(XGacTests) 3 | find_package(PkgConfig REQUIRED) 4 | include_directories("../GacLib/Import") 5 | include_directories("../X11Cairo") 6 | 7 | pkg_check_modules(DEPENDENCIES REQUIRED x11 cairo cairo-xlib pango pangocairo recordproto xtst) 8 | 9 | include_directories(${DEPENDENCIES_INCLUDE_DIRS}) 10 | link_directories(${DEPENDENCIES_LIBRARY_DIRS}) 11 | 12 | set(OS_LIBRARIES "pthread") 13 | if(APPLE) 14 | link_directories("/opt/X11/lib") 15 | link_directories("/usr/local/Cellar/gettext/0.19.6/lib") 16 | include_directories("/opt/X11/include") 17 | find_library(COREFOUNDATION_LIBRARIES CoreFoundation) 18 | set(OS_LIBRARIES ${COREFOUNDATION_LIBRARIES} ${OS_LIBRARIES}) 19 | add_definitions(-D__APPLE__) 20 | endif() 21 | 22 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-missing-declarations") 23 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") 24 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") 25 | 26 | add_definitions(-DGAC_X11_DOUBLEBUFFER) 27 | 28 | set(GACUI_COMMON_FILES "../GacLib/Import/Vlpp.cpp" "../GacLib/Import/VlppWorkflow.cpp" "../GacLib/Import/GacUI.cpp" "../GacLib/Import/GacUIReflection.cpp") 29 | 30 | set(GACUI_X11CAIRO_COMMON_FILES 31 | "../X11Cairo/X11CairoSetup.cpp" 32 | "../X11Cairo/GraphicsElement/GuiGraphicsX11Cairo.cpp" 33 | "../X11Cairo/GraphicsElement/X11CairoRenderTarget.cpp" 34 | "../X11Cairo/GraphicsElement/X11CairoResourceManager.cpp" 35 | "../X11Cairo/GraphicsElement/Renderers/CairoHelpers.cpp" 36 | "../X11Cairo/GraphicsElement/Renderers/GuiSolidBackgroundElementRenderer.cpp" 37 | "../X11Cairo/GraphicsElement/Renderers/GuiSolidLabelElementRenderer.cpp" 38 | "../X11Cairo/GraphicsElement/Renderers/GuiSolidBorderElementRenderer.cpp" 39 | "../X11Cairo/GraphicsElement/Renderers/GuiGradientBackgroundElementRenderer.cpp" 40 | "../X11Cairo/GraphicsElement/Renderers/GuiPolygonElementRenderer.cpp" 41 | "../X11Cairo/NativeWindow/Common/ServicesImpl/PosixAsyncService.cpp" 42 | ) 43 | 44 | set(GACUI_X11CAIRO_XLIB_FILES 45 | "../X11Cairo/NativeWindow/Xlib/XlibNativeController.cpp" 46 | "../X11Cairo/NativeWindow/Xlib/XlibWindow.cpp" 47 | "../X11Cairo/NativeWindow/Xlib/XlibCommon.cpp" 48 | "../X11Cairo/NativeWindow/Xlib/XlibAtoms.cpp" 49 | "../X11Cairo/NativeWindow/Xlib/XlibScreen.cpp" 50 | "../X11Cairo/NativeWindow/Xlib/XlibXRecordMouseHookHelper.cpp" 51 | "../X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeWindowService.cpp" 52 | "../X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeScreenService.cpp" 53 | "../X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeInputService.cpp" 54 | "../X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeCallbackService.cpp" 55 | "../X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeResourceService.cpp" 56 | ) 57 | 58 | add_library(GacUI STATIC ${GACUI_COMMON_FILES}) 59 | add_library(GacUIX11Cairo STATIC ${GACUI_X11CAIRO_COMMON_FILES} ${GACUI_X11CAIRO_XLIB_FILES}) 60 | 61 | set(DEPENDENCIES_LIBRARIES ${DEPENDENCIES_LIBRARIES} ${OS_LIBRARIES}) 62 | set(GACUI_LIBRARIES "GacUI" "GacUIX11Cairo") 63 | 64 | set(HELLOWORLD_SOURCE_FILES "HelloWorld/HelloWorld.cpp") 65 | add_executable(HelloWorld ${HELLOWORLD_SOURCE_FILES}) 66 | target_link_libraries(HelloWorld ${GACUI_LIBRARIES} ${DEPENDENCIES_LIBRARIES}) 67 | 68 | set(CONTROLS_BUTTON_ENABLEDISABLE_SOURCE_FILES "./Controls.Button.EnableDisable/Controls.Button.EnableDisable.cpp") 69 | add_executable(Controls.Button.EnableDisable ${CONTROLS_BUTTON_ENABLEDISABLE_SOURCE_FILES}) 70 | target_link_libraries(Controls.Button.EnableDisable ${GACUI_LIBRARIES} ${DEPENDENCIES_LIBRARIES}) 71 | 72 | set(CONTROLS_BUTTON_CHECKANDRADIO_SOURCE_FILES "./Controls.Button.CheckAndRadio/Controls.Button.CheckAndRadio.cpp") 73 | add_executable(Controls.Button.CheckAndRadio ${CONTROLS_BUTTON_CHECKANDRADIO_SOURCE_FILES}) 74 | target_link_libraries(Controls.Button.CheckAndRadio ${GACUI_LIBRARIES} ${DEPENDENCIES_LIBRARIES}) 75 | 76 | set(CONTROLS_LISTBOX_VIRTUALMODE_SOURCE_FILES "./Controls.ListBox.VirtualMode/Controls.ListBox.VirtualMode.cpp") 77 | add_executable(Controls.ListBox.VirtualMode ${CONTROLS_LISTBOX_VIRTUALMODE_SOURCE_FILES}) 78 | target_link_libraries(Controls.ListBox.VirtualMode ${GACUI_LIBRARIES} ${DEPENDENCIES_LIBRARIES}) 79 | 80 | set(CONTROLS_LISTBOX_NAMESELECTOR_SOURCE_FILES "./Controls.ListBox.NameSelector/Controls.ListBox.NameSelector.cpp") 81 | add_executable(Controls.ListBox.NameSelector ${CONTROLS_LISTBOX_NAMESELECTOR_SOURCE_FILES}) 82 | target_link_libraries(Controls.ListBox.NameSelector ${GACUI_LIBRARIES} ${DEPENDENCIES_LIBRARIES}) 83 | 84 | set(CONTROLS_SCROLL_COLORPICKER_SOURCE_FILES "./Controls.Scroll.ColorPicker/Controls.Scroll.ColorPicker.cpp") 85 | add_executable(Controls.Scroll.ColorPicker ${CONTROLS_SCROLL_COLORPICKER_SOURCE_FILES}) 86 | target_link_libraries(Controls.Scroll.ColorPicker ${GACUI_LIBRARIES} ${DEPENDENCIES_LIBRARIES}) 87 | 88 | set(CONTROLS_DATEPICKER_DATEANDLOCALE_SOURCE_FILES "./Controls.DatePicker.DateAndLocale/Controls.DatePicker.DateAndLocale.cpp") 89 | add_executable(Controls.DatePicker.DateAndLocale ${CONTROLS_DATEPICKER_DATEANDLOCALE_SOURCE_FILES}) 90 | target_link_libraries(Controls.DatePicker.DateAndLocale ${GACUI_LIBRARIES} ${DEPENDENCIES_LIBRARIES}) 91 | 92 | -------------------------------------------------------------------------------- /Tests/Controls.Button.CheckAndRadio/Controls.Button.CheckAndRadio.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "X11CairoIncludes.h" 3 | 4 | using namespace vl; 5 | using namespace vl::presentation; 6 | using namespace vl::presentation::theme; 7 | using namespace vl::presentation::controls; 8 | using namespace vl::presentation::compositions; 9 | 10 | int main() 11 | { 12 | SetupX11CairoRenderer(); 13 | return 0; 14 | } 15 | 16 | class CheckAndRadioWindow : public GuiWindow 17 | { 18 | private: 19 | 20 | GuiCellComposition* CreateButtons(const WString& groupName, const WString& buttonName, bool checkBox, GuiSelectableButton::GroupController* groupController) 21 | { 22 | GuiCellComposition* cell=new GuiCellComposition; 23 | 24 | GuiControl* groupBox=g::NewGroupBox(); 25 | groupBox->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); 26 | groupBox->GetContainerComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); 27 | // all child controls should at least 10 pixels away from the group box 28 | groupBox->GetContainerComposition()->SetInternalMargin(Margin(10, 10, 10, 10)); 29 | // dock the group box to fill the cell 30 | groupBox->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 31 | groupBox->SetText(groupName); 32 | // add the button to the cell 33 | cell->AddChild(groupBox->GetBoundsComposition()); 34 | 35 | // create a stack to layout the 3 buttons from top to bottom shown like a list 36 | GuiStackComposition* stack=new GuiStackComposition; 37 | stack->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); 38 | stack->SetDirection(GuiStackComposition::Vertical); 39 | stack->SetAlignmentToParent(Margin(0, 0, 0, 0)); 40 | stack->SetPadding(6); 41 | groupBox->GetContainerComposition()->AddChild(stack); 42 | 43 | // create buttons 44 | for(int i=0;i<3;i++) 45 | { 46 | GuiSelectableButton* button=checkBox?g::NewCheckBox():g::NewRadioButton(); 47 | button->SetText(buttonName+itow(i+1)); 48 | button->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 49 | if(groupController) 50 | { 51 | button->SetGroupController(groupController); 52 | } 53 | 54 | GuiStackItemComposition* stackItem=new GuiStackItemComposition; 55 | stack->AddChild(stackItem); 56 | stackItem->AddChild(button->GetBoundsComposition()); 57 | } 58 | 59 | return cell; 60 | } 61 | public: 62 | CheckAndRadioWindow() 63 | :GuiWindow(GetCurrentTheme()->CreateWindowStyle()) 64 | { 65 | this->SetText(L"Controls.Button.CheckAndRadio"); 66 | // limit the size that the window should always show the whole content without cliping it 67 | this->GetContainerComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); 68 | 69 | // create a table to layout the 2 group boxes 70 | GuiTableComposition* table=new GuiTableComposition; 71 | // make the table to have 2 rows 72 | table->SetRowsAndColumns(1, 2); 73 | table->SetRowOption(0, GuiCellOption::MinSizeOption()); 74 | table->SetColumnOption(0, GuiCellOption::PercentageOption(0.5)); 75 | table->SetColumnOption(1, GuiCellOption::PercentageOption(0.5)); 76 | // dock the table to fill the window 77 | table->SetAlignmentToParent(Margin(4, 4, 4, 4)); 78 | table->SetCellPadding(6); 79 | // add the table to the window; 80 | this->GetContainerComposition()->AddChild(table); 81 | 82 | // add group box for check boxes 83 | { 84 | GuiCellComposition* cell=CreateButtons(L"Check Boxes", L"This is a check box ", true, 0); 85 | table->AddChild(cell); 86 | // this cell is the left cell 87 | cell->SetSite(0, 0, 1, 1); 88 | } 89 | 90 | // add group box for radio buttons 91 | { 92 | // create a group controller to group those radio buttons together 93 | // so that select a radio button will unselect the previous one automatically 94 | GuiSelectableButton::GroupController* groupController=new GuiSelectableButton::MutexGroupController; 95 | this->AddComponent(groupController); 96 | 97 | GuiCellComposition* cell=CreateButtons(L"Radio buttons", L"This is a radio button ", false, groupController); 98 | table->AddChild(cell); 99 | // this cell is the right cell 100 | cell->SetSite(0, 1, 1, 1); 101 | } 102 | 103 | // call this to calculate the size immediately if any indirect content in the table changes 104 | // so that the window can calcaulte its correct size before calling the MoveToScreenCenter() 105 | this->ForceCalculateSizeImmediately(); 106 | // move to the screen center 107 | this->MoveToScreenCenter(); 108 | } 109 | 110 | ~CheckAndRadioWindow() 111 | { 112 | } 113 | }; 114 | 115 | void GuiMain() 116 | { 117 | GuiWindow* window=new CheckAndRadioWindow(); 118 | GetApplication()->Run(window); 119 | delete window; 120 | } 121 | -------------------------------------------------------------------------------- /Tests/Controls.Button.EnableDisable/Controls.Button.EnableDisable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "X11CairoIncludes.h" 3 | 4 | using namespace vl; 5 | using namespace vl::presentation; 6 | using namespace vl::presentation::theme; 7 | using namespace vl::presentation::controls; 8 | using namespace vl::presentation::compositions; 9 | 10 | int main() 11 | { 12 | SetupX11CairoRenderer(); 13 | } 14 | 15 | class EnableDisableWindow : public GuiWindow 16 | { 17 | private: 18 | GuiButton* buttonTarget; 19 | GuiButton* buttonEnable; 20 | GuiButton* buttonDisable; 21 | 22 | void buttonEnable_OnClick(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 23 | { 24 | buttonTarget->SetEnabled(true); 25 | } 26 | 27 | void buttonDisable_OnClick(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 28 | { 29 | buttonTarget->SetEnabled(false); 30 | } 31 | public: 32 | EnableDisableWindow() 33 | :GuiWindow(GetCurrentTheme()->CreateWindowStyle()) 34 | { 35 | this->SetText(L"Controls.Button.EnableDisable"); 36 | // limit the size that the window should always show the whole content without cliping it 37 | this->GetContainerComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); 38 | 39 | // create a table to layout the 3 buttons 40 | GuiTableComposition* table=new GuiTableComposition; 41 | // make the table to have 2 rows 42 | table->SetRowsAndColumns(2, 2); 43 | table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); 44 | table->SetRowOption(1, GuiCellOption::PercentageOption(0.5)); 45 | table->SetColumnOption(0, GuiCellOption::PercentageOption(0.5)); 46 | table->SetColumnOption(1, GuiCellOption::PercentageOption(0.5)); 47 | // dock the table to fill the window 48 | table->SetAlignmentToParent(Margin(4, 4, 4, 4)); 49 | table->SetCellPadding(6); 50 | // add the table to the window; 51 | this->GetContainerComposition()->AddChild(table); 52 | 53 | // add the target button 54 | { 55 | GuiCellComposition* cell=new GuiCellComposition; 56 | table->AddChild(cell); 57 | // this cell is the top cell 58 | cell->SetSite(0, 0, 1, 2); 59 | 60 | buttonTarget=g::NewButton(); 61 | buttonTarget->SetText(L"Enable or disable me using the buttons below!"); 62 | // dock the button to fill the cell 63 | buttonTarget->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 64 | // add the button to the cell 65 | cell->AddChild(buttonTarget->GetBoundsComposition()); 66 | } 67 | 68 | // add the enable button 69 | { 70 | GuiCellComposition* cell=new GuiCellComposition; 71 | table->AddChild(cell); 72 | // this cell is the bottom left cell 73 | cell->SetSite(1, 0, 1, 1); 74 | 75 | buttonEnable=g::NewButton(); 76 | buttonEnable->SetText(L"Enable"); 77 | buttonEnable->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); 78 | buttonEnable->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 79 | buttonEnable->Clicked.AttachMethod(this, &EnableDisableWindow::buttonEnable_OnClick); 80 | cell->AddChild(buttonEnable->GetBoundsComposition()); 81 | } 82 | 83 | // add the disable button 84 | { 85 | GuiCellComposition* cell=new GuiCellComposition; 86 | table->AddChild(cell); 87 | // this cell is the bottom right cell 88 | cell->SetSite(1, 1, 1, 1); 89 | 90 | buttonDisable=g::NewButton(); 91 | buttonDisable->SetText(L"Disable"); 92 | buttonDisable->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); 93 | buttonDisable->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 94 | buttonDisable->Clicked.AttachMethod(this, &EnableDisableWindow::buttonDisable_OnClick); 95 | cell->AddChild(buttonDisable->GetBoundsComposition()); 96 | } 97 | 98 | // change the button font 99 | { 100 | FontProperties font; 101 | 102 | font=buttonTarget->GetFont(); 103 | font.size=20; 104 | buttonTarget->SetFont(font); 105 | buttonEnable->SetFont(font); 106 | buttonDisable->SetFont(font); 107 | } 108 | 109 | // call this to calculate the size immediately if any indirect content in the table changes 110 | // so that the window can calcaulte its correct size before calling the MoveToScreenCenter() 111 | this->ForceCalculateSizeImmediately(); 112 | // move to the screen center 113 | this->MoveToScreenCenter(); 114 | } 115 | 116 | ~EnableDisableWindow() 117 | { 118 | } 119 | }; 120 | 121 | void GuiMain() 122 | { 123 | GuiWindow* window=new EnableDisableWindow(); 124 | GetApplication()->Run(window); 125 | delete window; 126 | } 127 | -------------------------------------------------------------------------------- /Tests/Controls.DatePicker.DateAndLocale/Controls.DatePicker.DateAndLocale.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "X11CairoIncludes.h" 4 | 5 | using namespace vl; 6 | using namespace vl::presentation; 7 | using namespace vl::presentation::theme; 8 | using namespace vl::presentation::controls; 9 | using namespace vl::presentation::compositions; 10 | using namespace vl::collections; 11 | 12 | int main() 13 | { 14 | SetupX11CairoRenderer(); 15 | } 16 | 17 | /*********************************************************************** 18 | DatePickerWindow 19 | ***********************************************************************/ 20 | 21 | class DatePickerWindow : public GuiWindow 22 | { 23 | private: 24 | GuiLabel* labelLocale; 25 | GuiTextList* listLocales; 26 | GuiLabel* labelFormat; 27 | GuiTextList* listFormats; 28 | 29 | GuiLabel* labelDate; 30 | GuiDateComboBox* dateComboBox; 31 | GuiLabel* labelPicker; 32 | GuiDatePicker* datePicker; 33 | 34 | void FillLocales() 35 | { 36 | listLocales->GetItems().Clear(); 37 | List locales; 38 | Locale::Enumerate(locales); 39 | 40 | FOREACH(Locale, locale, locales) 41 | { 42 | listLocales->GetItems().Add(new list::TextItem(locale.GetName())); 43 | } 44 | CopyFrom( 45 | listLocales->GetItems(), 46 | From(locales) 47 | .Select([](const Locale& locale)->WString{return locale.GetName();}) 48 | .OrderBy([](const WString& a, const WString& b){return WString::Compare(a, b);}) 49 | .Select([](const WString& locale){return new list::TextItem(locale);}) 50 | ); 51 | listLocales->SetSelected(0, true); 52 | } 53 | 54 | void FillFormats(const Locale& locale) 55 | { 56 | List formats; 57 | locale.GetLongDateFormats(formats); 58 | locale.GetShortDateFormats(formats); 59 | 60 | CopyFrom( 61 | listFormats->GetItems(), 62 | From(formats) 63 | .Select([](const WString& format){return new list::TextItem(format);}) 64 | ); 65 | listFormats->SetSelected(0, true); 66 | } 67 | 68 | void listLocales_SelectionChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 69 | { 70 | if(listLocales->GetSelectedItems().Count()>0) 71 | { 72 | Locale locale(listLocales->GetItems().Get(listLocales->GetSelectedItems().Get(0))->GetText()); 73 | datePicker->SetDateLocale(locale); 74 | dateComboBox->GetDatePicker()->SetDateLocale(locale); 75 | FillFormats(locale); 76 | } 77 | } 78 | 79 | void listFormats_SelectionChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 80 | { 81 | if(listFormats->GetSelectedItems().Count()>0) 82 | { 83 | WString format=listFormats->GetItems().Get(listFormats->GetSelectedItems().Get(0))->GetText(); 84 | datePicker->SetDateFormat(format); 85 | dateComboBox->GetDatePicker()->SetDateFormat(format); 86 | } 87 | } 88 | 89 | void datePicker_TextChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 90 | { 91 | labelPicker->SetText(L"↓: "+datePicker->GetText()); 92 | 93 | /* equivalent code that can put in GuiDatePicker::DateChanged 94 | 95 | DateTime date=datePicker->GetDate(); 96 | Locale locale=datePicker->GetDateLocale(); 97 | WString format=datePicker->GetDateFormat(); 98 | WString dateText=locale.FormatDate(format, date); 99 | labelPicker->SetText(L"↓: "+dateText); 100 | */ 101 | } 102 | public: 103 | DatePickerWindow() 104 | :GuiWindow(GetCurrentTheme()->CreateWindowStyle()) 105 | { 106 | this->SetText(L"Controls.DatePicker.DateAndLocale"); 107 | 108 | GuiTableComposition* table=new GuiTableComposition; 109 | table->SetAlignmentToParent(Margin(0, 0, 0, 0)); 110 | table->SetCellPadding(5); 111 | table->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); 112 | 113 | table->SetRowsAndColumns(4, 3); 114 | table->SetRowOption(0, GuiCellOption::MinSizeOption()); 115 | table->SetRowOption(1, GuiCellOption::MinSizeOption()); 116 | table->SetRowOption(2, GuiCellOption::PercentageOption(1.0)); 117 | table->SetRowOption(3, GuiCellOption::MinSizeOption()); 118 | table->SetColumnOption(0, GuiCellOption::PercentageOption(0.5)); 119 | table->SetColumnOption(1, GuiCellOption::PercentageOption(0.5)); 120 | table->SetColumnOption(2, GuiCellOption::MinSizeOption()); 121 | 122 | { 123 | GuiCellComposition* cell=new GuiCellComposition; 124 | table->AddChild(cell); 125 | cell->SetSite(0, 0, 1, 1); 126 | 127 | labelLocale=g::NewLabel(); 128 | labelLocale->SetText(L"Select Locale:"); 129 | labelLocale->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 130 | cell->AddChild(labelLocale->GetBoundsComposition()); 131 | } 132 | { 133 | GuiCellComposition* cell=new GuiCellComposition; 134 | table->AddChild(cell); 135 | cell->SetSite(1, 0, 3, 1); 136 | 137 | listLocales=g::NewTextList(); 138 | listLocales->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 139 | listLocales->SelectionChanged.AttachMethod(this, &DatePickerWindow::listLocales_SelectionChanged); 140 | cell->AddChild(listLocales->GetBoundsComposition()); 141 | } 142 | 143 | { 144 | GuiCellComposition* cell=new GuiCellComposition; 145 | table->AddChild(cell); 146 | cell->SetSite(0, 1, 1, 1); 147 | 148 | labelFormat=g::NewLabel(); 149 | labelFormat->SetText(L"Select Format:"); 150 | labelFormat->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 151 | cell->AddChild(labelFormat->GetBoundsComposition()); 152 | } 153 | { 154 | GuiCellComposition* cell=new GuiCellComposition; 155 | table->AddChild(cell); 156 | cell->SetSite(1, 1, 3, 1); 157 | 158 | listFormats=g::NewTextList(); 159 | listFormats->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 160 | listFormats->SelectionChanged.AttachMethod(this, &DatePickerWindow::listFormats_SelectionChanged); 161 | cell->AddChild(listFormats->GetBoundsComposition()); 162 | } 163 | 164 | { 165 | GuiCellComposition* cell=new GuiCellComposition; 166 | table->AddChild(cell); 167 | cell->SetSite(0, 2, 1, 1); 168 | 169 | labelDate=g::NewLabel(); 170 | labelDate->SetText(L"Select Date:"); 171 | labelDate->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 172 | cell->AddChild(labelDate->GetBoundsComposition()); 173 | } 174 | { 175 | GuiCellComposition* cell=new GuiCellComposition; 176 | table->AddChild(cell); 177 | cell->SetSite(1, 2, 1, 1); 178 | 179 | dateComboBox=g::NewDateComboBox(); 180 | dateComboBox->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 181 | cell->AddChild(dateComboBox->GetBoundsComposition()); 182 | } 183 | 184 | { 185 | GuiCellComposition* cell=new GuiCellComposition; 186 | table->AddChild(cell); 187 | cell->SetSite(2, 2, 1, 1); 188 | 189 | labelPicker=g::NewLabel(); 190 | labelPicker->SetText(L"↓: "); 191 | labelPicker->GetBoundsComposition()->SetAlignmentToParent(Margin(0, -1, 0, 0)); 192 | cell->AddChild(labelPicker->GetBoundsComposition()); 193 | } 194 | { 195 | GuiCellComposition* cell=new GuiCellComposition; 196 | table->AddChild(cell); 197 | cell->SetSite(3, 2, 1, 1); 198 | 199 | datePicker=g::NewDatePicker(); 200 | datePicker->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 201 | datePicker->TextChanged.AttachMethod(this, &DatePickerWindow::datePicker_TextChanged); 202 | cell->AddChild(datePicker->GetBoundsComposition()); 203 | } 204 | FillLocales(); 205 | 206 | this->GetBoundsComposition()->AddChild(table); 207 | 208 | // set the preferred minimum client size 209 | this->GetBoundsComposition()->SetPreferredMinSize(Size(640, 320)); 210 | // call this to calculate the size immediately if any indirect content in the table changes 211 | // so that the window can calcaulte its correct size before calling the MoveToScreenCenter() 212 | this->ForceCalculateSizeImmediately(); 213 | // move to the screen center 214 | this->MoveToScreenCenter(); 215 | } 216 | }; 217 | 218 | /*********************************************************************** 219 | GuiMain 220 | ***********************************************************************/ 221 | 222 | void GuiMain() 223 | { 224 | GuiWindow* window=new DatePickerWindow; 225 | GetApplication()->Run(window); 226 | delete window; 227 | } 228 | -------------------------------------------------------------------------------- /Tests/Controls.ListBox.NameSelector/Controls.ListBox.NameSelector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "X11CairoIncludes.h" 3 | 4 | // for SortedList, CopyFrom and Select 5 | 6 | using namespace vl; 7 | using namespace vl::presentation; 8 | using namespace vl::presentation::theme; 9 | using namespace vl::presentation::controls; 10 | using namespace vl::presentation::compositions; 11 | using namespace vl::collections; 12 | 13 | int main() 14 | { 15 | SetupX11CairoRenderer(); 16 | } 17 | 18 | const wchar_t* DataSource[]= 19 | { 20 | L"Weierstrass", 21 | L"Cantor", 22 | L"Bernoulli", 23 | L"Fatou", 24 | L"Green", 25 | L"S.Lie", 26 | L"Euler", 27 | L"Gauss", 28 | L"Sturm", 29 | L"Riemann", 30 | L"Neumann", 31 | L"Caratheodory", 32 | L"Newton", 33 | L"Jordan", 34 | L"Laplace", 35 | L"Wiener", 36 | L"Thales", 37 | L"Maxwell", 38 | L"Riesz", 39 | L"Fourier", 40 | L"Noether", 41 | L"Kepler", 42 | L"Kolmogorov", 43 | L"Borel", 44 | L"Sobolev", 45 | L"Dirchlet", 46 | L"Lebesgue", 47 | L"Leibniz", 48 | L"Abel", 49 | L"Lagrange", 50 | L"Ramanujan", 51 | L"Ljapunov", 52 | L"Holder", 53 | L"Poisson", 54 | L"Nikodym", 55 | L"H.Hopf", 56 | L"Pythagoras", 57 | L"Baire", 58 | L"Haar", 59 | L"Fermat", 60 | L"Kronecker", 61 | L"E.Laudau", 62 | L"Markov", 63 | L"Wronski", 64 | L"Zermelo", 65 | L"Rouche", 66 | L"Taylor", 67 | L"Urysohn", 68 | L"Frechet", 69 | L"Picard", 70 | L"Schauder", 71 | L"Lipschiz", 72 | L"Liouville", 73 | L"Lindelof", 74 | L"de Moivre", 75 | L"Klein", 76 | L"Bessel", 77 | L"Euclid", 78 | L"Kummer", 79 | L"Ascoli", 80 | L"Chebyschev", 81 | L"Banach", 82 | L"Hilbert", 83 | L"Minkowski", 84 | L"Hamilton", 85 | L"Poincare", 86 | L"Peano", 87 | L"Zorn", 88 | }; 89 | 90 | class NameSelectorWindow : public GuiWindow 91 | { 92 | private: 93 | GuiTextList* listSource; 94 | GuiTextList* listDestination; 95 | GuiButton* buttonAdd; 96 | GuiButton* buttonRemove; 97 | 98 | static Ptr GetTextItem(GuiTextList* list, int index) 99 | { 100 | return list->GetItems()[index]; 101 | } 102 | 103 | static int CompareTextItem(Ptr a, Ptr b) 104 | { 105 | return wcscmp(a->GetText().Buffer(), b->GetText().Buffer()); 106 | } 107 | 108 | static int ReverseCompareInt(int a, int b) 109 | { 110 | return b-a; 111 | } 112 | 113 | void MoveNames(GuiTextList* from, GuiTextList* to) 114 | { 115 | CopyFrom( 116 | to->GetItems(), 117 | From(to->GetItems()) 118 | .Concat( 119 | From(from->GetSelectedItems()).Select(Curry(GetTextItem)(from)) 120 | ) 121 | .OrderBy(CompareTextItem) 122 | ); 123 | 124 | List selectedItems; 125 | CopyFrom( 126 | selectedItems, 127 | From(from->GetSelectedItems()) 128 | .OrderBy(ReverseCompareInt) 129 | ); 130 | FOREACH(int, index, selectedItems) 131 | { 132 | from->GetItems().RemoveAt(index); 133 | } 134 | } 135 | 136 | void LoadNames(GuiTextList* list) 137 | { 138 | // Use linq for C++ to create sorted TextItem(s) from DataSource 139 | CopyFrom( 140 | list->GetItems(), 141 | From(DataSource) 142 | .OrderBy(wcscmp) 143 | .Select([](const wchar_t* name){return new list::TextItem(name);}) 144 | ); 145 | } 146 | 147 | void buttonAdd_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 148 | { 149 | MoveNames(listSource, listDestination); 150 | } 151 | 152 | void buttonRemove_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 153 | { 154 | MoveNames(listDestination, listSource); 155 | } 156 | 157 | void listSource_SelectionChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 158 | { 159 | buttonAdd->SetEnabled(listSource->GetSelectedItems().Count()>0); 160 | } 161 | 162 | void listDestination_SelectionChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 163 | { 164 | buttonRemove->SetEnabled(listDestination->GetSelectedItems().Count()>0); 165 | } 166 | public: 167 | NameSelectorWindow() 168 | :GuiWindow(GetCurrentTheme()->CreateWindowStyle()) 169 | { 170 | this->SetText(L"Controls.ListBox.NameSelector"); 171 | 172 | GuiTableComposition* table=new GuiTableComposition; 173 | table->SetRowsAndColumns(5, 3); 174 | table->SetCellPadding(3); 175 | table->SetAlignmentToParent(Margin(0, 0, 0, 0)); 176 | 177 | table->SetRowOption(0, GuiCellOption::PercentageOption(0.5)); 178 | table->SetRowOption(1, GuiCellOption::MinSizeOption()); 179 | table->SetRowOption(2, GuiCellOption::AbsoluteOption(64)); 180 | table->SetRowOption(3, GuiCellOption::MinSizeOption()); 181 | table->SetRowOption(4, GuiCellOption::PercentageOption(0.5)); 182 | 183 | table->SetColumnOption(0, GuiCellOption::PercentageOption(0.5)); 184 | table->SetColumnOption(1, GuiCellOption::MinSizeOption()); 185 | table->SetColumnOption(2, GuiCellOption::PercentageOption(0.5)); 186 | 187 | this->GetContainerComposition()->AddChild(table); 188 | 189 | { 190 | GuiCellComposition* cell=new GuiCellComposition; 191 | table->AddChild(cell); 192 | cell->SetSite(0, 0, 5, 1); 193 | 194 | listSource=g::NewTextList(); 195 | listSource->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 196 | // make listSource's horizontal scroll bar disappeared when it is not needed. 197 | listSource->SetHorizontalAlwaysVisible(false); 198 | listSource->SetMultiSelect(true); 199 | listSource->SelectionChanged.AttachMethod(this, &NameSelectorWindow::listSource_SelectionChanged); 200 | cell->AddChild(listSource->GetBoundsComposition()); 201 | } 202 | { 203 | GuiCellComposition* cell=new GuiCellComposition; 204 | table->AddChild(cell); 205 | cell->SetSite(0, 2, 5, 1); 206 | 207 | listDestination=g::NewTextList(); 208 | listDestination->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 209 | // make listSource's horizontal scroll bar disappeared when it is not needed. 210 | listDestination->SetHorizontalAlwaysVisible(false); 211 | listDestination->SetMultiSelect(true); 212 | listDestination->SelectionChanged.AttachMethod(this, &NameSelectorWindow::listDestination_SelectionChanged); 213 | cell->AddChild(listDestination->GetBoundsComposition()); 214 | } 215 | { 216 | GuiCellComposition* cell=new GuiCellComposition; 217 | table->AddChild(cell); 218 | cell->SetSite(1, 1, 1, 1); 219 | 220 | buttonAdd=g::NewButton(); 221 | buttonAdd->SetText(L">>"); 222 | buttonAdd->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 223 | buttonAdd->GetBoundsComposition()->SetPreferredMinSize(Size(32, 32)); 224 | buttonAdd->Clicked.AttachMethod(this, &NameSelectorWindow::buttonAdd_Clicked); 225 | buttonAdd->SetEnabled(false); 226 | cell->AddChild(buttonAdd->GetBoundsComposition()); 227 | } 228 | { 229 | GuiCellComposition* cell=new GuiCellComposition; 230 | table->AddChild(cell); 231 | cell->SetSite(3, 1, 1, 1); 232 | 233 | buttonRemove=g::NewButton(); 234 | buttonRemove->SetText(L"<<"); 235 | buttonRemove->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 236 | buttonRemove->GetBoundsComposition()->SetPreferredMinSize(Size(32, 32)); 237 | buttonRemove->Clicked.AttachMethod(this, &NameSelectorWindow::buttonRemove_Clicked); 238 | buttonRemove->SetEnabled(false); 239 | cell->AddChild(buttonRemove->GetBoundsComposition()); 240 | } 241 | 242 | // Add names into listSource 243 | LoadNames(listSource); 244 | 245 | // set the preferred minimum client size 246 | this->GetBoundsComposition()->SetPreferredMinSize(Size(640, 480)); 247 | // call this to calculate the size immediately if any indirect content in the table changes 248 | // so that the window can calcaulte its correct size before calling the MoveToScreenCenter() 249 | this->ForceCalculateSizeImmediately(); 250 | // move to the screen center 251 | this->MoveToScreenCenter(); 252 | } 253 | }; 254 | 255 | void GuiMain() 256 | { 257 | GuiWindow* window=new NameSelectorWindow; 258 | GetApplication()->Run(window); 259 | delete window; 260 | } 261 | -------------------------------------------------------------------------------- /Tests/Controls.ListBox.VirtualMode/Controls.ListBox.VirtualMode.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "X11CairoIncludes.h" 3 | 4 | // for SortedList, CopyFrom and Select 5 | using namespace vl; 6 | using namespace vl::presentation; 7 | using namespace vl::presentation::theme; 8 | using namespace vl::presentation::controls; 9 | using namespace vl::presentation::compositions; 10 | using namespace vl::collections; 11 | 12 | int main() 13 | { 14 | SetupX11CairoRenderer(); 15 | } 16 | 17 | /*********************************************************************** 18 | DataSource 19 | ***********************************************************************/ 20 | 21 | class DataSource : public list::ItemProviderBase, private list::TextItemStyleProvider::ITextItemView 22 | { 23 | protected: 24 | int count; 25 | public: 26 | DataSource() 27 | :count(100000) 28 | { 29 | } 30 | 31 | void SetCount(int newCount) 32 | { 33 | if(0<=newCount) 34 | { 35 | int oldCount=count; 36 | count=newCount; 37 | 38 | // this->InvokeOnItemModified(affected-items-start, affected-items-count, new-items-count); 39 | // this function notifies the list control to update it's content and scroll bars 40 | if(oldCountInvokeOnItemModified(oldCount, 0, newCount-oldCount); 44 | } 45 | else if(oldCount>newCount) 46 | { 47 | // delete 48 | this->InvokeOnItemModified(newCount, oldCount-newCount, 0); 49 | } 50 | } 51 | } 52 | 53 | // GuiListControl::IItemProvider 54 | 55 | vint Count() 56 | { 57 | return count; 58 | } 59 | 60 | IDescriptable* RequestView(const WString& identifier) 61 | { 62 | if(identifier==list::TextItemStyleProvider::ITextItemView::Identifier) 63 | { 64 | return this; 65 | } 66 | else if(identifier==GuiListControl::IItemPrimaryTextView::Identifier) 67 | { 68 | return this; 69 | } 70 | else 71 | { 72 | return 0; 73 | } 74 | } 75 | 76 | void ReleaseView(IDescriptable* view) 77 | { 78 | } 79 | 80 | // list::TextItemStyleProvider::ITextItemView 81 | 82 | WString GetText(vint itemIndex) 83 | { 84 | return L"Item "+itow(itemIndex+1); 85 | } 86 | 87 | bool GetChecked(vint itemIndex) 88 | { 89 | // DataSource don't support check state 90 | return false; 91 | } 92 | 93 | void SetCheckedSilently(vint itemIndex, bool value) 94 | { 95 | // DataSource don't support check state 96 | } 97 | 98 | // GuiListControl::IItemPrimaryTextView 99 | 100 | WString GetPrimaryTextViewText(vint itemIndex) 101 | { 102 | return GetText(itemIndex); 103 | } 104 | 105 | bool ContainsPrimaryText(vint itemIndex) 106 | { 107 | return true; 108 | } 109 | }; 110 | 111 | /*********************************************************************** 112 | VirtualModeWindow 113 | ***********************************************************************/ 114 | 115 | class VirtualModeWindow : public GuiWindow 116 | { 117 | private: 118 | GuiVirtualTextList* listBox; 119 | GuiButton* buttonIncrease; 120 | GuiButton* buttonDecrease; 121 | DataSource* dataSource; 122 | 123 | void buttonIncrease_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 124 | { 125 | dataSource->SetCount(dataSource->Count()+100000); 126 | } 127 | 128 | void buttonDecrease_Clicked(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 129 | { 130 | dataSource->SetCount(dataSource->Count()-100000); 131 | } 132 | public: 133 | VirtualModeWindow() 134 | :GuiWindow(GetCurrentTheme()->CreateWindowStyle()) 135 | { 136 | this->SetText(L"Controls.ListBox.VirtualMode"); 137 | 138 | GuiTableComposition* table=new GuiTableComposition; 139 | table->SetRowsAndColumns(3, 2); 140 | table->SetCellPadding(3); 141 | table->SetAlignmentToParent(Margin(0, 0, 0, 0)); 142 | 143 | table->SetRowOption(0, GuiCellOption::MinSizeOption()); 144 | table->SetRowOption(1, GuiCellOption::MinSizeOption()); 145 | table->SetRowOption(2, GuiCellOption::PercentageOption(1.0)); 146 | 147 | table->SetColumnOption(0, GuiCellOption::PercentageOption(1.0)); 148 | table->SetColumnOption(1, GuiCellOption::MinSizeOption()); 149 | 150 | this->GetContainerComposition()->AddChild(table); 151 | 152 | { 153 | GuiCellComposition* cell=new GuiCellComposition; 154 | table->AddChild(cell); 155 | cell->SetSite(0, 0, 3, 1); 156 | 157 | dataSource=new DataSource; 158 | listBox=new GuiVirtualTextList(GetCurrentTheme()->CreateTextListStyle(), GetCurrentTheme()->CreateTextListItemStyle(), dataSource); 159 | listBox->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 160 | listBox->SetHorizontalAlwaysVisible(false); 161 | cell->AddChild(listBox->GetBoundsComposition()); 162 | } 163 | { 164 | GuiCellComposition* cell=new GuiCellComposition; 165 | table->AddChild(cell); 166 | cell->SetSite(0, 1, 1, 1); 167 | 168 | buttonIncrease=g::NewButton(); 169 | buttonIncrease->SetText(L"Increase 100000 Items"); 170 | buttonIncrease->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 171 | buttonIncrease->Clicked.AttachMethod(this, &VirtualModeWindow::buttonIncrease_Clicked); 172 | cell->AddChild(buttonIncrease->GetBoundsComposition()); 173 | } 174 | { 175 | GuiCellComposition* cell=new GuiCellComposition; 176 | table->AddChild(cell); 177 | cell->SetSite(1, 1, 1, 1); 178 | 179 | buttonDecrease=g::NewButton(); 180 | buttonDecrease->SetText(L"Decrease 100000 Items"); 181 | buttonDecrease->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 182 | buttonDecrease->Clicked.AttachMethod(this, &VirtualModeWindow::buttonDecrease_Clicked); 183 | cell->AddChild(buttonDecrease->GetBoundsComposition()); 184 | } 185 | 186 | // set the preferred minimum client size 187 | this->GetBoundsComposition()->SetPreferredMinSize(Size(480, 480)); 188 | // call this to calculate the size immediately if any indirect content in the table changes 189 | // so that the window can calcaulte its correct size before calling the MoveToScreenCenter() 190 | this->ForceCalculateSizeImmediately(); 191 | // move to the screen center 192 | this->MoveToScreenCenter(); 193 | } 194 | }; 195 | 196 | void GuiMain() 197 | { 198 | GuiWindow* window=new VirtualModeWindow; 199 | GetApplication()->Run(window); 200 | delete window; 201 | } 202 | -------------------------------------------------------------------------------- /Tests/Controls.Scroll.ColorPicker/Controls.Scroll.ColorPicker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "X11CairoIncludes.h" 3 | 4 | // for SortedList, CopyFrom and Select 5 | 6 | using namespace vl; 7 | using namespace vl::presentation; 8 | using namespace vl::presentation::theme; 9 | using namespace vl::presentation::controls; 10 | using namespace vl::presentation::compositions; 11 | using namespace vl::presentation::elements; 12 | using namespace vl::collections; 13 | 14 | int main() 15 | { 16 | SetupX11CairoRenderer(); 17 | } 18 | 19 | 20 | 21 | class ColorPickerWindow : public GuiWindow 22 | { 23 | private: 24 | GuiSolidBackgroundElement* colorElement; 25 | GuiLabel* labelComponents[3]; 26 | GuiScroll* trackers[3]; 27 | 28 | void UpdateColor() 29 | { 30 | int components[3]; 31 | for(int i=0;i<3;i++) 32 | { 33 | components[i]=trackers[i]->GetPosition(); 34 | labelComponents[i]->SetText(itow(components[i])); 35 | } 36 | colorElement->SetColor(Color((unsigned char)components[0], (unsigned char)components[1], (unsigned char)components[2])); 37 | } 38 | 39 | void Tracker_PositionChanged(GuiGraphicsComposition* sender, GuiEventArgs& arguments) 40 | { 41 | UpdateColor(); 42 | } 43 | public: 44 | ColorPickerWindow() 45 | :GuiWindow(GetCurrentTheme()->CreateWindowStyle()) 46 | { 47 | this->SetText(L"Controls.Scroll.ColorPicker"); 48 | this->GetContainerComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren); 49 | 50 | GuiTableComposition* table=new GuiTableComposition; 51 | table->SetAlignmentToParent(Margin(0, 0, 0, 0)); 52 | table->SetCellPadding(2); 53 | table->SetRowsAndColumns(4, 3); 54 | table->SetRowOption(0, GuiCellOption::PercentageOption(1.0)); 55 | table->SetRowOption(1, GuiCellOption::MinSizeOption()); 56 | table->SetRowOption(2, GuiCellOption::MinSizeOption()); 57 | table->SetRowOption(3, GuiCellOption::MinSizeOption()); 58 | table->SetColumnOption(0, GuiCellOption::MinSizeOption()); 59 | table->SetColumnOption(1, GuiCellOption::AbsoluteOption(32)); 60 | table->SetColumnOption(2, GuiCellOption::PercentageOption(1.0)); 61 | this->GetContainerComposition()->AddChild(table); 62 | 63 | { 64 | colorElement=GuiSolidBackgroundElement::Create(); 65 | 66 | GuiBoundsComposition* colorComposition=new GuiBoundsComposition; 67 | colorComposition->SetAlignmentToParent(Margin(0, 0, 0, 0)); 68 | colorComposition->SetOwnedElement(colorElement); 69 | 70 | GuiCellComposition* cell=new GuiCellComposition; 71 | table->AddChild(cell); 72 | cell->SetSite(0, 0, 1, 3); 73 | cell->AddChild(colorComposition); 74 | } 75 | 76 | const wchar_t* labels[]={L"R: ", L"G: ", L"B: "}; 77 | for(int i=0;i<3;i++) 78 | { 79 | { 80 | GuiLabel* label=g::NewLabel(); 81 | label->SetText(labels[i]); 82 | label->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 83 | 84 | GuiCellComposition* cell=new GuiCellComposition; 85 | table->AddChild(cell); 86 | cell->SetSite(i+1, 0, 1, 1); 87 | cell->AddChild(label->GetBoundsComposition()); 88 | } 89 | { 90 | labelComponents[i]=g::NewLabel(); 91 | labelComponents[i]->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 92 | 93 | GuiCellComposition* cell=new GuiCellComposition; 94 | table->AddChild(cell); 95 | cell->SetSite(i+1, 1, 1, 1); 96 | cell->AddChild(labelComponents[i]->GetBoundsComposition()); 97 | } 98 | { 99 | trackers[i]=g::NewHTracker(); 100 | trackers[i]->SetTotalSize(255); 101 | trackers[i]->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0)); 102 | trackers[i]->PositionChanged.AttachMethod(this, &ColorPickerWindow::Tracker_PositionChanged); 103 | 104 | GuiCellComposition* cell=new GuiCellComposition; 105 | table->AddChild(cell); 106 | cell->SetSite(i+1, 2, 1, 1); 107 | cell->AddChild(trackers[i]->GetBoundsComposition()); 108 | } 109 | } 110 | 111 | UpdateColor(); 112 | 113 | // set the preferred minimum client size 114 | this->GetBoundsComposition()->SetPreferredMinSize(Size(640, 480)); 115 | // call this to calculate the size immediately if any indirect content in the table changes 116 | // so that the window can calcaulte its correct size before calling the MoveToScreenCenter() 117 | this->ForceCalculateSizeImmediately(); 118 | // move to the screen center 119 | this->MoveToScreenCenter(); 120 | } 121 | 122 | ~ColorPickerWindow() 123 | { 124 | } 125 | }; 126 | 127 | void GuiMain() 128 | { 129 | GuiWindow* window=new ColorPickerWindow(); 130 | GetApplication()->Run(window); 131 | delete window; 132 | } 133 | -------------------------------------------------------------------------------- /Tests/HelloWorld/HelloWorld.cpp: -------------------------------------------------------------------------------- 1 | #include "HelloWorld.h" 2 | 3 | template 4 | void RunWindow() 5 | { 6 | GuiWindow* window = new T(); 7 | GetApplication()->Run(window); 8 | delete window; 9 | } 10 | 11 | void GuiMain() 12 | { 13 | RunWindow(); 14 | } 15 | 16 | int main(int argc, const char * argv[]) 17 | { 18 | SetupX11CairoRenderer(); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /Tests/HelloWorld/HelloWorld.h: -------------------------------------------------------------------------------- 1 | #ifndef __HELLO_WORLD_H 2 | #define __HELLO_WORLD_H 3 | 4 | #include 5 | #include "X11CairoIncludes.h" 6 | 7 | using namespace vl; 8 | using namespace vl::presentation; 9 | using namespace vl::presentation::theme; 10 | using namespace vl::presentation::controls; 11 | 12 | class HelloWorldWindow : public GuiWindow 13 | { 14 | public: 15 | HelloWorldWindow() :GuiWindow(GetCurrentTheme()->CreateWindowStyle()) 16 | { 17 | WString title(L"GacUI X11/Cairo"); 18 | 19 | this->SetText(title); 20 | this->SetClientSize(vl::presentation::Size(640, 480)); 21 | //this->MoveToScreenCenter(); 22 | 23 | 24 | GuiLabel* label = g::NewLabel(); 25 | label->SetText(L"Welcome to GacUI Library!"); 26 | { 27 | FontProperties font; 28 | font.fontFamily = L"Sans"; 29 | font.size = 40; 30 | font.antialias = true; 31 | font.italic = true; 32 | font.underline = true; 33 | font.strikeline = true; 34 | font.bold = true; 35 | label->SetTextColor(Color(0, 0, 255)); 36 | label->SetFont(font); 37 | } 38 | this->AddChild(label); 39 | 40 | } 41 | 42 | ~HelloWorldWindow() 43 | { 44 | } 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/CairoPangoIncludes.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_CAIRO_PANGO_INCLUDES_H 2 | #define __GAC_X11CAIRO_CAIRO_PANGO_INCLUDES_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/GuiGraphicsX11Cairo.cpp: -------------------------------------------------------------------------------- 1 | #include "GuiGraphicsX11Cairo.h" 2 | 3 | 4 | namespace vl 5 | { 6 | namespace presentation 7 | { 8 | namespace elements_x11cairo 9 | { 10 | void RegisterX11CairoElementRenderers() 11 | { 12 | GuiSolidBackgroundElementRenderer::Register(); 13 | GuiSolidLabelElementRenderer::Register(); 14 | GuiSolidBorderElementRenderer::Register(); 15 | GuiGradientBackgroundElementRenderer::Register(); 16 | GuiPolygonElementRenderer::Register(); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/GuiGraphicsX11Cairo.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_GUI_GRAPHICS_X11_CAIRO_H 2 | #define __GAC_X11CAIRO_GUI_GRAPHICS_X11_CAIRO_H 3 | 4 | #include 5 | #include "CairoPangoIncludes.h" 6 | #include "Renderers/X11CairoRenderers.h" 7 | 8 | namespace vl 9 | { 10 | namespace presentation 11 | { 12 | namespace elements 13 | { 14 | class GuiX11CairoElement; 15 | 16 | struct GuiX11CairoElementEventArgs: compositions::GuiEventArgs 17 | { 18 | public: 19 | GuiX11CairoElement* element; 20 | 21 | }; 22 | 23 | class GuiX11CairoElement: public Object, public elements::IGuiGraphicsElement, public Description 24 | { 25 | DEFINE_GUI_GRAPHICS_ELEMENT(GuiX11CairoElement, L"X11CairoElement"); 26 | 27 | protected: 28 | GuiX11CairoElement(); 29 | 30 | public: 31 | ~GuiX11CairoElement(); 32 | }; 33 | } 34 | namespace elements_x11cairo 35 | { 36 | extern void RegisterX11CairoElementRenderers(); 37 | } 38 | } 39 | } 40 | 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/CairoHelpers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "CairoHelpers.h" 3 | 4 | namespace vl 5 | { 6 | namespace presentation 7 | { 8 | namespace elements_x11cairo 9 | { 10 | namespace helpers 11 | { 12 | GradientDirection ConvertDirection(GuiGradientBackgroundElement::Direction direction) 13 | { 14 | switch(direction) 15 | { 16 | case GuiGradientBackgroundElement::Horizontal: 17 | return GradientDirection::Horizontal; 18 | case GuiGradientBackgroundElement::Vertical: 19 | return GradientDirection::Vertical; 20 | case GuiGradientBackgroundElement::Slash: 21 | return GradientDirection::Slash; 22 | case GuiGradientBackgroundElement::Backslash: 23 | return GradientDirection::Backslash; 24 | } 25 | 26 | return GradientDirection(); 27 | } 28 | 29 | void PathGenerate(cairo_t* cairoContext, ElementShape shape, Rect bounds) 30 | { 31 | switch(shape) 32 | { 33 | case ElementShape::Rectangle: 34 | //Add 0.5 to make this line pass through the center of pixel 35 | cairo_rectangle(cairoContext, 0.5 + bounds.x1, 0.5 + bounds.y1, - 1.0 + bounds.Width(), - 1.0 + bounds.Height()); 36 | break; 37 | case ElementShape::Ellipse: 38 | cairo_translate(cairoContext, bounds.x1 + bounds.Width() / 2 + 0.5, bounds.y1 + bounds.Height() / 2 + 0.5); 39 | cairo_scale(cairoContext, bounds.Width() / 2 - 0.5, bounds.Height() / 2 - 0.5); 40 | cairo_arc(cairoContext, 0.0, 0.0, 1.0, 0.0, 2 * M_PI); 41 | cairo_identity_matrix(cairoContext); 42 | break; 43 | } 44 | } 45 | 46 | void ColorSet(cairo_t* cairoContext, Color color) 47 | { 48 | cairo_set_source_rgba(cairoContext, 1.0 * color.r / 255, 1.0 * color.g / 255, 1.0 * color.b / 255, 1.0 * color.a / 255); 49 | } 50 | 51 | void SolidFill(cairo_t* cairoContext, Color color) 52 | { 53 | ColorSet(cairoContext, color); 54 | cairo_fill(cairoContext); 55 | } 56 | 57 | void GradientFill(cairo_t* cairoContext, Color color1, Color color2, Rect bounds, GradientDirection direction, bool smooth) 58 | { 59 | cairo_pattern_t* pattern = NULL; 60 | 61 | int midX = bounds.x1 + bounds.Width() / 2; 62 | int midY = bounds.y1 + bounds.Height() / 2; 63 | 64 | switch(direction) 65 | { 66 | case GradientDirection::Horizontal: 67 | pattern = cairo_pattern_create_linear(bounds.x1, midY, bounds.x2, midY); 68 | break; 69 | case GradientDirection::Vertical: 70 | pattern = cairo_pattern_create_linear(midX, bounds.y1, midX, bounds.y2); 71 | break; 72 | case GradientDirection::Slash: 73 | pattern = cairo_pattern_create_linear(bounds.x1, bounds.y2, bounds.x2, bounds.y1); 74 | break; 75 | case GradientDirection::Backslash: 76 | pattern = cairo_pattern_create_linear(bounds.x1, bounds.x2, bounds.y1, bounds.y2); 77 | break; 78 | default: 79 | throw Exception(L"Illegal gradient direction"); 80 | } 81 | 82 | cairo_pattern_add_color_stop_rgba(pattern, 0, 1.0 * color1.r / 255, 1.0 * color1.g / 255, 1.0 * color1.b / 255, 1.0 * color1.a / 255); 83 | cairo_pattern_add_color_stop_rgba(pattern, 1, 1.0 * color2.r / 255, 1.0 * color2.g / 255, 1.0 * color2.b / 255, 1.0 * color2.a / 255); 84 | 85 | if(!smooth) 86 | { 87 | cairo_pattern_add_color_stop_rgba(pattern, 0.49, 1.0 * color1.r / 255, 1.0 * color1.g / 255, 1.0 * color1.b / 255, 1.0 * color1.a / 255); 88 | cairo_pattern_add_color_stop_rgba(pattern, 0.51, 1.0 * color2.r / 255, 1.0 * color2.g / 255, 1.0 * color2.b / 255, 1.0 * color2.a / 255); 89 | } 90 | cairo_set_source(cairoContext, pattern); 91 | 92 | cairo_fill(cairoContext); 93 | 94 | cairo_pattern_destroy(pattern); 95 | } 96 | 97 | 98 | void PathStroke(cairo_t* cairoContext, Color color, double thickness) 99 | { 100 | ColorSet(cairoContext, color); 101 | 102 | cairo_set_line_width(cairoContext, thickness); 103 | cairo_stroke(cairoContext); 104 | } 105 | 106 | WString WebdingsMap(WString oldString) 107 | { 108 | wchar_t result[oldString.Length() + 1]; 109 | result[oldString.Length()] = L'\0'; 110 | for(vint i = 0; i < oldString.Length(); i++) 111 | { 112 | switch(oldString[i]) 113 | { 114 | case L'a': result[i] = 0x2713; 115 | break; 116 | } 117 | } 118 | return WString(result); 119 | } 120 | } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/CairoHelpers.h: -------------------------------------------------------------------------------- 1 | #ifndef GAC_X11CAIRO_CAIRO_HELPER_FUNCTIONS_H 2 | #define GAC_X11CAIRO_CAIRO_HELPER_FUNCTIONS_H 3 | 4 | #include 5 | #include "../CairoPangoIncludes.h" 6 | 7 | namespace vl 8 | { 9 | namespace presentation 10 | { 11 | namespace elements_x11cairo 12 | { 13 | using namespace elements; 14 | namespace helpers 15 | { 16 | enum class GradientDirection 17 | { 18 | Horizontal, 19 | Vertical, 20 | Slash, 21 | Backslash, 22 | }; 23 | 24 | GradientDirection ConvertDirection(GuiGradientBackgroundElement::Direction direction); 25 | 26 | void PathGenerate(cairo_t* cairoContext, ElementShape shape, Rect bounds); 27 | 28 | void PathStroke(cairo_t* cairoContext, Color color, double thickness = 1.0); 29 | 30 | void ColorSet(cairo_t* cairoContext, Color color); 31 | 32 | void SolidFill(cairo_t* cairoContext, Color color); 33 | 34 | void GradientFill(cairo_t* cairoContext, Color color1, Color color2, Rect bounds, GradientDirection direction, bool smooth = false); 35 | 36 | WString WebdingsMap(WString oldString); 37 | } 38 | } 39 | } 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/GuiGradientBackgroundElementRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include "GuiGradientBackgroundElementRenderer.h" 2 | #include "CairoHelpers.h" 3 | 4 | namespace vl 5 | { 6 | namespace presentation 7 | { 8 | namespace elements_x11cairo 9 | { 10 | GuiGradientBackgroundElementRenderer::GuiGradientBackgroundElementRenderer(): 11 | minSize(1, 1), cairoContext(NULL) 12 | { 13 | } 14 | 15 | 16 | void GuiGradientBackgroundElementRenderer::InitializeInternal() 17 | { 18 | if(element) OnElementStateChanged(); 19 | } 20 | 21 | void GuiGradientBackgroundElementRenderer::FinalizeInternal() 22 | { 23 | } 24 | 25 | void GuiGradientBackgroundElementRenderer::Render(Rect bounds) 26 | { 27 | cairo_save(cairoContext); 28 | helpers::PathGenerate(cairoContext, element->GetShape(), bounds); 29 | helpers::GradientFill(cairoContext, 30 | element->GetColor1(), 31 | element->GetColor2(), 32 | bounds, 33 | helpers::ConvertDirection(element->GetDirection()), 34 | false); 35 | cairo_restore(cairoContext); 36 | } 37 | 38 | void GuiGradientBackgroundElementRenderer::OnElementStateChanged() 39 | { 40 | } 41 | 42 | void GuiGradientBackgroundElementRenderer::RenderTargetChangedInternal(IX11CairoRenderTarget* oldRT, IX11CairoRenderTarget* newRT) 43 | { 44 | if(newRT) 45 | cairoContext = newRT->GetCairoContext(); 46 | else cairoContext = NULL; 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/GuiGradientBackgroundElementRenderer.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_GUI_GRADIENT_BACKGROUND_ELEMENT_RENDERER_H 2 | #define __GAC_X11CAIRO_GUI_GRADIENT_BACKGROUND_ELEMENT_RENDERER_H 3 | 4 | #include 5 | #include "../X11CairoRenderTarget.h" 6 | 7 | namespace vl 8 | { 9 | namespace presentation 10 | { 11 | namespace elements_x11cairo 12 | { 13 | using namespace elements; 14 | class GuiGradientBackgroundElementRenderer: public Object, public IGuiGraphicsRenderer 15 | { 16 | DEFINE_GUI_GRAPHICS_RENDERER(GuiGradientBackgroundElement, GuiGradientBackgroundElementRenderer, IX11CairoRenderTarget); 17 | 18 | protected: 19 | cairo_t* cairoContext; 20 | 21 | public: 22 | GuiGradientBackgroundElementRenderer(); 23 | 24 | void InitializeInternal(); 25 | void FinalizeInternal(); 26 | void Render(Rect bounds); 27 | void OnElementStateChanged(); 28 | void RenderTargetChangedInternal(IX11CairoRenderTarget* oldRT, IX11CairoRenderTarget* newRT); 29 | }; 30 | } 31 | } 32 | } 33 | 34 | 35 | #endif 36 | 37 | 38 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/GuiPolygonElementRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include "GuiPolygonElementRenderer.h" 2 | #include "CairoHelpers.h" 3 | 4 | 5 | namespace vl 6 | { 7 | namespace presentation 8 | { 9 | namespace elements_x11cairo 10 | { 11 | GuiPolygonElementRenderer::GuiPolygonElementRenderer() 12 | { 13 | } 14 | void GuiPolygonElementRenderer::InitializeInternal() 15 | { 16 | } 17 | 18 | void GuiPolygonElementRenderer::FinalizeInternal() 19 | { 20 | } 21 | 22 | void GuiPolygonElementRenderer::RenderTargetChangedInternal(IX11CairoRenderTarget* oldRT, IX11CairoRenderTarget* newRT) 23 | { 24 | if(newRT) 25 | { 26 | cairoContext = newRT->GetCairoContext(); 27 | OnElementStateChanged(); 28 | } 29 | } 30 | 31 | void GuiPolygonElementRenderer::OnElementStateChanged() 32 | { 33 | } 34 | 35 | void GuiPolygonElementRenderer::Render(Rect bounds) 36 | { 37 | cairo_save(cairoContext); 38 | 39 | Color bg = element->GetBackgroundColor(); 40 | Color border = element->GetBorderColor(); 41 | 42 | //Actual left-top point of the shape 43 | int ptx = bounds.x1 + (bounds.Width() - element->GetSize().x) / 2; 44 | int pty = bounds.y1 + (bounds.Height() - element->GetSize().y) / 2; 45 | 46 | cairo_move_to(cairoContext, 0.5 + ptx + element->GetPoint(0).x, 0.5 + pty + element->GetPoint(0).y); 47 | for(int i = 1; i < element->GetPointCount(); i++) 48 | { 49 | cairo_line_to(cairoContext, 0.5 + ptx + element->GetPoint(i).x, 0.5 + pty + element->GetPoint(i).y); 50 | } 51 | cairo_close_path(cairoContext); 52 | 53 | helpers::ColorSet(cairoContext, bg); 54 | cairo_fill_preserve(cairoContext); 55 | 56 | helpers::PathStroke(cairoContext, border, 1.0); 57 | 58 | cairo_restore(cairoContext); 59 | 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/GuiPolygonElementRenderer.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_GUI_POLYGON_ELEMENT_RENDERER_H 2 | #define __GAC_X11CAIRO_GUI_POLYGON_ELEMENT_RENDERER_H 3 | 4 | #include 5 | #include "../X11CairoRenderTarget.h" 6 | 7 | 8 | namespace vl 9 | { 10 | namespace presentation 11 | { 12 | namespace elements_x11cairo 13 | { 14 | using namespace elements; 15 | class GuiPolygonElementRenderer: public Object, public IGuiGraphicsRenderer 16 | { 17 | DEFINE_GUI_GRAPHICS_RENDERER(GuiPolygonElement, GuiPolygonElementRenderer, IX11CairoRenderTarget); 18 | 19 | protected: 20 | cairo_t* cairoContext; 21 | 22 | public: 23 | GuiPolygonElementRenderer(); 24 | 25 | void InitializeInternal(); 26 | void FinalizeInternal(); 27 | void Render(Rect bounds); 28 | void OnElementStateChanged(); 29 | void RenderTargetChangedInternal(IX11CairoRenderTarget* oldRT, IX11CairoRenderTarget* newRT); 30 | }; 31 | } 32 | } 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/GuiSolidBackgroundElementRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include "GuiSolidBackgroundElementRenderer.h" 2 | #include "CairoHelpers.h" 3 | 4 | 5 | namespace vl 6 | { 7 | namespace presentation 8 | { 9 | namespace elements_x11cairo 10 | { 11 | GuiSolidBackgroundElementRenderer::GuiSolidBackgroundElementRenderer(): 12 | minSize(1, 1), cairoContext(NULL) 13 | { 14 | } 15 | 16 | 17 | void GuiSolidBackgroundElementRenderer::InitializeInternal() 18 | { 19 | } 20 | 21 | void GuiSolidBackgroundElementRenderer::FinalizeInternal() 22 | { 23 | } 24 | 25 | void GuiSolidBackgroundElementRenderer::Render(Rect bounds) 26 | { 27 | Color color = element->GetColor(); 28 | 29 | cairo_save(cairoContext); 30 | helpers::PathGenerate(cairoContext, element->GetShape(), bounds); 31 | helpers::SolidFill(cairoContext, color); 32 | cairo_restore(cairoContext); 33 | } 34 | 35 | void GuiSolidBackgroundElementRenderer::OnElementStateChanged() 36 | { 37 | } 38 | 39 | void GuiSolidBackgroundElementRenderer::RenderTargetChangedInternal(IX11CairoRenderTarget* oldRT, IX11CairoRenderTarget* newRT) 40 | { 41 | if(newRT) 42 | cairoContext = newRT->GetCairoContext(); 43 | else cairoContext = NULL; 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/GuiSolidBackgroundElementRenderer.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_GUI_SOLID_BACKGROUND_ELEMENT_RENDERER_H 2 | #define __GAC_X11CAIRO_GUI_SOLID_BACKGROUND_ELEMENT_RENDERER_H 3 | 4 | #include 5 | #include "../X11CairoRenderTarget.h" 6 | 7 | namespace vl 8 | { 9 | namespace presentation 10 | { 11 | namespace elements_x11cairo 12 | { 13 | using namespace elements; 14 | class GuiSolidBackgroundElementRenderer: public Object, public IGuiGraphicsRenderer 15 | { 16 | DEFINE_GUI_GRAPHICS_RENDERER(GuiSolidBackgroundElement, GuiSolidBackgroundElementRenderer, IX11CairoRenderTarget); 17 | 18 | protected: 19 | cairo_t* cairoContext; 20 | 21 | public: 22 | GuiSolidBackgroundElementRenderer(); 23 | 24 | void InitializeInternal(); 25 | void FinalizeInternal(); 26 | void Render(Rect bounds); 27 | void OnElementStateChanged(); 28 | void RenderTargetChangedInternal(IX11CairoRenderTarget* oldRT, IX11CairoRenderTarget* newRT); 29 | }; 30 | } 31 | } 32 | } 33 | 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/GuiSolidBorderElementRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include "GuiSolidBorderElementRenderer.h" 2 | #include "CairoHelpers.h" 3 | 4 | 5 | namespace vl 6 | { 7 | namespace presentation 8 | { 9 | namespace elements_x11cairo 10 | { 11 | GuiSolidBorderElementRenderer::GuiSolidBorderElementRenderer(): 12 | minSize(1, 1), cairoContext(NULL) 13 | { 14 | } 15 | 16 | 17 | void GuiSolidBorderElementRenderer::InitializeInternal() 18 | { 19 | } 20 | 21 | void GuiSolidBorderElementRenderer::FinalizeInternal() 22 | { 23 | } 24 | 25 | void GuiSolidBorderElementRenderer::Render(Rect bounds) 26 | { 27 | Color color = element->GetColor(); 28 | cairo_save(cairoContext); 29 | cairo_set_source_rgb(cairoContext, 1.0 * color.r / 255, 1.0 * color.g / 255, 1.0 * color.b / 255); 30 | 31 | cairo_set_line_width(cairoContext, 1.0); 32 | helpers::PathGenerate(cairoContext, element->GetShape(), bounds); 33 | helpers::PathStroke(cairoContext, color); 34 | } 35 | 36 | void GuiSolidBorderElementRenderer::OnElementStateChanged() 37 | { 38 | } 39 | 40 | void GuiSolidBorderElementRenderer::RenderTargetChangedInternal(IX11CairoRenderTarget* oldRT, IX11CairoRenderTarget* newRT) 41 | { 42 | if(newRT) 43 | cairoContext = newRT->GetCairoContext(); 44 | else cairoContext = NULL; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/GuiSolidBorderElementRenderer.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_GUI_SOLID_BORDER_ELEMENT_RENDERER_H 2 | #define __GAC_X11CAIRO_GUI_SOLID_BORDER_ELEMENT_RENDERER_H 3 | 4 | #include 5 | #include "../X11CairoRenderTarget.h" 6 | 7 | namespace vl 8 | { 9 | namespace presentation 10 | { 11 | namespace elements_x11cairo 12 | { 13 | using namespace elements; 14 | class GuiSolidBorderElementRenderer: public Object, public IGuiGraphicsRenderer 15 | { 16 | DEFINE_GUI_GRAPHICS_RENDERER(GuiSolidBorderElement, GuiSolidBorderElementRenderer, IX11CairoRenderTarget); 17 | 18 | protected: 19 | cairo_t* cairoContext; 20 | 21 | public: 22 | GuiSolidBorderElementRenderer(); 23 | 24 | void InitializeInternal(); 25 | void FinalizeInternal(); 26 | void Render(Rect bounds); 27 | void OnElementStateChanged(); 28 | void RenderTargetChangedInternal(IX11CairoRenderTarget* oldRT, IX11CairoRenderTarget* newRT); 29 | }; 30 | } 31 | } 32 | } 33 | 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/GuiSolidLabelElementRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include "GuiSolidLabelElementRenderer.h" 2 | #include "CairoHelpers.h" 3 | 4 | using namespace vl::collections; 5 | using namespace vl::presentation::elements::text; 6 | namespace vl 7 | { 8 | namespace presentation 9 | { 10 | namespace elements_x11cairo 11 | { 12 | GuiSolidLabelElementRenderer::GuiSolidLabelElementRenderer() 13 | : minSize(1, 1), cairoContext(NULL), pangoFontDesc(NULL), attrList(NULL), layout(NULL) 14 | { 15 | } 16 | 17 | void GuiSolidLabelElementRenderer::InitializeInternal() 18 | { 19 | pangoFontDesc = pango_font_description_new(); 20 | OnElementStateChanged(); 21 | } 22 | 23 | void GuiSolidLabelElementRenderer::FinalizeInternal() 24 | { 25 | pango_font_description_free(pangoFontDesc); 26 | 27 | if(layout) 28 | { 29 | g_object_unref(layout); 30 | layout = NULL; 31 | } 32 | 33 | if(attrList) 34 | pango_attr_list_unref(attrList); 35 | } 36 | 37 | void GuiSolidLabelElementRenderer::Render(Rect bounds) 38 | { 39 | if(cairoContext) 40 | { 41 | cairo_save(cairoContext); 42 | Color color = element->GetColor(); 43 | FontProperties font = element->GetFont(); 44 | 45 | cairo_set_source_rgba(cairoContext, 46 | 1.0 * color.r / 255, 47 | 1.0 * color.g / 255, 48 | 1.0 * color.b / 255, 49 | 1.0 * color.a / 255 50 | ); 51 | 52 | if(element->GetWrapLine()) pango_layout_set_width(layout, bounds.Width() * PANGO_SCALE); 53 | pango_cairo_update_layout(cairoContext, layout); 54 | int layoutWidth, layoutHeight; 55 | int plotX1, plotY1; 56 | 57 | pango_layout_get_pixel_size( layout, &layoutWidth, &layoutHeight); 58 | switch(element->GetHorizontalAlignment()) 59 | { 60 | case Alignment::Left: 61 | plotX1 = bounds.x1; 62 | break; 63 | case Alignment::Center: 64 | plotX1 = bounds.x1 + (bounds.Width() - layoutWidth) / 2; 65 | break; 66 | case Alignment::Right: 67 | plotX1 = bounds.x1 + (bounds.Width() - layoutWidth); 68 | break; 69 | } 70 | 71 | switch(element->GetVerticalAlignment()) 72 | { 73 | case Alignment::Top: 74 | plotY1 = bounds.y1; 75 | break; 76 | case Alignment::Center: 77 | plotY1 = bounds.y1 + (bounds.Height() - layoutHeight) / 2; 78 | break; 79 | case Alignment::Bottom: 80 | plotY1 = bounds.y1 + (bounds.Height() - layoutHeight); 81 | break; 82 | } 83 | 84 | cairo_move_to(cairoContext, plotX1, plotY1); 85 | 86 | pango_cairo_layout_path(cairoContext, layout); 87 | cairo_fill(cairoContext); 88 | 89 | cairo_restore(cairoContext); 90 | } 91 | } 92 | 93 | void GuiSolidLabelElementRenderer::OnElementStateChanged() 94 | { 95 | FontProperties font = element->GetFont(); 96 | Color color = element->GetColor(); 97 | int layoutWidth, layoutHeight; 98 | 99 | AString family = wtoa(font.fontFamily); 100 | pango_font_description_set_family(pangoFontDesc, family.Buffer()); 101 | pango_font_description_set_absolute_size(pangoFontDesc, font.size * PANGO_SCALE); 102 | 103 | if(font.italic) pango_font_description_set_style(pangoFontDesc, PANGO_STYLE_ITALIC); 104 | else pango_font_description_set_style(pangoFontDesc, PANGO_STYLE_NORMAL); 105 | 106 | if(attrList) 107 | { 108 | pango_attr_list_unref(attrList); 109 | } 110 | 111 | attrList = pango_attr_list_new(); 112 | 113 | pango_attr_list_insert(attrList, pango_attr_underline_new( 114 | font.underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE) 115 | ); 116 | 117 | pango_attr_list_insert(attrList, pango_attr_strikethrough_new ( 118 | font.strikeline ? TRUE : FALSE 119 | ) 120 | ); 121 | 122 | pango_attr_list_insert(attrList, pango_attr_weight_new ( 123 | font.bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_MEDIUM 124 | ) 125 | ); 126 | 127 | if(layout) 128 | { 129 | g_object_unref(layout); 130 | layout = NULL; 131 | } 132 | 133 | if(cairoContext) 134 | { 135 | layout = pango_cairo_create_layout(cairoContext); 136 | 137 | WString wtext = (font.fontFamily == L"Webdings") ? helpers::WebdingsMap(element->GetText()) : element->GetText(); 138 | AString text = wtoa(wtext); 139 | 140 | pango_layout_set_font_description(layout, pangoFontDesc); 141 | pango_layout_set_attributes(layout, attrList); 142 | pango_layout_set_text(layout, text.Buffer(), text.Length()); 143 | pango_layout_set_alignment(layout, 144 | element->GetHorizontalAlignment() == Alignment::Left ? PANGO_ALIGN_LEFT : 145 | element->GetHorizontalAlignment() == Alignment::Center ? PANGO_ALIGN_CENTER : 146 | element->GetHorizontalAlignment() == Alignment::Right ? PANGO_ALIGN_RIGHT : 147 | PANGO_ALIGN_LEFT 148 | ); 149 | 150 | 151 | pango_cairo_update_layout(cairoContext, layout); 152 | 153 | 154 | pango_layout_get_pixel_size( layout, &layoutWidth, &layoutHeight); 155 | 156 | minSize.x = layoutWidth; 157 | minSize.y = layoutHeight; 158 | } 159 | } 160 | 161 | void GuiSolidLabelElementRenderer::RenderTargetChangedInternal(IX11CairoRenderTarget* oldRT, IX11CairoRenderTarget* newRT) 162 | { 163 | if(newRT) 164 | { 165 | cairoContext = newRT->GetCairoContext(); 166 | OnElementStateChanged(); 167 | } 168 | else cairoContext = NULL; 169 | } 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/GuiSolidLabelElementRenderer.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_GUI_COLORIZED_TEXT_ELEMENT_RENDERER_H 2 | #define __GAC_X11CAIRO_GUI_COLORIZED_TEXT_ELEMENT_RENDERER_H 3 | 4 | #include 5 | #include "../X11CairoRenderTarget.h" 6 | 7 | namespace vl 8 | { 9 | namespace presentation 10 | { 11 | namespace elements_x11cairo 12 | { 13 | using namespace elements; 14 | class GuiSolidLabelElementRenderer: public Object, public IGuiGraphicsRenderer 15 | { 16 | DEFINE_GUI_GRAPHICS_RENDERER(GuiSolidLabelElement, GuiSolidLabelElementRenderer, IX11CairoRenderTarget); 17 | 18 | protected: 19 | cairo_t* cairoContext; 20 | PangoFontDescription* pangoFontDesc; 21 | PangoAttrList* attrList; 22 | PangoLayout *layout; 23 | 24 | public: 25 | GuiSolidLabelElementRenderer(); 26 | 27 | void InitializeInternal(); 28 | void FinalizeInternal(); 29 | void Render(Rect bounds); 30 | void OnElementStateChanged(); 31 | void RenderTargetChangedInternal(IX11CairoRenderTarget* oldRT, IX11CairoRenderTarget* newRT); 32 | }; 33 | } 34 | } 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/Renderers/X11CairoRenderers.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_X11_CAIRO_RENDERERS_H 2 | #define __GAC_X11CAIRO_X11_CAIRO_RENDERERS_H 3 | 4 | #include "GuiSolidBackgroundElementRenderer.h" 5 | #include "GuiSolidLabelElementRenderer.h" 6 | #include "GuiSolidBorderElementRenderer.h" 7 | #include "GuiGradientBackgroundElementRenderer.h" 8 | #include "GuiPolygonElementRenderer.h" 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/X11CairoRenderTarget.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "X11CairoRenderTarget.h" 4 | #include "X11CairoResourceManager.h" 5 | 6 | 7 | using namespace vl::presentation::x11cairo; 8 | using namespace vl::presentation::elements; 9 | using namespace vl::presentation::elements_x11cairo; 10 | 11 | #ifndef GAC_X11_XCB 12 | #include "../NativeWindow/Xlib/XlibWindow.h" 13 | 14 | using namespace vl::presentation::x11cairo::xlib; 15 | #endif 16 | 17 | namespace vl 18 | { 19 | namespace presentation 20 | { 21 | namespace elements_x11cairo 22 | { 23 | 24 | #ifndef GAC_X11_XCB 25 | class X11CairoXlibRenderTarget: public IX11CairoRenderTarget, INativeWindowListener 26 | { 27 | private: 28 | cairo_surface_t* surface; 29 | cairo_t* context; 30 | XlibWindow* window; 31 | std::vector clippers; 32 | 33 | 34 | public: 35 | X11CairoXlibRenderTarget(XlibWindow* window): 36 | window(window) 37 | { 38 | Size size = window->GetClientSize(); 39 | if(window->GetDoubleBuffer()) 40 | { 41 | surface = cairo_xlib_surface_create(window->GetDisplay(), window->GetBackBuffer(), DefaultVisual(window->GetDisplay(), 0), size.x, size.y); 42 | } 43 | else 44 | { 45 | surface = cairo_xlib_surface_create(window->GetDisplay(), window->GetWindow(), DefaultVisual(window->GetDisplay(), 0), size.x, size.y); 46 | } 47 | 48 | context = cairo_create(surface); 49 | 50 | if(!surface || !context) 51 | throw Exception(L"Failed to create Cairo Surface / Context"); 52 | 53 | window->InstallListener(this); 54 | 55 | } 56 | 57 | virtual ~X11CairoXlibRenderTarget() 58 | { 59 | window->UninstallListener(this); 60 | 61 | cairo_destroy(context); 62 | cairo_surface_destroy(surface); 63 | } 64 | 65 | cairo_surface_t* GetCairoSurface() 66 | { 67 | return surface; 68 | } 69 | 70 | cairo_t* GetCairoContext() 71 | { 72 | return context; 73 | } 74 | 75 | void StartRendering() 76 | { 77 | } 78 | 79 | bool StopRendering() 80 | { 81 | if(window->GetDoubleBuffer()) 82 | { 83 | window->SwapBuffer(); 84 | } 85 | 86 | return true; 87 | } 88 | 89 | void PushClipper(Rect clipper) 90 | { 91 | cairo_save(context); 92 | 93 | if(clippers.size() != 0) 94 | { 95 | Rect previousClipper=GetClipper(); 96 | 97 | clipper.x1=(previousClipper.x1>clipper.x1?previousClipper.x1:clipper.x1); 98 | clipper.y1=(previousClipper.y1>clipper.y1?previousClipper.y1:clipper.y1); 99 | clipper.x2=(previousClipper.x2GetClientSize(); 124 | Rect boundsWin(0, 0, size.x, size.y); 125 | cairo_clip_extents(context, &x1, &y1, &x2, &y2); 126 | Rect boundsClip(x1, x2, y1, y2); 127 | 128 | return (boundsWin == boundsClip); 129 | } 130 | 131 | void Moving(Rect& bounds, bool fixSizeOnly) 132 | { 133 | Size size = window->GetClientSize(); 134 | if(window->GetDoubleBuffer()) 135 | { 136 | cairo_xlib_surface_set_drawable(surface, window->GetBackBuffer(), size.x, size.y); 137 | } 138 | else 139 | { 140 | cairo_xlib_surface_set_size(surface, size.x, size.y); 141 | } 142 | } 143 | 144 | HitTestResult HitTest(Point location) { return BorderNoSizing; } 145 | void Moved() { } 146 | void Enabled() { } 147 | void Disabled() { } 148 | void GotFocus() { } 149 | void LostFocus() { } 150 | void Activated() { } 151 | void Deactivated() { } 152 | void Opened() { } 153 | void Closing(bool& cancel) { } 154 | void Closed() { } 155 | void Paint() { } 156 | void Destroying() { } 157 | void Destroyed() { } 158 | 159 | void LeftButtonDown(const NativeWindowMouseInfo& info) { } 160 | void LeftButtonUp(const NativeWindowMouseInfo& info) { } 161 | void LeftButtonDoubleClick(const NativeWindowMouseInfo& info) { } 162 | void RightButtonDown(const NativeWindowMouseInfo& info) { } 163 | void RightButtonUp(const NativeWindowMouseInfo& info) { } 164 | void RightButtonDoubleClick(const NativeWindowMouseInfo& info) { } 165 | void MiddleButtonDown(const NativeWindowMouseInfo& info) { } 166 | void MiddleButtonUp(const NativeWindowMouseInfo& info) { } 167 | void MiddleButtonDoubleClick(const NativeWindowMouseInfo& info) { } 168 | void HorizontalWheel(const NativeWindowMouseInfo& info) { } 169 | void VerticalWheel(const NativeWindowMouseInfo& info) { } 170 | void MouseMoving(const NativeWindowMouseInfo& info) { } 171 | void MouseEntered() { } 172 | void MouseLeaved() { } 173 | 174 | void KeyDown(const NativeWindowKeyInfo& info) { } 175 | void KeyUp(const NativeWindowKeyInfo& info) { } 176 | void SysKeyDown(const NativeWindowKeyInfo& info) { } 177 | void SysKeyUp(const NativeWindowKeyInfo& info) { } 178 | void Char(const NativeWindowCharInfo& info) { } 179 | 180 | 181 | }; 182 | 183 | IX11CairoRenderTarget* CreateX11CairoRenderTarget(IX11Window* window) 184 | { 185 | XlibWindow* xlibWindow = dynamic_cast(window); 186 | if(!xlibWindow) 187 | throw Exception(L"Invalid window"); 188 | 189 | return new X11CairoXlibRenderTarget(xlibWindow); 190 | } 191 | #else 192 | #endif 193 | void DestroyX11CairoRenderTarget(IX11CairoRenderTarget* target) 194 | { 195 | delete target; 196 | } 197 | } 198 | } 199 | } 200 | 201 | 202 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/X11CairoRenderTarget.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_X11_CAIRO_RENDER_TARGET_H 2 | #define __GAC_X11CAIRO_X11_CAIRO_RENDER_TARGET_H 3 | 4 | #include 5 | #include "CairoPangoIncludes.h" 6 | #include "../NativeWindow/Common/X11Window.h" 7 | 8 | namespace vl 9 | { 10 | namespace presentation 11 | { 12 | namespace elements_x11cairo 13 | { 14 | class IX11CairoRenderTarget: public elements::IGuiGraphicsRenderTarget 15 | { 16 | public: 17 | virtual cairo_surface_t* GetCairoSurface() = 0; 18 | virtual cairo_t* GetCairoContext() = 0; 19 | }; 20 | 21 | extern IX11CairoRenderTarget* CreateX11CairoRenderTarget(x11cairo::IX11Window* window); 22 | extern void DestroyX11CairoRenderTarget(IX11CairoRenderTarget* target); 23 | } 24 | } 25 | } 26 | 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/X11CairoResourceManager.cpp: -------------------------------------------------------------------------------- 1 | #include "X11CairoRenderTarget.h" 2 | #include "X11CairoResourceManager.h" 3 | #include "../NativeWindow/Common/X11Window.h" 4 | 5 | using namespace vl::presentation::elements; 6 | using namespace vl::presentation::elements_x11cairo; 7 | 8 | namespace vl 9 | { 10 | namespace presentation 11 | { 12 | namespace x11cairo 13 | { 14 | class X11CairoResourceManager: public elements::GuiGraphicsResourceManager, public IX11CairoResourceManager 15 | { 16 | IGuiGraphicsRenderTarget* GetRenderTarget(INativeWindow* window) 17 | { 18 | IX11Window* xWindow = dynamic_cast(window); 19 | if(!xWindow) throw Exception(L"Invalid Window"); 20 | 21 | IX11CairoRenderTarget* renderTarget = dynamic_cast(xWindow->GetRenderTarget()); 22 | if(!renderTarget) 23 | { 24 | RecreateRenderTarget(window); 25 | renderTarget = dynamic_cast(xWindow->GetRenderTarget()); 26 | } 27 | 28 | return renderTarget; 29 | } 30 | void RecreateRenderTarget(INativeWindow* window) 31 | { 32 | IX11Window* xWindow = dynamic_cast(window); 33 | if(!xWindow) throw Exception(L"Invalid Window"); 34 | 35 | if(xWindow->GetRenderTarget()) delete xWindow->GetRenderTarget(); 36 | 37 | xWindow->SetRenderTarget(CreateX11CairoRenderTarget(xWindow)); 38 | } 39 | IGuiGraphicsLayoutProvider* GetLayoutProvider() 40 | { 41 | //TODO 42 | return NULL; 43 | } 44 | }; 45 | 46 | void RegisterX11CairoResourceManager() 47 | { 48 | SetGuiGraphicsResourceManager(new X11CairoResourceManager()); 49 | } 50 | 51 | void UnregisterX11CairoResourceManager() 52 | { 53 | if(GetGuiGraphicsResourceManager()) 54 | delete GetGuiGraphicsResourceManager(); 55 | SetGuiGraphicsResourceManager(NULL); 56 | } 57 | } 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /X11Cairo/GraphicsElement/X11CairoResourceManager.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_X11_CAIRO_RESOURCE_MANAGER_H 2 | #define __GAC_X11CAIRO_X11_CAIRO_RESOURCE_MANAGER_H 3 | 4 | #include 5 | namespace vl 6 | { 7 | namespace presentation 8 | { 9 | namespace x11cairo 10 | { 11 | class IX11CairoResourceManager: public Interface 12 | { 13 | }; 14 | 15 | extern void RegisterX11CairoResourceManager(); 16 | extern void UnregisterX11CairoResourceManager(); 17 | } 18 | } 19 | } 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Common/ServicesImpl/PosixAsyncService.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Modified from PosixAsyncService.cpp 3 | // 4 | // Created by Robert Bu on 12/8/14. 5 | // Copyright (c) 2014 Robert Bu. All rights reserved. 6 | // 7 | 8 | #include "PosixAsyncService.h" 9 | 10 | namespace vl { 11 | 12 | namespace presentation { 13 | 14 | namespace x11cairo { 15 | 16 | using namespace collections; 17 | 18 | PosixAsyncService::TaskItem::TaskItem(): 19 | semaphore(0) 20 | { 21 | 22 | } 23 | 24 | PosixAsyncService::TaskItem::TaskItem(Semaphore* _semaphore, const Func& _proc): 25 | semaphore(_semaphore), 26 | proc(_proc) 27 | { 28 | 29 | } 30 | 31 | PosixAsyncService::TaskItem::~TaskItem() 32 | { 33 | 34 | } 35 | 36 | PosixAsyncService::DelayItem::DelayItem(PosixAsyncService* _service, const Func& _proc, bool _executeInMainThread, vint milliseconds): 37 | service(_service), 38 | proc(_proc), 39 | status(INativeDelay::Pending), 40 | executeTime(DateTime::LocalTime().Forward(milliseconds)), 41 | executeInMainThread(_executeInMainThread) 42 | { 43 | 44 | } 45 | 46 | PosixAsyncService::DelayItem::~DelayItem() 47 | { 48 | 49 | } 50 | 51 | INativeDelay::ExecuteStatus PosixAsyncService::DelayItem::GetStatus() 52 | { 53 | return status; 54 | } 55 | 56 | bool PosixAsyncService::DelayItem::Delay(vint milliseconds) 57 | { 58 | SPIN_LOCK(service->taskListLock) 59 | { 60 | if(status==INativeDelay::Pending) 61 | { 62 | executeTime=DateTime::LocalTime().Forward(milliseconds); 63 | return true; 64 | } 65 | } 66 | return false; 67 | } 68 | 69 | bool PosixAsyncService::DelayItem::Cancel() 70 | { 71 | SPIN_LOCK(service->taskListLock) 72 | { 73 | if(status==INativeDelay::Pending) 74 | { 75 | if(service->delayItems.Remove(this)) 76 | { 77 | status=INativeDelay::Canceled; 78 | return true; 79 | } 80 | } 81 | } 82 | return false; 83 | } 84 | 85 | PosixAsyncService::PosixAsyncService(): 86 | mainThreadId(Thread::GetCurrentThreadId()) 87 | { 88 | 89 | } 90 | 91 | PosixAsyncService::~PosixAsyncService() 92 | { 93 | 94 | } 95 | 96 | void PosixAsyncService::ExecuteAsyncTasks() 97 | { 98 | DateTime now = DateTime::LocalTime(); 99 | Array items; 100 | List> executableDelayItems; 101 | 102 | SPIN_LOCK(taskListLock) 103 | { 104 | CopyFrom(items, taskItems); 105 | taskItems.RemoveRange(0, items.Count()); 106 | for(vint i = delayItems.Count()-1;i>=0;i--) 107 | { 108 | Ptr item = delayItems[i]; 109 | if(now.filetime >= item->executeTime.filetime) 110 | { 111 | item->status = INativeDelay::Executing; 112 | executableDelayItems.Add(item); 113 | delayItems.RemoveAt(i); 114 | } 115 | } 116 | } 117 | 118 | FOREACH(TaskItem, item, items) 119 | { 120 | item.proc(); 121 | if(item.semaphore) 122 | { 123 | item.semaphore->Release(); 124 | } 125 | } 126 | 127 | FOREACH(Ptr, item, executableDelayItems) 128 | { 129 | if(item->executeInMainThread) 130 | { 131 | item->proc(); 132 | item->status=INativeDelay::Executed; 133 | } 134 | else 135 | { 136 | InvokeAsync([=]() 137 | { 138 | item->proc(); 139 | item->status=INativeDelay::Executed; 140 | }); 141 | } 142 | } 143 | } 144 | 145 | bool PosixAsyncService::IsInMainThread() 146 | { 147 | return Thread::GetCurrentThreadId() == mainThreadId; 148 | } 149 | 150 | void PosixAsyncService::InvokeAsync(const Func& proc) 151 | { 152 | ThreadPoolLite::Queue(proc); 153 | } 154 | 155 | void PosixAsyncService::InvokeInMainThread(const Func& proc) 156 | { 157 | SPIN_LOCK(taskListLock) 158 | { 159 | TaskItem item(0, proc); 160 | taskItems.Add(item); 161 | } 162 | } 163 | 164 | bool PosixAsyncService::InvokeInMainThreadAndWait(const Func& proc, vint milliseconds) 165 | { 166 | Semaphore* semaphore = new Semaphore(); 167 | semaphore->Create(0, 1); 168 | 169 | TaskItem item(semaphore, proc); 170 | SPIN_LOCK(taskListLock) 171 | { 172 | taskItems.Add(item); 173 | } 174 | 175 | // todo, if semphoare fails to wait for some reason 176 | // taskItems will corrupt 177 | return semaphore->Wait(); 178 | 179 | // if(milliseconds < 0) 180 | // { 181 | // return semaphore.Wait(); 182 | // } 183 | // else 184 | // { 185 | // // todo 186 | // return false; 187 | // //return semaphore.WaitForTime(milliseconds); 188 | // } 189 | } 190 | 191 | Ptr PosixAsyncService::DelayExecute(const Func& proc, vint milliseconds) 192 | { 193 | Ptr delay; 194 | SPIN_LOCK(taskListLock) 195 | { 196 | delay = new DelayItem(this, proc, false, milliseconds); 197 | delayItems.Add(delay); 198 | } 199 | return delay; 200 | } 201 | 202 | Ptr PosixAsyncService::DelayExecuteInMainThread(const Func& proc, vint milliseconds) 203 | { 204 | Ptr delay; 205 | SPIN_LOCK(taskListLock) 206 | { 207 | delay = new DelayItem(this, proc, true, milliseconds); 208 | delayItems.Add(delay); 209 | } 210 | return delay; 211 | } 212 | 213 | 214 | } 215 | 216 | } 217 | 218 | } -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Common/ServicesImpl/PosixAsyncService.h: -------------------------------------------------------------------------------- 1 | // Modified from PosixAsyncService.h 2 | // 3 | // Created by Robert Bu on 12/8/14. 4 | // Copyright (c) 2014 Robert Bu. All rights reserved. 5 | // 6 | 7 | #ifndef __GAC_X11CAIRO_POSIX_ASYNC_SERVICE_H 8 | #define __GAC_X11CAIRO_POSIX_ASYNC_SERVICE_H 9 | 10 | #include 11 | 12 | namespace vl { 13 | 14 | namespace presentation { 15 | 16 | namespace x11cairo { 17 | 18 | class PosixAsyncService : public INativeAsyncService 19 | { 20 | protected: 21 | struct TaskItem 22 | { 23 | Semaphore* semaphore; 24 | Func proc; 25 | 26 | TaskItem(); 27 | TaskItem(Semaphore* _semaphore, const Func& _proc); 28 | ~TaskItem(); 29 | }; 30 | 31 | class DelayItem: public Object, public INativeDelay 32 | { 33 | public: 34 | DelayItem(PosixAsyncService* _service, const Func& _proc, bool _executeInMainThread, vint milliseconds); 35 | ~DelayItem(); 36 | 37 | PosixAsyncService* service; 38 | Func proc; 39 | ExecuteStatus status; 40 | DateTime executeTime; 41 | bool executeInMainThread; 42 | 43 | ExecuteStatus GetStatus() override; 44 | bool Delay(vint milliseconds) override; 45 | bool Cancel() override; 46 | }; 47 | 48 | collections::List taskItems; 49 | collections::List> delayItems; 50 | SpinLock taskListLock; 51 | vint mainThreadId; 52 | 53 | public: 54 | PosixAsyncService(); 55 | ~PosixAsyncService(); 56 | 57 | void ExecuteAsyncTasks(); 58 | bool IsInMainThread()override; 59 | void InvokeAsync(const Func& proc)override; 60 | void InvokeInMainThread(const Func& proc)override; 61 | bool InvokeInMainThreadAndWait(const Func& proc, vint milliseconds)override; 62 | Ptr DelayExecute(const Func& proc, vint milliseconds)override; 63 | Ptr DelayExecuteInMainThread(const Func& proc, vint milliseconds)override; 64 | }; 65 | } 66 | } 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Common/X11Window.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_X11_CAIRO_WINDOW_H 2 | #define __GAC_X11CAIRO_X11_CAIRO_WINDOW_H 3 | 4 | #include 5 | 6 | namespace vl 7 | { 8 | namespace presentation 9 | { 10 | namespace x11cairo 11 | { 12 | class IX11Window: public INativeWindow, public Description 13 | { 14 | public: 15 | virtual void SetRenderTarget(elements::IGuiGraphicsRenderTarget*) = 0; 16 | 17 | virtual elements::IGuiGraphicsRenderTarget* GetRenderTarget() = 0; 18 | }; 19 | } 20 | } 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeCallbackService.cpp: -------------------------------------------------------------------------------- 1 | #include "XlibNativeCallbackService.h" 2 | 3 | using namespace vl::collections; 4 | 5 | namespace vl 6 | { 7 | namespace presentation 8 | { 9 | namespace x11cairo 10 | { 11 | namespace xlib 12 | { 13 | bool XlibNativeCallbackService::InstallListener(INativeControllerListener* listener) 14 | { 15 | listeners.Add(listener); 16 | return true; 17 | } 18 | bool XlibNativeCallbackService::UninstallListener(INativeControllerListener* listener) 19 | { 20 | return listeners.Remove(listener); 21 | } 22 | 23 | void XlibNativeCallbackService::SetTimer() 24 | { 25 | flag = true; 26 | } 27 | 28 | void XlibNativeCallbackService::CheckTimer() 29 | { 30 | if(flag) 31 | { 32 | flag = false; 33 | FOREACH( INativeControllerListener*, i, listeners) 34 | { 35 | i->GlobalTimer(); 36 | } 37 | } 38 | } 39 | void XlibNativeCallbackService::MouseUpEvent(MouseButton button, Point position) 40 | { 41 | switch(button) 42 | { 43 | case MouseButton::LBUTTON: 44 | FOREACH( INativeControllerListener*, i, listeners) 45 | { 46 | i->LeftButtonDown(position); 47 | } 48 | break; 49 | 50 | case MouseButton::RBUTTON: 51 | FOREACH( INativeControllerListener*, i, listeners) 52 | { 53 | i->RightButtonDown(position); 54 | } 55 | break; 56 | 57 | default: 58 | break; 59 | 60 | } 61 | } 62 | void XlibNativeCallbackService::MouseDownEvent(MouseButton button, Point position) 63 | { 64 | switch(button) 65 | { 66 | case MouseButton::LBUTTON: 67 | FOREACH( INativeControllerListener*, i, listeners) 68 | { 69 | i->LeftButtonUp(position); 70 | } 71 | break; 72 | 73 | case MouseButton::RBUTTON: 74 | FOREACH( INativeControllerListener*, i, listeners) 75 | { 76 | i->RightButtonUp(position); 77 | } 78 | break; 79 | 80 | default: 81 | break; 82 | } 83 | 84 | } 85 | void XlibNativeCallbackService::MouseMoveEvent(Point position) 86 | { 87 | FOREACH( INativeControllerListener*, i, listeners) 88 | { 89 | i->MouseMoving(position); 90 | } 91 | } 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeCallbackService.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_NATIVE_CALLBACK_SERVICE_H 2 | #define __GAC_X11CAIRO_XLIB_NATIVE_CALLBACK_SERVICE_H 3 | 4 | #include 5 | #include "../XlibIncludes.h" 6 | 7 | 8 | namespace vl 9 | { 10 | namespace presentation 11 | { 12 | namespace x11cairo 13 | { 14 | namespace xlib 15 | { 16 | class XlibNativeCallbackService: public Object, public INativeCallbackService 17 | { 18 | protected: 19 | collections::List listeners; 20 | bool flag; 21 | 22 | public: 23 | virtual bool InstallListener(INativeControllerListener* listener); 24 | virtual bool UninstallListener(INativeControllerListener* listener); 25 | 26 | void CheckTimer(); 27 | void SetTimer(); 28 | void MouseUpEvent(MouseButton button, Point position); 29 | void MouseDownEvent(MouseButton button, Point position); 30 | void MouseMoveEvent(Point position); 31 | }; 32 | } 33 | } 34 | } 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeInputService.cpp: -------------------------------------------------------------------------------- 1 | #include "XlibNativeInputService.h" 2 | 3 | namespace vl 4 | { 5 | namespace presentation 6 | { 7 | namespace x11cairo 8 | { 9 | namespace xlib 10 | { 11 | void XlibNativeInputService::StartHookMouse() 12 | { 13 | //TODO 14 | } 15 | 16 | void XlibNativeInputService::StopHookMouse() 17 | { 18 | //TODO 19 | 20 | } 21 | 22 | bool XlibNativeInputService::IsHookingMouse() 23 | { 24 | //TODO 25 | return false; 26 | } 27 | 28 | void XlibNativeInputService::StartTimer() 29 | { 30 | struct itimerval timer; 31 | timer.it_interval.tv_usec = timerInterval; 32 | timer.it_interval.tv_sec = 0; 33 | timer.it_value.tv_usec = timerInterval; 34 | timer.it_value.tv_sec = 0; 35 | if(setitimer(ITIMER_REAL, &timer, NULL)) 36 | throw Exception(L"Failed to setup timer"); 37 | } 38 | 39 | void XlibNativeInputService::StopTimer() 40 | { 41 | setitimer(ITIMER_REAL, NULL, NULL); 42 | } 43 | 44 | bool XlibNativeInputService::IsTimerEnabled() 45 | { 46 | //TODO 47 | return false; 48 | } 49 | 50 | bool XlibNativeInputService::IsKeyPressing(vint code) 51 | { 52 | //TODO 53 | return false; 54 | } 55 | 56 | bool XlibNativeInputService::IsKeyToggled(vint code) 57 | { 58 | //TODO 59 | return false; 60 | } 61 | 62 | WString XlibNativeInputService::GetKeyName(vint code) 63 | { 64 | //TODO 65 | return WString(); 66 | } 67 | 68 | vint XlibNativeInputService::GetKey(const WString &name) 69 | { 70 | //TODO 71 | return 0; 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeInputService.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_NATIVE_INPUT_SERVICE_H 2 | #define __GAC_X11CAIRO_XLIB_NATIVE_INPUT_SERVICE_H 3 | 4 | #include 5 | #include 6 | #include "../XlibIncludes.h" 7 | 8 | namespace vl 9 | { 10 | namespace presentation 11 | { 12 | namespace x11cairo 13 | { 14 | namespace xlib 15 | { 16 | class XlibNativeInputService: public Object, public INativeInputService 17 | { 18 | protected: 19 | bool timerEnabled; 20 | const int timerInterval = 33333; 21 | 22 | public: 23 | virtual void StartHookMouse(); 24 | virtual void StopHookMouse(); 25 | virtual bool IsHookingMouse(); 26 | 27 | virtual void StartTimer(); 28 | virtual void StopTimer(); 29 | virtual bool IsTimerEnabled(); 30 | 31 | virtual bool IsKeyPressing(vint code); 32 | virtual bool IsKeyToggled(vint code); 33 | 34 | virtual WString GetKeyName(vint code); 35 | virtual vint GetKey(const WString& name); 36 | 37 | static void TimerSignalHandler(); 38 | }; 39 | } 40 | } 41 | } 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeResourceService.cpp: -------------------------------------------------------------------------------- 1 | #include "XlibNativeResourceService.h" 2 | 3 | namespace vl 4 | { 5 | namespace presentation 6 | { 7 | namespace x11cairo 8 | { 9 | namespace xlib 10 | { 11 | INativeCursor* XlibNativeResourceService::GetSystemCursor(INativeCursor::SystemCursorType type) 12 | { 13 | //TODO 14 | return NULL; 15 | } 16 | 17 | INativeCursor* XlibNativeResourceService::GetDefaultSystemCursor() 18 | { 19 | //TODO 20 | return NULL; 21 | } 22 | 23 | FontProperties XlibNativeResourceService::GetDefaultFont() 24 | { 25 | FontProperties prop; 26 | { 27 | prop.fontFamily = L"Sans"; 28 | prop.size = 12; 29 | prop.italic = false; 30 | prop.bold = false; 31 | prop.underline = false; 32 | prop.strikeline = false; 33 | prop.antialias = true; 34 | prop.verticalAntialias = true; 35 | } 36 | return prop; 37 | } 38 | 39 | void XlibNativeResourceService::SetDefaultFont(const FontProperties& value) 40 | { 41 | //TODO 42 | } 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeResourceService.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_NATIVE_RESOURCE_SERVICE_H 2 | #define __GAC_X11CAIRO_XLIB_NATIVE_RESOURCE_SERVICE_H 3 | 4 | #include 5 | 6 | namespace vl 7 | { 8 | namespace presentation 9 | { 10 | namespace x11cairo 11 | { 12 | namespace xlib 13 | { 14 | class XlibNativeResourceService: public Object, public INativeResourceService 15 | { 16 | INativeCursor* GetSystemCursor(INativeCursor::SystemCursorType type); 17 | INativeCursor* GetDefaultSystemCursor(); 18 | 19 | FontProperties GetDefaultFont(); 20 | void SetDefaultFont(const FontProperties& value); 21 | 22 | }; 23 | } 24 | } 25 | } 26 | } 27 | 28 | 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeScreenService.cpp: -------------------------------------------------------------------------------- 1 | #include "XlibNativeScreenService.h" 2 | #include "../XlibScreen.h" 3 | #include "../XlibWindow.h" 4 | 5 | namespace vl 6 | { 7 | namespace presentation 8 | { 9 | namespace x11cairo 10 | { 11 | namespace xlib 12 | { 13 | XlibNativeScreenService::XlibNativeScreenService(Display* display) 14 | : display (display), count(XScreenCount(display)), screens(new INativeScreen*[XScreenCount(display)]) 15 | { 16 | for(int i = 0; i < count; i++) 17 | { 18 | screens[i] = new XlibScreen(display, XScreenOfDisplay(display, i), i); 19 | } 20 | } 21 | 22 | XlibNativeScreenService::~XlibNativeScreenService() 23 | { 24 | for(int i = 0; i < count; i++) 25 | { 26 | delete screens[i]; 27 | } 28 | 29 | delete[] screens; 30 | } 31 | 32 | vint XlibNativeScreenService::GetScreenCount() 33 | { 34 | return count; 35 | } 36 | 37 | INativeScreen* XlibNativeScreenService::GetScreen(vint index) 38 | { 39 | return screens[index]; 40 | } 41 | 42 | INativeScreen* XlibNativeScreenService::GetScreen(INativeWindow* window) 43 | { 44 | XlibWindow *actualWindow = dynamic_cast(window); 45 | if(actualWindow) 46 | { 47 | XWindowAttributes attr; 48 | XGetWindowAttributes(display, actualWindow->GetWindow(), &attr); 49 | return screens[XScreenNumberOfScreen(attr.screen)]; 50 | } 51 | 52 | return NULL; 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeScreenService.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_NATIVE_SCREEN_SERVICE_H 2 | #define __GAC_X11CAIRO_XLIB_NATIVE_SCREEN_SERVICE_H 3 | 4 | #include 5 | #include "../XlibIncludes.h" 6 | 7 | namespace vl 8 | { 9 | namespace presentation 10 | { 11 | namespace x11cairo 12 | { 13 | namespace xlib 14 | { 15 | class XlibNativeScreenService: public Object, public INativeScreenService 16 | { 17 | protected: 18 | Display* display; 19 | vint count; 20 | INativeScreen** screens; 21 | public: 22 | XlibNativeScreenService(Display* display); 23 | ~XlibNativeScreenService(); 24 | 25 | virtual vint GetScreenCount(); 26 | virtual INativeScreen* GetScreen(vint index); 27 | virtual INativeScreen* GetScreen(INativeWindow* window); 28 | }; 29 | } 30 | } 31 | } 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeWindowService.cpp: -------------------------------------------------------------------------------- 1 | #include "XlibNativeWindowService.h" 2 | #include "../XlibNativeController.h" 3 | 4 | #include 5 | 6 | using namespace vl::presentation; 7 | using namespace vl::collections; 8 | 9 | namespace vl 10 | { 11 | namespace presentation 12 | { 13 | namespace x11cairo 14 | { 15 | namespace xlib 16 | { 17 | XlibNativeWindowService::XlibNativeWindowService(Display* display, PosixAsyncService* asyncService, XlibNativeCallbackService* callbackService): 18 | display(display), 19 | asyncService(asyncService), 20 | callbackService(callbackService), 21 | mainWindow(NULL) 22 | { 23 | recordHelper = new XlibXRecordMouseHookHelper(XDisplayString(display)); 24 | } 25 | 26 | XlibNativeWindowService::~XlibNativeWindowService() 27 | { 28 | delete recordHelper; 29 | } 30 | 31 | INativeWindow *XlibNativeWindowService::CreateNativeWindow() 32 | { 33 | XlibWindow *window = new XlibWindow(display); 34 | windows.Add(window); 35 | 36 | return window; 37 | } 38 | 39 | void XlibNativeWindowService::DestroyNativeWindow(INativeWindow *window) 40 | { 41 | if (window) 42 | { 43 | XlibWindow* actualWindow = dynamic_cast(window); 44 | if(actualWindow) 45 | { 46 | windows.Remove(actualWindow); 47 | delete window; 48 | } 49 | else 50 | { 51 | throw Exception(L"Wrong Window Type"); 52 | } 53 | } 54 | } 55 | 56 | INativeWindow* XlibNativeWindowService::GetMainWindow() 57 | { 58 | if(windows.Count() > 0) 59 | { 60 | return windows[0]; 61 | } 62 | else return NULL; 63 | } 64 | 65 | INativeWindow* XlibNativeWindowService::GetWindow(Point location) 66 | { 67 | // Find the top-most window 68 | Window seekWindow = XDefaultRootWindow(display); 69 | Window resultWindow = seekWindow; 70 | int x = 0, y = 0; 71 | 72 | while(true) 73 | { 74 | if(XTranslateCoordinates(display, XDefaultRootWindow(display), seekWindow, 75 | location.x, location.y, &x, &y, &resultWindow) == XLIB_TRUE) 76 | { 77 | if(resultWindow != XLIB_NONE) 78 | { 79 | seekWindow = resultWindow; 80 | } 81 | else 82 | { 83 | return FindWindow(seekWindow); 84 | } 85 | } 86 | else break; 87 | } 88 | 89 | return NULL; 90 | } 91 | 92 | XlibWindow* XlibNativeWindowService::FindWindow(Window win) 93 | { 94 | FOREACH(XlibWindow*, i, windows) 95 | { 96 | if(i->GetWindow() == win) 97 | { 98 | return i; 99 | } 100 | } 101 | 102 | return NULL; 103 | } 104 | 105 | 106 | NativeWindowMouseInfo XlibNativeWindowService::MouseStateMaskToInfo(int x, int y, unsigned int state) 107 | { 108 | NativeWindowMouseInfo result; 109 | { 110 | result.x = x; 111 | result.y = y; 112 | result.left = state & Button1Mask; 113 | result.right = state & Button2Mask; 114 | result.middle = state & Button3Mask; 115 | result.ctrl = state & ControlMask; 116 | result.shift = state & ShiftMask; 117 | result.wheel = 0; // TODO 118 | result.nonClient = false; 119 | } 120 | 121 | return result; 122 | } 123 | 124 | MouseButton XlibNativeWindowService::XButtonCodeToButton(unsigned int button) 125 | { 126 | switch(button) 127 | { 128 | default: 129 | case Button1: 130 | return MouseButton::LBUTTON; 131 | case Button2: 132 | return MouseButton::RBUTTON; 133 | case Button3: 134 | return MouseButton::MBUTTON; 135 | } 136 | } 137 | 138 | void XlibNativeWindowService::Run(INativeWindow *window) 139 | { 140 | XEvent event; 141 | mainWindow = dynamic_cast(window); 142 | 143 | if(!mainWindow) 144 | { 145 | throw Exception(L"Invalid Window Type"); 146 | } 147 | 148 | mainWindow->Show(); 149 | recordHelper->StartCapture(); 150 | 151 | while(true) 152 | { 153 | 154 | recordHelper->Update(); 155 | 156 | recordHelper->ProcessEvents( 157 | [this](MouseEvent ev) 158 | { 159 | switch(ev.type) 160 | { 161 | case MouseEventType::BUTTONDOWN: 162 | callbackService->MouseDownEvent(ev.button, ev.position); 163 | break; 164 | case MouseEventType::BUTTONUP: 165 | callbackService->MouseUpEvent(ev.button, ev.position); 166 | break; 167 | case MouseEventType::POINTERMOVE: 168 | callbackService->MouseMoveEvent(ev.position); 169 | break; 170 | } 171 | }); 172 | 173 | 174 | while(XPending(mainWindow->GetDisplay())) 175 | { 176 | XlibWindow* evWindow = NULL; 177 | XNextEvent(mainWindow->GetDisplay(), &event); 178 | switch(event.type) 179 | { 180 | case ButtonPress: 181 | if((evWindow = FindWindow(event.xbutton.window)) != NULL) 182 | evWindow->MouseDownEvent( 183 | XButtonCodeToButton(event.xbutton.button), 184 | MouseStateMaskToInfo(event.xbutton.x, event.xbutton.y, event.xbutton.state) 185 | ); 186 | 187 | break; 188 | 189 | case ButtonRelease: 190 | if((evWindow = FindWindow(event.xbutton.window)) != NULL) 191 | evWindow->MouseUpEvent( 192 | XButtonCodeToButton(event.xbutton.button), 193 | MouseStateMaskToInfo(event.xbutton.x, event.xbutton.y, event.xbutton.state) 194 | ); 195 | break; 196 | 197 | case MotionNotify: 198 | if((evWindow = FindWindow(event.xmotion.window)) != NULL) 199 | evWindow->MouseMoveEvent( 200 | MouseStateMaskToInfo(event.xmotion.x, event.xmotion.y, event.xbutton.state) 201 | ); 202 | break; 203 | 204 | case EnterNotify: 205 | if((evWindow = FindWindow(event.xcrossing.window)) != NULL) 206 | evWindow->MouseEnterEvent(); 207 | break; 208 | 209 | case LeaveNotify: 210 | if((evWindow = FindWindow(event.xcrossing.window)) != NULL) 211 | evWindow->MouseEnterEvent(); 212 | break; 213 | 214 | case ClientMessage: 215 | // TODO: Handle different client messages 216 | goto Cleanup; 217 | 218 | case ConfigureNotify: 219 | if((evWindow = FindWindow(event.xconfigure.window)) != NULL) 220 | evWindow->ResizeEvent(event.xconfigure.width, event.xconfigure.height); 221 | break; 222 | 223 | case Expose: 224 | case GraphicsExpose: 225 | if((evWindow = FindWindow(event.xexpose.window)) != NULL) 226 | evWindow->RedrawContent(); 227 | break; 228 | 229 | case VisibilityNotify: 230 | if(event.xvisibility.state != VisibilityUnobscured) 231 | { 232 | FOREACH(XlibWindow*, i, windows) 233 | { 234 | i->VisibilityEvent(event.xvisibility.window); 235 | } 236 | } 237 | break; 238 | 239 | default: 240 | break; 241 | } 242 | } 243 | 244 | asyncService->ExecuteAsyncTasks(); 245 | callbackService->CheckTimer(); 246 | 247 | XFlush(mainWindow->GetDisplay()); 248 | 249 | pause(); 250 | } 251 | 252 | Cleanup: 253 | recordHelper->EndCapture(); 254 | XFlush(mainWindow->GetDisplay()); 255 | 256 | mainWindow = NULL; 257 | 258 | return; 259 | } 260 | } 261 | } 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/ServicesImpl/XlibNativeWindowService.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_NATIVE_WINDOW_SERVICE_H 2 | #define __GAC_X11CAIRO_XLIB_NATIVE_WINDOW_SERVICE_H 3 | 4 | #include 5 | #include "../XlibIncludes.h" 6 | #include "../XlibWindow.h" 7 | #include "../XlibXRecordMouseHookHelper.h" 8 | #include "../../Common/ServicesImpl/PosixAsyncService.h" 9 | #include "XlibNativeCallbackService.h" 10 | 11 | namespace vl 12 | { 13 | namespace presentation 14 | { 15 | namespace x11cairo 16 | { 17 | namespace xlib 18 | { 19 | class XlibNativeWindowService: public Object, public virtual INativeWindowService 20 | { 21 | protected: 22 | Display* display; 23 | PosixAsyncService* asyncService; 24 | XlibNativeCallbackService* callbackService; 25 | XlibXRecordMouseHookHelper* recordHelper; 26 | XlibWindow* mainWindow; 27 | vl::collections::List windows; 28 | bool timerFlag; 29 | 30 | XlibWindow* FindWindow(Window win); 31 | void DispatchGlobalMouseEvent(const MouseEvent& ev); 32 | NativeWindowMouseInfo MouseStateMaskToInfo(int x, int y, unsigned int state); 33 | MouseButton XButtonCodeToButton(unsigned int button); 34 | 35 | public: 36 | XlibNativeWindowService (Display* display, PosixAsyncService* asyncService, XlibNativeCallbackService* callbackService); 37 | 38 | virtual ~XlibNativeWindowService (); 39 | 40 | virtual INativeWindow *CreateNativeWindow (); 41 | 42 | virtual void DestroyNativeWindow (INativeWindow *window); 43 | 44 | virtual INativeWindow *GetMainWindow (); 45 | 46 | virtual INativeWindow *GetWindow (Point location); 47 | 48 | virtual void Run (INativeWindow *window); 49 | }; 50 | } 51 | } 52 | } 53 | } 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibAtoms.cpp: -------------------------------------------------------------------------------- 1 | #include "XlibAtoms.h" 2 | 3 | #define DEFINE_ATOM(x) \ 4 | Atom XlibAtoms::x = XLIB_NONE; 5 | 6 | #define INIT_ATOM(x) \ 7 | x = XInternAtom(display, #x, XLIB_FALSE); \ 8 | map.Add(#x, x); 9 | 10 | namespace vl 11 | { 12 | namespace presentation 13 | { 14 | namespace x11cairo 15 | { 16 | namespace xlib 17 | { 18 | vl::collections::Dictionary XlibAtoms::map; 19 | 20 | DEFINE_ATOM(WM_DELETE_WINDOW); 21 | DEFINE_ATOM(_MOTIF_WM_HINTS); 22 | DEFINE_ATOM(_NET_WM_WINDOW_TYPE); 23 | DEFINE_ATOM(_NET_WM_WINDOW_TYPE_NORMAL); 24 | DEFINE_ATOM(_NET_WM_WINDOW_TYPE_POPUP_MENU); 25 | 26 | void XlibAtoms::Initialize(Display* display) 27 | { 28 | static bool initialized = false; 29 | if(!initialized) 30 | { 31 | INIT_ATOM(WM_DELETE_WINDOW); 32 | INIT_ATOM(_MOTIF_WM_HINTS); 33 | INIT_ATOM(_NET_WM_WINDOW_TYPE); 34 | INIT_ATOM(_NET_WM_WINDOW_TYPE_NORMAL); 35 | INIT_ATOM(_NET_WM_WINDOW_TYPE_POPUP_MENU); 36 | 37 | initialized = true; 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibAtoms.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_ATOMS_H 2 | #define __GAC_X11CAIRO_XLIB_ATOMS_H 3 | 4 | #include 5 | #include "XlibIncludes.h" 6 | 7 | namespace vl 8 | { 9 | namespace presentation 10 | { 11 | namespace x11cairo 12 | { 13 | namespace xlib 14 | { 15 | struct XlibAtoms 16 | { 17 | static vl::collections::Dictionary map; 18 | static Atom WM_DELETE_WINDOW; 19 | static Atom _MOTIF_WM_HINTS; 20 | static Atom _NET_WM_WINDOW_TYPE; 21 | static Atom _NET_WM_WINDOW_TYPE_NORMAL; 22 | static Atom _NET_WM_WINDOW_TYPE_POPUP_MENU; 23 | 24 | static void Initialize(Display* display); 25 | }; 26 | } 27 | } 28 | } 29 | } 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibCommon.cpp: -------------------------------------------------------------------------------- 1 | #include "XlibCommon.h" 2 | #include 3 | 4 | namespace vl 5 | { 6 | namespace presentation 7 | { 8 | namespace x11cairo 9 | { 10 | namespace xlib 11 | { 12 | bool CheckXdbeExtension(Display* display) 13 | { 14 | int major, minor; 15 | if(XdbeQueryExtension(display, &major, &minor)) 16 | { 17 | if(major >= 1) 18 | return true; 19 | } 20 | 21 | return false; 22 | } 23 | 24 | bool CheckXRecordExtension(Display* display) 25 | { 26 | int major, minor; 27 | if(XRecordQueryVersion(display, &major, &minor)) 28 | { 29 | if(major >= 1) 30 | return true; 31 | } 32 | return false; 33 | } 34 | } 35 | } 36 | } 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibCommon.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_COMMON_H 2 | #define __GAC_X11CAIRO_XLIB_COMMON_H 3 | 4 | #include 5 | #include "XlibIncludes.h" 6 | 7 | namespace vl 8 | { 9 | namespace presentation 10 | { 11 | namespace x11cairo 12 | { 13 | namespace xlib 14 | { 15 | enum class MouseButton 16 | { 17 | LBUTTON, 18 | RBUTTON, 19 | MBUTTON 20 | }; 21 | 22 | enum class MouseEventType 23 | { 24 | BUTTONDOWN, 25 | BUTTONUP, 26 | POINTERMOVE 27 | }; 28 | 29 | struct MouseEvent 30 | { 31 | MouseButton button; 32 | MouseEventType type; 33 | vl::presentation::Point position; 34 | 35 | MouseEvent(MouseButton button, MouseEventType type, int rootX, int rootY) 36 | : button(button), type(type), position(rootX, rootY) 37 | { 38 | } 39 | 40 | MouseEvent() 41 | { 42 | } 43 | }; 44 | 45 | struct MotifWmHints 46 | { 47 | long flags; 48 | long functions; 49 | long decorations; 50 | long input_mode; 51 | long status; 52 | }; 53 | 54 | bool CheckXdbeExtension(Display*); 55 | bool CheckXRecordExtension(Display*); 56 | } 57 | } 58 | } 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibIncludes.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_INCLUDES_H 2 | #define __GAC_X11CAIRO_XLIB_INCLUDES_H 3 | 4 | extern "C" 5 | { 6 | #include 7 | #include 8 | #include 9 | } 10 | 11 | const Bool XLIB_TRUE = True; 12 | const Bool XLIB_FALSE = False; 13 | const Status XLIB_SUCCESS = Success; 14 | const Status XLIB_NONE = None; 15 | 16 | #undef True 17 | #undef False 18 | #undef Success 19 | #undef None 20 | 21 | #include "XlibCommon.h" 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibNativeController.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "XlibAtoms.h" 4 | #include "XlibNativeController.h" 5 | #include "ServicesImpl/XlibNativeWindowService.h" 6 | #include "ServicesImpl/XlibNativeScreenService.h" 7 | #include "ServicesImpl/XlibNativeResourceService.h" 8 | #include "ServicesImpl/XlibNativeInputService.h" 9 | #include "ServicesImpl/XlibNativeCallbackService.h" 10 | #include "../Common/ServicesImpl/PosixAsyncService.h" 11 | 12 | #include "XlibIncludes.h" 13 | 14 | 15 | 16 | namespace vl 17 | { 18 | namespace presentation 19 | { 20 | namespace x11cairo 21 | { 22 | namespace xlib 23 | { 24 | class XlibNativeController : public Object, public virtual INativeController 25 | { 26 | protected: 27 | //Xlib Display 28 | Display *display; 29 | 30 | //Native Services 31 | XlibNativeCallbackService *callbackService; 32 | XlibNativeResourceService *resourceService; 33 | PosixAsyncService *asyncService; 34 | INativeClipboardService *clipboardService; 35 | INativeImageService *imageService; 36 | XlibNativeScreenService *screenService; 37 | XlibNativeWindowService *windowService; 38 | XlibNativeInputService *inputService; 39 | INativeDialogService *dialogService; 40 | 41 | public: 42 | XlibNativeController(const char *displayString = NULL) 43 | { 44 | XSetErrorHandler(NULL); 45 | display = XOpenDisplay(displayString); 46 | if(!display) 47 | { 48 | throw Exception(L"Unable to open display."); 49 | } 50 | 51 | asyncService = new PosixAsyncService(); 52 | screenService = new XlibNativeScreenService(display); 53 | inputService = new XlibNativeInputService(); 54 | callbackService = new XlibNativeCallbackService(); 55 | windowService = new XlibNativeWindowService(display, asyncService, callbackService); 56 | resourceService = new XlibNativeResourceService(); 57 | 58 | XlibAtoms::Initialize(display); 59 | 60 | if(signal(SIGALRM, XlibNativeController::TimerSignalHandler)) 61 | { 62 | throw Exception(L"Unable to set signal handler"); 63 | } 64 | } 65 | 66 | virtual ~XlibNativeController() 67 | { 68 | delete resourceService; 69 | delete windowService; 70 | delete callbackService; 71 | delete inputService; 72 | delete screenService; 73 | delete asyncService; 74 | 75 | XCloseDisplay(display); 76 | } 77 | 78 | virtual INativeCallbackService *CallbackService() 79 | { 80 | return callbackService; 81 | } 82 | 83 | virtual INativeResourceService *ResourceService() 84 | { 85 | return resourceService; 86 | } 87 | 88 | virtual INativeAsyncService *AsyncService() 89 | { 90 | return asyncService; 91 | } 92 | 93 | virtual INativeClipboardService *ClipboardService() 94 | { 95 | //TODO 96 | return NULL; 97 | } 98 | 99 | virtual INativeImageService *ImageService() 100 | { 101 | //TODO 102 | return NULL; 103 | } 104 | 105 | virtual INativeScreenService *ScreenService() 106 | { 107 | return screenService; 108 | } 109 | 110 | virtual INativeWindowService *WindowService() 111 | { 112 | return windowService; 113 | } 114 | 115 | virtual INativeInputService *InputService() 116 | { 117 | return inputService; 118 | } 119 | 120 | virtual INativeDialogService *DialogService() 121 | { 122 | //TODO 123 | return NULL; 124 | } 125 | 126 | virtual WString GetOSVersion() 127 | { 128 | return WString(L"Linux"); 129 | } 130 | 131 | virtual WString GetExecutablePath() 132 | { 133 | //TODO 134 | return WString(); 135 | } 136 | 137 | static void TimerSignalHandler(int signal) 138 | { 139 | if(XlibNativeController* controller = dynamic_cast(GetCurrentController())) 140 | { 141 | XlibNativeCallbackService* callbackService = dynamic_cast(controller->CallbackService()); 142 | if(callbackService) 143 | { 144 | callbackService->SetTimer(); 145 | } 146 | } 147 | } 148 | }; 149 | 150 | vl::presentation::INativeController *CreateXlibCairoNativeController(const char *displayname) 151 | { 152 | return new XlibNativeController(displayname); 153 | } 154 | 155 | 156 | void DestroyXlibCairoNativeController(vl::presentation::INativeController *controller) 157 | { 158 | delete controller; 159 | } 160 | 161 | 162 | void X11CairoMain() 163 | { 164 | GuiApplicationMain(); 165 | } 166 | 167 | } 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibNativeController.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_NATIVE_CONTROLLER_H 2 | #define __GAC_X11CAIRO_XLIB_NATIVE_CONTROLLER_H 3 | 4 | #include 5 | 6 | using namespace vl::presentation; 7 | 8 | namespace vl 9 | { 10 | namespace presentation 11 | { 12 | namespace x11cairo 13 | { 14 | namespace xlib 15 | { 16 | extern INativeController *CreateXlibCairoNativeController(const char *displayname = NULL); 17 | 18 | extern void DestroyXlibCairoNativeController(INativeController *controller); 19 | 20 | extern void X11CairoMain(); 21 | } 22 | } 23 | } 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibScreen.cpp: -------------------------------------------------------------------------------- 1 | #include "XlibScreen.h" 2 | 3 | 4 | namespace vl 5 | { 6 | namespace presentation 7 | { 8 | namespace x11cairo 9 | { 10 | namespace xlib 11 | { 12 | XlibScreen::XlibScreen(Display* display, Screen* screen, int id) 13 | : display (display), 14 | screen (screen), 15 | id (id) 16 | { 17 | 18 | } 19 | 20 | Rect XlibScreen::GetBounds() 21 | { 22 | //TODO 23 | return GetClientBounds(); 24 | } 25 | 26 | Rect XlibScreen::GetClientBounds() 27 | { 28 | return Rect(0, 0, XWidthOfScreen(screen), XHeightOfScreen(screen)); 29 | } 30 | 31 | WString XlibScreen::GetName() 32 | { 33 | return WString(L"Screen ") + WString(XScreenNumberOfScreen(screen)); 34 | } 35 | 36 | bool XlibScreen::IsPrimary() 37 | { 38 | //TODO 39 | return true; 40 | } 41 | } 42 | } 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibScreen.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_SCREEN_H 2 | #define __GAC_X11CAIRO_XLIB_SCREEN_H 3 | 4 | #include 5 | #include "XlibIncludes.h" 6 | 7 | namespace vl 8 | { 9 | namespace presentation 10 | { 11 | namespace x11cairo 12 | { 13 | namespace xlib 14 | { 15 | class XlibScreen: public Object, public INativeScreen 16 | { 17 | protected: 18 | Display* display; 19 | Screen* screen; 20 | int id; 21 | public: 22 | XlibScreen(Display* display, Screen* screen, int id); 23 | Rect GetBounds(); 24 | Rect GetClientBounds(); 25 | WString GetName(); 26 | bool IsPrimary(); 27 | }; 28 | } 29 | } 30 | } 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibWindow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "XlibAtoms.h" 3 | #include "XlibWindow.h" 4 | 5 | using namespace vl::collections; 6 | 7 | namespace vl 8 | { 9 | namespace presentation 10 | { 11 | namespace x11cairo 12 | { 13 | namespace xlib 14 | { 15 | XlibWindow::XlibWindow(Display *display): 16 | display(display), 17 | title(), 18 | renderTarget(nullptr), 19 | resizable (false), 20 | doubleBuffer(false), 21 | customFrameMode(false), 22 | visible(false), 23 | backBuffer(XLIB_NONE), 24 | parentWindow(NULL), 25 | bounds(0, 0, 400, 200), 26 | clientSize(400, 200) 27 | { 28 | this->display = display; 29 | window = XCreateWindow( 30 | display, //Display 31 | XRootWindow(display, 0), //Root Display 32 | 0, //X 33 | 0, //Y 34 | 400, //Width 35 | 200, //Height 36 | 2, //Border Width 37 | CopyFromParent, //Depth 38 | InputOutput, //Class 39 | CopyFromParent, //Visual 40 | 0, //Value Mask 41 | NULL //Attributes 42 | ); 43 | 44 | 45 | XSelectInput(display, window, PointerMotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | SubstructureNotifyMask | VisibilityChangeMask | ExposureMask); 46 | XSetWMProtocols(display, window, &XlibAtoms::WM_DELETE_WINDOW, 1); 47 | 48 | CheckDoubleBuffer(); 49 | 50 | UpdateTitle(); 51 | XSync(display, false); 52 | } 53 | 54 | XlibWindow::~XlibWindow() 55 | { 56 | delete renderTarget; 57 | XDestroyWindow(display, window); 58 | } 59 | 60 | void XlibWindow::CheckDoubleBuffer() 61 | { 62 | #ifdef GAC_X11_DOUBLEBUFFER 63 | if(CheckXdbeExtension(display)) 64 | { 65 | RebuildDoubleBuffer(); 66 | if(backBuffer != XLIB_NONE) 67 | { 68 | doubleBuffer = true; 69 | } 70 | } 71 | #endif 72 | } 73 | 74 | void XlibWindow::RebuildDoubleBuffer() 75 | { 76 | if(backBuffer != XLIB_NONE) 77 | XdbeDeallocateBackBufferName(display, backBuffer); 78 | backBuffer = XdbeAllocateBackBufferName(display, window, XdbeUndefined); 79 | } 80 | 81 | XdbeBackBuffer XlibWindow::GetBackBuffer() 82 | { 83 | return backBuffer; 84 | } 85 | 86 | bool XlibWindow::GetDoubleBuffer() 87 | { 88 | return doubleBuffer; 89 | } 90 | 91 | void XlibWindow::SwapBuffer() 92 | { 93 | if(doubleBuffer) 94 | { 95 | XdbeBackBufferAttributes* attributes = XdbeGetBackBufferAttributes(display, backBuffer); 96 | XdbeSwapInfo info; 97 | { 98 | info.swap_window = window; 99 | info.swap_action = XdbeCopied; 100 | } 101 | 102 | XdbeSwapBuffers(display, &info, 1); 103 | XFree(attributes); 104 | } 105 | } 106 | 107 | void XlibWindow::UpdateResizable() 108 | { 109 | XSizeHints *hints = XAllocSizeHints(); 110 | Size currentSize = GetClientSize(); 111 | XGetNormalHints(display, window, hints); 112 | if(resizable) 113 | { 114 | hints->min_width = currentSize.x; 115 | hints->min_height = currentSize.y; 116 | hints->max_width = currentSize.x; 117 | hints->max_height = currentSize.y; 118 | } 119 | else 120 | { 121 | hints->min_width = 0; 122 | hints->min_height = 0; 123 | hints->max_width = INT_MAX; 124 | hints->max_height = INT_MAX; 125 | } 126 | XSetNormalHints(display, window, hints); 127 | XFree(hints); 128 | } 129 | 130 | void XlibWindow::GetParentList(vl::collections::List& result) 131 | { 132 | XlibWindow* win = this; 133 | 134 | while(win) 135 | { 136 | result.Add(win->GetWindow()); 137 | win = dynamic_cast(win->GetParent()); 138 | } 139 | } 140 | 141 | Window XlibWindow::GetWindow() 142 | { 143 | return window; 144 | } 145 | 146 | Display* XlibWindow::GetDisplay() 147 | { 148 | return display; 149 | } 150 | 151 | void XlibWindow::SetRenderTarget(elements::IGuiGraphicsRenderTarget* target) 152 | { 153 | renderTarget = target; 154 | } 155 | 156 | elements::IGuiGraphicsRenderTarget* XlibWindow::GetRenderTarget() 157 | { 158 | return renderTarget; 159 | } 160 | 161 | void XlibWindow::UpdateTitle() 162 | { 163 | AString narrow = wtoa(title); 164 | XStoreName(display, window, narrow.Buffer()); 165 | } 166 | 167 | void XlibWindow::ResizeEvent(int width, int height) 168 | { 169 | RebuildDoubleBuffer(); 170 | Rect newBound = GetBounds(); 171 | FOREACH(INativeWindowListener*, i, listeners) 172 | { 173 | i->Moving(newBound, true); 174 | i->Moved(); 175 | } 176 | 177 | GetBounds(); 178 | GetClientSize(); 179 | RedrawContent(); 180 | } 181 | 182 | void XlibWindow::MouseUpEvent(MouseButton button, NativeWindowMouseInfo info) 183 | { 184 | switch(button) 185 | { 186 | case MouseButton::LBUTTON: 187 | FOREACH(INativeWindowListener*, i, listeners) 188 | { 189 | i->LeftButtonUp(info); 190 | } 191 | break; 192 | 193 | case MouseButton::RBUTTON: 194 | FOREACH(INativeWindowListener*, i, listeners) 195 | { 196 | i->RightButtonUp(info); 197 | } 198 | break; 199 | 200 | case MouseButton::MBUTTON: 201 | FOREACH(INativeWindowListener*, i, listeners) 202 | { 203 | i->MiddleButtonUp(info); 204 | } 205 | break; 206 | } 207 | } 208 | 209 | void XlibWindow::MouseDownEvent(MouseButton button, NativeWindowMouseInfo info) 210 | { 211 | switch(button) 212 | { 213 | case MouseButton::LBUTTON: 214 | FOREACH(INativeWindowListener*, i, listeners) 215 | { 216 | i->LeftButtonDown(info); 217 | } 218 | break; 219 | 220 | case MouseButton::RBUTTON: 221 | FOREACH(INativeWindowListener*, i, listeners) 222 | { 223 | i->RightButtonDown(info); 224 | } 225 | break; 226 | 227 | case MouseButton::MBUTTON: 228 | FOREACH(INativeWindowListener*, i, listeners) 229 | { 230 | i->MiddleButtonDown(info); 231 | } 232 | break; 233 | 234 | } 235 | } 236 | 237 | void XlibWindow::MouseMoveEvent(NativeWindowMouseInfo info) 238 | { 239 | FOREACH(INativeWindowListener*, i, listeners) 240 | { 241 | i->MouseMoving(info); 242 | } 243 | } 244 | 245 | void XlibWindow::MouseEnterEvent() 246 | { 247 | FOREACH(INativeWindowListener*, i, listeners) 248 | { 249 | i->MouseEntered(); 250 | } 251 | } 252 | 253 | void XlibWindow::MouseLeaveEvent() 254 | { 255 | FOREACH(INativeWindowListener*, i, listeners) 256 | { 257 | i->MouseLeaved(); 258 | } 259 | } 260 | 261 | void XlibWindow::VisibilityEvent(Window window) 262 | { 263 | if(visible && parentWindow) 264 | { 265 | collections::List windows; 266 | GetParentList(windows); 267 | XRestackWindows(display, &windows[0], windows.Count()); 268 | } 269 | } 270 | 271 | void XlibWindow::Show() 272 | { 273 | XMapWindow(display, window); 274 | 275 | visible = true; 276 | SetBounds(bounds); 277 | GetClientSize(); 278 | } 279 | 280 | void XlibWindow::Hide() 281 | { 282 | XUnmapWindow(display, window); 283 | 284 | visible = false; 285 | } 286 | 287 | Rect XlibWindow::GetBounds() 288 | { 289 | //TODO 290 | if(visible) 291 | { 292 | int x, y; 293 | Window child; 294 | XWindowAttributes attr; 295 | XGetWindowAttributes(display, window, &attr); 296 | XTranslateCoordinates(display, window, XDefaultRootWindow(display), 0, 0, &x, &y, &child); 297 | 298 | bounds = Rect(x, y, x + attr.width, y + attr.height); 299 | } 300 | 301 | return bounds; 302 | } 303 | 304 | void XlibWindow::SetBounds(const Rect &bounds) 305 | { 306 | //TODO 307 | this->bounds = bounds; 308 | if(visible) 309 | XMoveResizeWindow(display, window, bounds.x1, bounds.y1, bounds.Width(), bounds.Height()); 310 | } 311 | 312 | Size XlibWindow::GetClientSize() 313 | { 314 | if(visible) 315 | { 316 | XWindowAttributes attr; 317 | XGetWindowAttributes(display, window, &attr); 318 | clientSize = Size(attr.width, attr.height); 319 | } 320 | 321 | return clientSize; 322 | } 323 | 324 | void XlibWindow::SetClientSize(Size size) 325 | { 326 | clientSize = size; 327 | if(visible) 328 | XResizeWindow(display, window, size.x, size.y); 329 | } 330 | 331 | Rect XlibWindow::GetClientBoundsInScreen() 332 | { 333 | //TODO 334 | return GetBounds(); 335 | } 336 | 337 | WString XlibWindow::GetTitle() 338 | { 339 | return title; 340 | } 341 | 342 | void XlibWindow::SetTitle(WString title) 343 | { 344 | this->title = title; 345 | UpdateTitle(); 346 | } 347 | 348 | INativeCursor *XlibWindow::GetWindowCursor() 349 | { 350 | //TODO 351 | return NULL; 352 | } 353 | 354 | void XlibWindow::SetWindowCursor(INativeCursor *cursor) 355 | { 356 | //TODO 357 | } 358 | 359 | Point XlibWindow::GetCaretPoint() 360 | { 361 | //TODO 362 | return Point(); 363 | } 364 | 365 | void XlibWindow::SetCaretPoint(Point point) 366 | { 367 | //TODO 368 | } 369 | 370 | INativeWindow *XlibWindow::GetParent() 371 | { 372 | return parentWindow; 373 | } 374 | 375 | void XlibWindow::SetParent(INativeWindow *parent) 376 | { 377 | parentWindow = dynamic_cast(parent); 378 | 379 | if(parentWindow) 380 | { 381 | XChangeProperty(display, window, XlibAtoms::_NET_WM_WINDOW_TYPE, XlibAtoms::_NET_WM_WINDOW_TYPE, 32, PropModeReplace, 382 | (unsigned char*)&XlibAtoms::_NET_WM_WINDOW_TYPE_POPUP_MENU, 1); 383 | } 384 | } 385 | 386 | bool XlibWindow::GetAlwaysPassFocusToParent() 387 | { 388 | //TODO 389 | return false; 390 | } 391 | 392 | void XlibWindow::SetAlwaysPassFocusToParent(bool value) 393 | { 394 | //TODO 395 | } 396 | 397 | void XlibWindow::EnableCustomFrameMode() 398 | { 399 | MotifWmHints hints; 400 | 401 | hints.flags = 1 << 1; 402 | hints.decorations = 0; 403 | 404 | XChangeProperty(display, window, XlibAtoms::_MOTIF_WM_HINTS, XlibAtoms::_MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char*) &hints, 5); 405 | 406 | customFrameMode = true; 407 | } 408 | 409 | void XlibWindow::DisableCustomFrameMode() 410 | { 411 | MotifWmHints hints; 412 | 413 | hints.flags = 1 << 1; 414 | hints.decorations = 1; 415 | 416 | XChangeProperty(display, window, XlibAtoms::_MOTIF_WM_HINTS, XlibAtoms::_MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char*) &hints, 5); 417 | 418 | customFrameMode = false; 419 | } 420 | 421 | bool XlibWindow::IsCustomFrameModeEnabled() 422 | { 423 | return customFrameMode; 424 | } 425 | 426 | XlibWindow::WindowSizeState XlibWindow::GetSizeState() 427 | { 428 | //TODO 429 | return XlibWindow::WindowSizeState::Restored; 430 | } 431 | 432 | void XlibWindow::ShowDeactivated() 433 | { 434 | //TODO 435 | Show(); 436 | } 437 | 438 | void XlibWindow::ShowRestored() 439 | { 440 | //TODO 441 | Show(); 442 | } 443 | 444 | void XlibWindow::ShowMaximized() 445 | { 446 | //TODO 447 | Show(); 448 | } 449 | 450 | void XlibWindow::ShowMinimized() 451 | { 452 | //TODO 453 | Show(); 454 | } 455 | 456 | bool XlibWindow::IsVisible() 457 | { 458 | return visible; 459 | } 460 | 461 | void XlibWindow::Enable() 462 | { 463 | //TODO 464 | } 465 | 466 | void XlibWindow::Disable() 467 | { 468 | //TODO 469 | } 470 | 471 | bool XlibWindow::IsEnabled() 472 | { 473 | //TODO 474 | return true; 475 | } 476 | 477 | void XlibWindow::SetFocus() 478 | { 479 | //TODO 480 | } 481 | 482 | bool XlibWindow::IsFocused() 483 | { 484 | //TODO 485 | return true; 486 | } 487 | 488 | void XlibWindow::SetActivate() 489 | { 490 | //TODO 491 | } 492 | 493 | bool XlibWindow::IsActivated() 494 | { 495 | //TODO 496 | return true; 497 | } 498 | 499 | void XlibWindow::ShowInTaskBar() 500 | { 501 | //TODO 502 | } 503 | 504 | void XlibWindow::HideInTaskBar() 505 | { 506 | //TODO 507 | } 508 | 509 | bool XlibWindow::IsAppearedInTaskBar() 510 | { 511 | //TODO 512 | return true; 513 | } 514 | 515 | void XlibWindow::EnableActivate() 516 | { 517 | //TODO 518 | } 519 | 520 | void XlibWindow::DisableActivate() 521 | { 522 | //TODO 523 | } 524 | 525 | bool XlibWindow::IsEnabledActivate() 526 | { 527 | //TODO 528 | return true; 529 | } 530 | 531 | bool XlibWindow::RequireCapture() 532 | { 533 | //TODO 534 | return false; 535 | } 536 | 537 | bool XlibWindow::ReleaseCapture() 538 | { 539 | //TODO 540 | return true; 541 | } 542 | 543 | bool XlibWindow::IsCapturing() 544 | { 545 | //TODO 546 | return false; 547 | } 548 | 549 | bool XlibWindow::GetMaximizedBox() 550 | { 551 | //TODO 552 | return false; 553 | } 554 | 555 | void XlibWindow::SetMaximizedBox(bool visible) 556 | { 557 | //TODO 558 | } 559 | 560 | bool XlibWindow::GetMinimizedBox() 561 | { 562 | //TODO 563 | return false; 564 | } 565 | 566 | void XlibWindow::SetMinimizedBox(bool visible) 567 | { 568 | //TODO 569 | } 570 | 571 | bool XlibWindow::GetBorder() 572 | { 573 | //TODO 574 | return true; 575 | } 576 | 577 | void XlibWindow::SetBorder(bool visible) 578 | { 579 | //TODO 580 | } 581 | 582 | bool XlibWindow::GetSizeBox() 583 | { 584 | return resizable; 585 | } 586 | 587 | void XlibWindow::SetSizeBox(bool visible) 588 | { 589 | resizable = visible; 590 | UpdateResizable(); 591 | } 592 | 593 | bool XlibWindow::GetIconVisible() 594 | { 595 | //TODO 596 | return true; 597 | } 598 | 599 | void XlibWindow::SetIconVisible(bool visible) 600 | { 601 | //TODO 602 | } 603 | 604 | bool XlibWindow::GetTitleBar() 605 | { 606 | //TODO 607 | return IsCustomFrameModeEnabled(); 608 | } 609 | 610 | void XlibWindow::SetTitleBar(bool visible) 611 | { 612 | //TODO 613 | visible ? DisableCustomFrameMode() : EnableCustomFrameMode(); 614 | } 615 | 616 | bool XlibWindow::GetTopMost() 617 | { 618 | //TODO 619 | return false; 620 | } 621 | 622 | void XlibWindow::SetTopMost(bool topmost) 623 | { 624 | //TODO 625 | } 626 | 627 | void XlibWindow::SupressAlt() 628 | { 629 | //TODO 630 | } 631 | 632 | bool XlibWindow::InstallListener(INativeWindowListener *listener) 633 | { 634 | listeners.Add(listener); 635 | return true; 636 | } 637 | 638 | bool XlibWindow::UninstallListener(INativeWindowListener *listener) 639 | { 640 | return listeners.Remove(listener); 641 | } 642 | 643 | void XlibWindow::RedrawContent() 644 | { 645 | FOREACH(INativeWindowListener*, i, listeners) 646 | { 647 | i->Paint(); 648 | } 649 | } 650 | } 651 | } 652 | } 653 | } 654 | 655 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_CAIRO_WINDOW_H 2 | #define __GAC_X11CAIRO_XLIB_CAIRO_WINDOW_H 3 | 4 | #include 5 | #include "XlibIncludes.h" 6 | #include "../Common/X11Window.h" 7 | 8 | namespace vl 9 | { 10 | namespace presentation 11 | { 12 | namespace x11cairo 13 | { 14 | namespace xlib 15 | { 16 | class XlibWindow : public Object, public IX11Window 17 | { 18 | protected: 19 | Display *display; 20 | Window window; 21 | WString title; 22 | elements::IGuiGraphicsRenderTarget* renderTarget; 23 | bool resizable, doubleBuffer, customFrameMode, visible; 24 | collections::List listeners; 25 | XdbeBackBuffer backBuffer; 26 | XlibWindow* parentWindow; 27 | Rect bounds; 28 | Size clientSize; 29 | 30 | void UpdateTitle(); 31 | void UpdateResizable(); 32 | void GetParentList(collections::List&); 33 | 34 | public: 35 | XlibWindow(Display *display); 36 | 37 | virtual ~XlibWindow(); 38 | 39 | //Internal methods 40 | Display *GetDisplay(); 41 | Window GetWindow(); 42 | void CheckDoubleBuffer(); 43 | void RebuildDoubleBuffer(); 44 | bool GetDoubleBuffer(); 45 | XdbeBackBuffer GetBackBuffer(); 46 | void SwapBuffer(); 47 | 48 | void SetRenderTarget(elements::IGuiGraphicsRenderTarget*); 49 | 50 | elements::IGuiGraphicsRenderTarget* GetRenderTarget(); 51 | 52 | void MouseUpEvent(MouseButton button, NativeWindowMouseInfo info); 53 | void MouseDownEvent(MouseButton button, NativeWindowMouseInfo info); 54 | void MouseMoveEvent(NativeWindowMouseInfo info); 55 | void MouseEnterEvent(); 56 | void MouseLeaveEvent(); 57 | void ResizeEvent(int width, int height); 58 | void VisibilityEvent(Window window); 59 | 60 | //GacUI Implementations 61 | virtual Rect GetBounds(); 62 | 63 | virtual void SetBounds(const Rect &bounds); 64 | 65 | virtual Size GetClientSize(); 66 | 67 | virtual void SetClientSize(Size size); 68 | 69 | virtual Rect GetClientBoundsInScreen(); 70 | 71 | virtual WString GetTitle(); 72 | 73 | virtual void SetTitle(WString title); 74 | 75 | virtual INativeCursor *GetWindowCursor(); 76 | 77 | virtual void SetWindowCursor(INativeCursor *cursor); 78 | 79 | virtual Point GetCaretPoint(); 80 | 81 | virtual void SetCaretPoint(Point point); 82 | 83 | virtual INativeWindow *GetParent(); 84 | 85 | virtual void SetParent(INativeWindow *parent); 86 | 87 | virtual bool GetAlwaysPassFocusToParent(); 88 | 89 | virtual void SetAlwaysPassFocusToParent(bool value); 90 | 91 | virtual void EnableCustomFrameMode(); 92 | 93 | virtual void DisableCustomFrameMode(); 94 | 95 | virtual bool IsCustomFrameModeEnabled(); 96 | 97 | virtual WindowSizeState GetSizeState(); 98 | 99 | virtual void Show(); 100 | 101 | virtual void ShowDeactivated(); 102 | 103 | virtual void ShowRestored(); 104 | 105 | virtual void ShowMaximized(); 106 | 107 | virtual void ShowMinimized(); 108 | 109 | virtual void Hide(); 110 | 111 | virtual bool IsVisible(); 112 | 113 | virtual void Enable(); 114 | 115 | virtual void Disable(); 116 | 117 | virtual bool IsEnabled(); 118 | 119 | virtual void SetFocus(); 120 | 121 | virtual bool IsFocused(); 122 | 123 | virtual void SetActivate(); 124 | 125 | virtual bool IsActivated(); 126 | 127 | virtual void ShowInTaskBar(); 128 | 129 | virtual void HideInTaskBar(); 130 | 131 | virtual bool IsAppearedInTaskBar(); 132 | 133 | virtual void EnableActivate(); 134 | 135 | virtual void DisableActivate(); 136 | 137 | virtual bool IsEnabledActivate(); 138 | 139 | virtual bool RequireCapture(); 140 | 141 | virtual bool ReleaseCapture(); 142 | 143 | virtual bool IsCapturing(); 144 | 145 | virtual bool GetMaximizedBox(); 146 | 147 | virtual void SetMaximizedBox(bool visible); 148 | 149 | virtual bool GetMinimizedBox(); 150 | 151 | virtual void SetMinimizedBox(bool visible); 152 | 153 | virtual bool GetBorder(); 154 | 155 | virtual void SetBorder(bool visible); 156 | 157 | virtual bool GetSizeBox(); 158 | 159 | virtual void SetSizeBox(bool visible); 160 | 161 | virtual bool GetIconVisible(); 162 | 163 | virtual void SetIconVisible(bool visible); 164 | 165 | virtual bool GetTitleBar(); 166 | 167 | virtual void SetTitleBar(bool visible); 168 | 169 | virtual bool GetTopMost(); 170 | 171 | virtual void SetTopMost(bool topmost); 172 | 173 | virtual void SupressAlt(); 174 | 175 | virtual bool InstallListener(INativeWindowListener *listener); 176 | 177 | virtual bool UninstallListener(INativeWindowListener *listener); 178 | 179 | virtual void RedrawContent(); 180 | }; 181 | } 182 | } 183 | } 184 | } 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibXRecordMouseHookHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "XlibXRecordMouseHookHelper.h" 2 | 3 | namespace vl 4 | { 5 | using namespace collections; 6 | namespace presentation 7 | { 8 | namespace x11cairo 9 | { 10 | namespace xlib 11 | { 12 | XlibXRecordMouseHookHelper::XlibXRecordMouseHookHelper(const char* connString): 13 | ctrlDisplay(NULL), dataDisplay(NULL), capturing(false) 14 | { 15 | hookEvents.SetLessMemoryMode(false); 16 | 17 | ctrlDisplay = XOpenDisplay(connString); 18 | dataDisplay = XOpenDisplay(connString); 19 | 20 | if(!ctrlDisplay || !dataDisplay) 21 | { 22 | throw Exception(L"Cannot connect to X server."); 23 | } 24 | 25 | if(!CheckXRecordExtension(ctrlDisplay) || !CheckXRecordExtension(dataDisplay)) 26 | { 27 | throw Exception(L"Record Extension is required for GacUI/X11."); 28 | } 29 | 30 | // Initialize X Record Extension 31 | XRecordClientSpec recordClientSpec = XRecordAllClients; 32 | XRecordRange *recordRange = XRecordAllocRange(); 33 | recordRange->device_events.first = ButtonPress; 34 | recordRange->device_events.last = MotionNotify; 35 | 36 | XSynchronize(ctrlDisplay, XLIB_TRUE); 37 | recordContext = XRecordCreateContext(ctrlDisplay, XRecordFromClientTime, &recordClientSpec, 1, &recordRange, 1); 38 | XFree(recordRange); 39 | } 40 | 41 | XlibXRecordMouseHookHelper::~XlibXRecordMouseHookHelper() 42 | { 43 | if(capturing) EndCapture(); 44 | XRecordFreeContext(ctrlDisplay, recordContext); 45 | XFlush(dataDisplay); 46 | XCloseDisplay(ctrlDisplay); 47 | XCloseDisplay(dataDisplay); 48 | } 49 | 50 | void XlibXRecordMouseHookHelper::StartCapture() 51 | { 52 | XRecordEnableContextAsync( 53 | dataDisplay, 54 | recordContext, 55 | [](XPointer closure, XRecordInterceptData *recorded_data) 56 | { 57 | if(recorded_data->category == XRecordFromServer) 58 | { 59 | xEvent *data = (xEvent *) recorded_data->data; 60 | XlibXRecordMouseHookHelper* helper = (XlibXRecordMouseHookHelper*) closure; 61 | switch(data->u.u.type) 62 | { 63 | case ButtonPress: 64 | case ButtonRelease: 65 | case MotionNotify: 66 | helper->AddData(data); 67 | break; 68 | } 69 | } 70 | XRecordFreeData(recorded_data); 71 | }, 72 | (XPointer) this); 73 | 74 | XFlush(dataDisplay); 75 | capturing = true; 76 | } 77 | 78 | void XlibXRecordMouseHookHelper::EndCapture() 79 | { 80 | XRecordDisableContext(ctrlDisplay, recordContext); 81 | capturing = false; 82 | } 83 | 84 | bool XlibXRecordMouseHookHelper::IsCapturing() 85 | { 86 | return capturing; 87 | } 88 | 89 | void XlibXRecordMouseHookHelper::Update() 90 | { 91 | XRecordProcessReplies(dataDisplay); 92 | } 93 | 94 | MouseEvent XlibXRecordMouseHookHelper::DataToEvent(xEvent* ev) 95 | { 96 | MouseEventType type; 97 | MouseButton button; 98 | switch(ev->u.u.type) 99 | { 100 | case ButtonPress: 101 | type = MouseEventType::BUTTONDOWN; 102 | break; 103 | case ButtonRelease: 104 | type = MouseEventType::BUTTONUP; 105 | break; 106 | case MotionNotify: 107 | type = MouseEventType::POINTERMOVE; 108 | break; 109 | } 110 | 111 | if(ev->u.keyButtonPointer.state & Button2Mask) 112 | { 113 | button = MouseButton::RBUTTON; 114 | } 115 | else 116 | { 117 | button = MouseButton::LBUTTON; 118 | } 119 | 120 | return MouseEvent(button, type, ev->u.keyButtonPointer.rootX, ev->u.keyButtonPointer.rootY); 121 | } 122 | 123 | void XlibXRecordMouseHookHelper::AddData(xEvent* ev) 124 | { 125 | hookEvents.Add(DataToEvent(ev)); 126 | } 127 | 128 | void XlibXRecordMouseHookHelper::ProcessEvents(Func handler) 129 | { 130 | Array currentEvents(hookEvents.Count()); 131 | CopyFrom(currentEvents, hookEvents); 132 | 133 | FOREACH(MouseEvent, i, currentEvents) 134 | { 135 | handler(i); 136 | } 137 | 138 | hookEvents.Clear(); 139 | } 140 | } 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /X11Cairo/NativeWindow/Xlib/XlibXRecordMouseHookHelper.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_XLIB_XRECORD_MOUSE_HOOK_HELPER_H 2 | #define __GAC_X11CAIRO_XLIB_XRECORD_MOUSE_HOOK_HELPER_H 3 | 4 | #include 5 | #include "XlibIncludes.h" 6 | 7 | extern "C" 8 | { 9 | #include 10 | #include 11 | #include 12 | #include 13 | } 14 | 15 | namespace vl 16 | { 17 | namespace presentation 18 | { 19 | namespace x11cairo 20 | { 21 | namespace xlib 22 | { 23 | class XlibXRecordMouseHookHelper: public Object 24 | { 25 | protected: 26 | vl::collections::List hookEvents; 27 | XRecordContext recordContext; 28 | Display *ctrlDisplay, *dataDisplay; 29 | bool capturing; 30 | 31 | MouseEvent DataToEvent(xEvent* ev); 32 | 33 | public: 34 | XlibXRecordMouseHookHelper(const char*); 35 | ~XlibXRecordMouseHookHelper(); 36 | void Update(); 37 | void ProcessEvents(Func); 38 | void StartCapture(); 39 | void EndCapture(); 40 | bool IsCapturing(); 41 | 42 | void AddData(xEvent* ev); 43 | }; 44 | } 45 | } 46 | } 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /X11Cairo/X11CairoIncludes.h: -------------------------------------------------------------------------------- 1 | #ifndef __X11_X11CAIRO_CAIRO_INCLUDES_H 2 | #define __X11_X11CAIRO_CAIRO_INCLUDES_H 3 | 4 | // Macros: 5 | // GAC_X11_XCB: Use XCB for X11 client library 6 | // GAC_X11_DOUBLEBUFFER: Use Xdbe Based Double Buffer 7 | // GAC_X11_CAIRO_OPENGL: Use OpenGL and Cairo_GL (Ignore GAC_X11_DOUBLEBUFFER if selected) 8 | 9 | #ifndef GAC_X11_XCB 10 | 11 | #include "NativeWindow/Xlib/XlibNativeController.h" 12 | #include "NativeWindow/Xlib/XlibWindow.h" 13 | #include "X11CairoSetup.h" 14 | 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /X11Cairo/X11CairoSetup.cpp: -------------------------------------------------------------------------------- 1 | #include "X11CairoSetup.h" 2 | #include "GraphicsElement/X11CairoResourceManager.h" 3 | #include "GraphicsElement/GuiGraphicsX11Cairo.h" 4 | #include 5 | 6 | #ifndef GAC_X11_XCB 7 | #include "NativeWindow/Xlib/XlibNativeController.h" 8 | 9 | void SetupX11CairoRenderer(const char* displayname) 10 | { 11 | setlocale(LC_ALL, ""); 12 | 13 | INativeController* controller = vl::presentation::x11cairo::xlib::CreateXlibCairoNativeController(displayname); 14 | SetCurrentController(controller); 15 | 16 | vl::presentation::x11cairo::RegisterX11CairoResourceManager(); 17 | vl::presentation::elements_x11cairo::RegisterX11CairoElementRenderers(); 18 | 19 | vl::presentation::x11cairo::xlib::X11CairoMain(); 20 | 21 | vl::presentation::x11cairo::UnregisterX11CairoResourceManager(); 22 | SetCurrentController(NULL); 23 | vl::presentation::x11cairo::xlib::DestroyXlibCairoNativeController(controller); 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /X11Cairo/X11CairoSetup.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAC_X11CAIRO_X11_CAIRO_SETUP_H 2 | #define __GAC_X11CAIRO_X11_CAIRO_SETUP_H 3 | 4 | extern void SetupX11CairoRenderer(const char* displayName = nullptr); 5 | 6 | #endif 7 | --------------------------------------------------------------------------------