1 /* 2 __ 3 / _| 4 __ _ _ _ _ __ ___ _ __ __ _ | |_ ___ ___ ___ 5 / _` | | | | '__/ _ \| '__/ _` | | _/ _ \/ __/ __| 6 | (_| | |_| | | | (_) | | | (_| | | || (_) \__ \__ \ 7 \__,_|\__,_|_| \___/|_| \__,_| |_| \___/|___/___/ 8 9 Copyright (C) 2018-2019 Aurora Free Open Source Software. 10 11 This file is part of the Aurora Free Open Source Software. This 12 organization promote free and open source software that you can 13 redistribute and/or modify under the terms of the GNU Lesser General 14 Public License Version 3 as published by the Free Software Foundation or 15 (at your option) any later version approved by the Aurora Free Open Source 16 Software Organization. The license is available in the package root path 17 as 'LICENSE' file. Please review the following information to ensure the 18 GNU Lesser General Public License version 3 requirements will be met: 19 https://www.gnu.org/licenses/lgpl.html . 20 21 Alternatively, this file may be used under the terms of the GNU General 22 Public License version 3 or later as published by the Free Software 23 Foundation. Please review the following information to ensure the GNU 24 General Public License requirements will be met: 25 http://www.gnu.org/licenses/gpl-3.0.html. 26 27 NOTE: All products, services or anything associated to trademarks and 28 service marks used or referenced on this file are the property of their 29 respective companies/owners or its subsidiaries. Other names and brands 30 may be claimed as the property of others. 31 32 For more info about intellectual property visit: aurorafoss.org or 33 directly send an email to: contact (at) aurorafoss.org . 34 */ 35 36 module aurorafw.gui.api.x11.backend; 37 38 import X = aurorafw.gui.platform.x; 39 import riverd.xcursor; 40 41 import std.conv : emplace; 42 import core.stdc.stdlib : malloc, free; 43 import aurorafw.math.vector : Vector2f; 44 import std.process : environment; 45 import aurorafw.core.logger : error; 46 import core.stdc.stdlib : exit; 47 import core.stdc.stdlib : atof; 48 import core.stdc..string : strcmp; 49 50 import aurorafw.gui.api.backend; 51 52 pure class X11Backend : Backend { 53 this() 54 { 55 super._type = BackendType.X11; 56 57 X.XInitThreads(); 58 X.XrmInitialize(); 59 _display = X.XOpenDisplay(null); 60 61 if(_display is null) 62 { 63 auto env_display = environment.get("DISPLAY"); 64 if(env_display) 65 error("X11: Cannot open display ", env_display); 66 else 67 error("X11: DISPLAY variable is missing"); 68 69 exit(1); //TODO: add error to Error Database 70 } 71 72 _screen = X.XDefaultScreen(_display); 73 _root = X.XRootWindow(_display, _screen); 74 _context = X.XUniqueContext(); 75 76 // get system content scale 77 float xdpi = X.XDisplayWidth(_display, _screen) * 25.4f / X.XDisplayWidthMM(_display, _screen); 78 float ydpi = X.XDisplayHeight(_display, _screen) * 25.4f / X.XDisplayHeightMM(_display, _screen); 79 80 char* rms = X.XResourceManagerString(_display); 81 if (rms) 82 { 83 X.XrmDatabase db = X.XrmGetStringDatabase(rms); 84 if (db) 85 { 86 X.XrmValue value; 87 char* type = null; 88 89 if (X.XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value)) 90 { 91 if (type && strcmp(type, "String") == 0) 92 xdpi = ydpi = atof(cast(char*)value.addr); 93 } 94 95 X.XrmDestroyDatabase(db); 96 } 97 } 98 99 _contentScale.x = xdpi / 96.0f; 100 _contentScale.y = ydpi / 96.0f; 101 102 //init x11 extensions 103 // TODO 104 initX11Extensions(); 105 106 X.XSetWindowAttributes wa; 107 wa.event_mask = X.PropertyChangeMask; 108 109 _helperWindowHandle = X.XCreateWindow(_display, _root, 110 0, 0, 1, 1, 0, 0, 111 X.InputOnly, 112 X.XDefaultVisual(_display, _screen), 113 X.CWEventMask, &wa); 114 115 immutable byte[16 * 16 * 4] pixels; 116 _hiddenCursorHandle = createXCursor(16, 16, pixels, 0, 0); 117 118 if (X.XSupportsLocale()) 119 { 120 X.XSetLocaleModifiers(""); 121 122 this._im = X.XOpenIM(_display, null, null, null); 123 if (this._im) 124 { 125 bool found = false; 126 X.XIMStyles* styles = null; 127 128 if(X.XGetIMValues(_im, X.XNQueryInputStyle, &styles, null) == null) 129 { 130 for (uint i = 0; i < styles.count_styles; i++) 131 { 132 if (styles.supported_styles[i] == (X.XIMPreeditNothing | X.XIMStatusNothing)) 133 { 134 found = true; 135 break; 136 } 137 } 138 139 X.XFree(styles); 140 } 141 142 if (!found) 143 { 144 X.XCloseIM(_im); 145 this._im = null; 146 } 147 } 148 } 149 } 150 151 ~this() 152 { 153 if(_display) 154 { 155 X.XCloseDisplay(_display); 156 _display = null; 157 } 158 } 159 160 X.Cursor createXCursor(immutable uint width, immutable uint height, immutable byte[] pixels, int xhot, int yhot) 161 { 162 X.Cursor cursor; 163 164 if (!X.dylib_is_loaded(_xcursor.handle)) 165 return X.None; 166 167 X.XcursorImage* native = X.XcursorImageCreate(width, height); 168 if (native == null) 169 return X.None; 170 171 native.xhot = xhot; 172 native.yhot = yhot; 173 174 byte* source = cast(byte*) pixels; 175 X.XcursorPixel* target = native.pixels; 176 177 for (int i = 0; i < width * height; i++, target++, source += 4) 178 { 179 uint alpha = source[3]; 180 181 *target = (alpha << 24) | 182 (cast(byte) ((source[0] * alpha) / 255) << 16) | 183 (cast(byte) ((source[1] * alpha) / 255) << 8) | 184 (cast(byte) ((source[2] * alpha) / 255) << 0); 185 } 186 187 cursor = X.XcursorImageLoadCursor(_display, native); 188 X.XcursorImageDestroy(native); 189 190 return cursor; 191 } 192 193 X.Display* display() @property { return _display; } 194 int screen() @property { return _screen; } 195 X.Window root() @property { return _root; } 196 197 private void initX11Extensions() 198 { 199 //TODO: Remove/improve logger 200 import std.experimental.logger; 201 import aurorafw.core.debugmanager; 202 try _xf86vmode.handle = X.dylib_load_xxf86vm(); catch(Exception e) debug trace(afwDebugFlag, e.msg); 203 204 if(X.dylib_is_loaded(_xf86vmode.handle)) 205 { 206 _xf86vmode.available = cast(bool)X.XF86VidModeQueryExtension(_display, &_xf86vmode.eventBase, &_xf86vmode.errorBase); 207 } 208 209 try _xcursor.handle = X.dylib_load_xcursor(); catch(Exception e) debug trace(afwDebugFlag, e.msg); 210 } 211 212 private: 213 X.Display* _display; 214 X.Window _root; 215 int _screen; 216 Vector2f _contentScale; 217 X.XContext _context; 218 X.XIM _im; 219 X.Window _helperWindowHandle; 220 X.Cursor _hiddenCursorHandle; 221 XCursorExtension _xcursor; 222 XF86VModeExtension _xf86vmode; 223 } 224 225 struct XCursorExtension { 226 void* handle; 227 } 228 229 struct XF86VModeExtension { 230 void* handle; 231 bool available; 232 int eventBase; 233 int errorBase; 234 }