File indexing completed on 2024-04-28 05:46:51
0001 /***************************************************************************** 0002 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify * 0005 * it under the terms of the GNU Lesser General Public License as * 0006 * published by the Free Software Foundation; either version 2.1 of the * 0007 * License, or (at your option) version 3, or any later version accepted * 0008 * by the membership of KDE e.V. (or its successor approved by the * 0009 * membership of KDE e.V.), which shall act as a proxy defined in * 0010 * Section 6 of version 3 of the license. * 0011 * * 0012 * This program is distributed in the hope that it will be useful, * 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0015 * Lesser General Public License for more details. * 0016 * * 0017 * You should have received a copy of the GNU Lesser General Public * 0018 * License along with this library. If not, * 0019 * see <http://www.gnu.org/licenses/>. * 0020 *****************************************************************************/ 0021 0022 // TODO multi screen? 0023 0024 #include "config.h" 0025 #include "x11utils.h" 0026 0027 QTC_EXPORT xcb_atom_t qtc_x11_qtc_menubar_size; 0028 QTC_EXPORT xcb_atom_t qtc_x11_qtc_statusbar; 0029 QTC_EXPORT xcb_atom_t qtc_x11_qtc_titlebar_size; 0030 QTC_EXPORT xcb_atom_t qtc_x11_qtc_active_window; 0031 QTC_EXPORT xcb_atom_t qtc_x11_qtc_toggle_menubar; 0032 QTC_EXPORT xcb_atom_t qtc_x11_qtc_toggle_statusbar; 0033 QTC_EXPORT xcb_atom_t qtc_x11_qtc_opacity; 0034 QTC_EXPORT xcb_atom_t qtc_x11_qtc_bgnd; 0035 0036 #ifdef QTC_ENABLE_X11 0037 0038 #include "x11shadow_p.h" 0039 #include "x11wrap.h" 0040 #include "log.h" 0041 #include "x11utils_p.h" 0042 #include <X11/Xlib-xcb.h> 0043 // #include <X11/Xutil.h> 0044 // #include <X11/extensions/Xrender.h> 0045 0046 void *qtc_disp = nullptr; 0047 xcb_connection_t *qtc_xcb_conn = nullptr; 0048 int qtc_default_screen_no = -1; 0049 xcb_window_t qtc_root_window = {0}; 0050 xcb_screen_t *qtc_default_screen = nullptr; 0051 static char wm_cm_s_atom_name[100] = "_NET_WM_CM_S"; 0052 0053 xcb_atom_t qtc_x11_net_wm_moveresize; 0054 xcb_atom_t qtc_x11_net_wm_cm_s_default; 0055 xcb_atom_t qtc_x11_kde_net_wm_shadow; 0056 xcb_atom_t qtc_x11_kde_net_wm_blur_behind_region; 0057 static xcb_atom_t qtc_x11_xembed_info; 0058 0059 static const struct { 0060 xcb_atom_t *atom; 0061 const char *name; 0062 } qtc_x11_atoms[] = { 0063 {&qtc_x11_net_wm_moveresize, "_NET_WM_MOVERESIZE"}, 0064 {&qtc_x11_net_wm_cm_s_default, wm_cm_s_atom_name}, 0065 {&qtc_x11_kde_net_wm_shadow, "_KDE_NET_WM_SHADOW"}, 0066 {&qtc_x11_kde_net_wm_blur_behind_region, "_KDE_NET_WM_BLUR_BEHIND_REGION"}, 0067 {&qtc_x11_qtc_menubar_size, "_QTCURVE_MENUBAR_SIZE_"}, 0068 {&qtc_x11_qtc_statusbar, "_QTCURVE_STATUSBAR_"}, 0069 {&qtc_x11_qtc_titlebar_size, "_QTCURVE_TITLEBAR_SIZE_"}, 0070 {&qtc_x11_qtc_active_window, "_QTCURVE_ACTIVE_WINDOW_"}, 0071 {&qtc_x11_qtc_toggle_menubar, "_QTCURVE_TOGGLE_MENUBAR_"}, 0072 {&qtc_x11_qtc_toggle_statusbar, "_QTCURVE_TOGGLE_STATUSBAR_"}, 0073 {&qtc_x11_qtc_opacity, "_QTCURVE_OPACITY_"}, 0074 {&qtc_x11_qtc_bgnd, "_QTCURVE_BGND_"}, 0075 {&qtc_x11_xembed_info, "_XEMBED_INFO"} 0076 }; 0077 #define QTC_X11_ATOM_N (sizeof(qtc_x11_atoms) / sizeof(qtc_x11_atoms[0])) 0078 0079 QTC_EXPORT bool 0080 qtcX11Enabled() 0081 { 0082 return qtc_xcb_conn != nullptr; 0083 } 0084 0085 QTC_EXPORT xcb_window_t 0086 qtcX11RootWindow(int scrn_no) 0087 { 0088 if (scrn_no < 0 || scrn_no == qtc_default_screen_no) { 0089 return qtc_root_window; 0090 } 0091 return qtcX11GetScreen(scrn_no)->root; 0092 } 0093 0094 QTC_EXPORT int 0095 qtcX11DefaultScreenNo() 0096 { 0097 return qtc_default_screen_no; 0098 } 0099 0100 QTC_EXPORT xcb_screen_t* 0101 qtcX11DefaultScreen() 0102 { 0103 return qtc_default_screen; 0104 } 0105 0106 static xcb_screen_t* 0107 screen_of_display(xcb_connection_t *c, int screen) 0108 { 0109 xcb_screen_iterator_t iter; 0110 0111 iter = xcb_setup_roots_iterator(xcb_get_setup(c)); 0112 for (;iter.rem;--screen, xcb_screen_next(&iter)) { 0113 if (screen == 0) { 0114 return iter.data; 0115 } 0116 } 0117 return nullptr; 0118 } 0119 0120 static void 0121 qtcX11AtomsInit() 0122 { 0123 xcb_connection_t *conn = qtc_xcb_conn; 0124 xcb_intern_atom_cookie_t cookies[QTC_X11_ATOM_N]; 0125 for (size_t i = 0;i < QTC_X11_ATOM_N;i++) { 0126 cookies[i] = xcb_intern_atom(conn, 0, strlen(qtc_x11_atoms[i].name), 0127 qtc_x11_atoms[i].name); 0128 } 0129 for (size_t i = 0;i < QTC_X11_ATOM_N;i++) { 0130 xcb_intern_atom_reply_t *r = 0131 xcb_intern_atom_reply(conn, cookies[i], nullptr); 0132 if (qtcLikely(r)) { 0133 *qtc_x11_atoms[i].atom = r->atom; 0134 free(r); 0135 } else { 0136 *qtc_x11_atoms[i].atom = 0; 0137 } 0138 } 0139 } 0140 0141 QTC_EXPORT xcb_screen_t* 0142 qtcX11GetScreen(int screen_no) 0143 { 0144 QTC_RET_IF_FAIL(qtc_xcb_conn, nullptr); 0145 if (screen_no == -1 || screen_no == qtc_default_screen_no) { 0146 return qtc_default_screen; 0147 } 0148 return screen_of_display(qtc_xcb_conn, screen_no); 0149 } 0150 0151 QTC_EXPORT void 0152 qtcX11InitXcb(xcb_connection_t *conn, int screen_no) 0153 { 0154 QTC_RET_IF_FAIL(!qtc_xcb_conn && conn); 0155 if (screen_no < 0) { 0156 screen_no = 0; 0157 } 0158 qtc_xcb_conn = conn; 0159 qtc_default_screen_no = screen_no; 0160 qtc_default_screen = screen_of_display(conn, screen_no); 0161 if (qtc_default_screen) { 0162 qtc_root_window = qtc_default_screen->root; 0163 } 0164 const size_t base_len = strlen("_NET_WM_CM_S"); 0165 sprintf(wm_cm_s_atom_name + base_len, "%d", screen_no); 0166 qtcX11AtomsInit(); 0167 qtcX11ShadowInit(); 0168 } 0169 0170 QTC_EXPORT void 0171 qtcX11InitXlib(void *disp) 0172 { 0173 QTC_RET_IF_FAIL(!qtc_xcb_conn && disp); 0174 qtc_disp = disp; 0175 qtcX11InitXcb(XGetXCBConnection((Display*)disp), DefaultScreen(disp)); 0176 } 0177 0178 QTC_EXPORT xcb_connection_t* 0179 qtcX11GetConn() 0180 { 0181 return qtc_xcb_conn; 0182 } 0183 0184 QTC_EXPORT void* 0185 qtcX11GetDisp() 0186 { 0187 return qtc_disp; 0188 } 0189 0190 QTC_EXPORT void 0191 qtcX11MapRaised(xcb_window_t win) 0192 { 0193 QTC_RET_IF_FAIL(qtc_xcb_conn && win); 0194 static const uint32_t val = XCB_STACK_MODE_ABOVE; 0195 qtcX11CallVoid(configure_window, win, XCB_CONFIG_WINDOW_STACK_MODE, &val); 0196 qtcX11CallVoid(map_window, win); 0197 } 0198 0199 QTC_EXPORT bool 0200 qtcX11CompositingActive() 0201 { 0202 QTC_RET_IF_FAIL(qtc_xcb_conn, false); 0203 xcb_get_selection_owner_reply_t *reply = 0204 qtcX11Call(get_selection_owner, qtc_x11_net_wm_cm_s_default); 0205 QTC_RET_IF_FAIL(reply, false); 0206 bool res = (reply->owner != 0); 0207 free(reply); 0208 return res; 0209 } 0210 0211 QTC_EXPORT bool 0212 qtcX11HasAlpha(xcb_window_t win) 0213 { 0214 QTC_RET_IF_FAIL(qtc_xcb_conn && win, false); 0215 if (!qtcX11CompositingActive()) { 0216 return false; 0217 } 0218 xcb_get_geometry_reply_t *reply = qtcX11Call(get_geometry, win); 0219 QTC_RET_IF_FAIL(reply, false); 0220 bool res = (reply->depth == 32); 0221 free(reply); 0222 return res; 0223 } 0224 0225 QTC_EXPORT bool 0226 qtcX11IsEmbed(xcb_window_t win) 0227 { 0228 QTC_RET_IF_FAIL(qtc_xcb_conn && win, false); 0229 xcb_get_property_reply_t *reply = 0230 qtcX11GetProperty(0, win, qtc_x11_xembed_info, 0231 qtc_x11_xembed_info, 0, 1); 0232 QTC_RET_IF_FAIL(reply, false); 0233 bool res = xcb_get_property_value_length(reply) > 0; 0234 free(reply); 0235 return res; 0236 } 0237 0238 #if 0 0239 QTC_EXPORT void* 0240 qtcX11RgbaVisual(unsigned long *colormap, int *map_entries, int screen) 0241 { 0242 QTC_RET_IF_FAIL(qtc_disp, nullptr); 0243 if (screen < 0) { 0244 screen = qtc_default_screen_no; 0245 } 0246 // Copied from Qt4 0247 Visual *argbVisual = nullptr; 0248 int nvi; 0249 XVisualInfo templ; 0250 templ.screen = screen; 0251 templ.depth = 32; 0252 templ.class = TrueColor; 0253 XVisualInfo *xvi = XGetVisualInfo(qtc_disp, VisualScreenMask | 0254 VisualDepthMask | VisualClassMask, 0255 &templ, &nvi); 0256 for (int idx = 0; idx < nvi; ++idx) { 0257 XRenderPictFormat *format = XRenderFindVisualFormat(qtc_disp, 0258 xvi[idx].visual); 0259 if (format->type == PictTypeDirect && format->direct.alphaMask) { 0260 argbVisual = xvi[idx].visual; 0261 break; 0262 } 0263 } 0264 XFree(xvi); 0265 QTC_RET_IF_FAIL(argbVisual, nullptr); 0266 qtcAssign(colormap, XCreateColormap(qtc_disp, RootWindow(qtc_disp, screen), 0267 argbVisual, AllocNone)); 0268 qtcAssign(map_entries, argbVisual->map_entries); 0269 return argbVisual; 0270 } 0271 #endif 0272 0273 #else 0274 0275 QTC_EXPORT bool 0276 qtcX11Enabled() 0277 { 0278 return false; 0279 } 0280 0281 QTC_EXPORT xcb_window_t 0282 qtcX11RootWindow(int) 0283 { 0284 return 0; 0285 } 0286 0287 QTC_EXPORT int 0288 qtcX11DefaultScreenNo() 0289 { 0290 return -1; 0291 } 0292 0293 QTC_EXPORT xcb_screen_t* 0294 qtcX11DefaultScreen() 0295 { 0296 return nullptr; 0297 } 0298 0299 QTC_EXPORT xcb_screen_t* 0300 qtcX11GetScreen(int) 0301 { 0302 return nullptr; 0303 } 0304 0305 QTC_EXPORT void 0306 qtcX11InitXcb(xcb_connection_t*, int) 0307 { 0308 } 0309 0310 QTC_EXPORT void 0311 qtcX11InitXlib(void*) 0312 { 0313 } 0314 0315 QTC_EXPORT xcb_connection_t* 0316 qtcX11GetConn() 0317 { 0318 return nullptr; 0319 } 0320 0321 QTC_EXPORT void* 0322 qtcX11GetDisp() 0323 { 0324 return nullptr; 0325 } 0326 0327 QTC_EXPORT void 0328 qtcX11MapRaised(xcb_window_t) 0329 { 0330 } 0331 0332 QTC_EXPORT bool 0333 qtcX11CompositingActive() 0334 { 0335 return false; 0336 } 0337 0338 QTC_EXPORT bool 0339 qtcX11HasAlpha(xcb_window_t) 0340 { 0341 return false; 0342 } 0343 0344 QTC_EXPORT bool 0345 qtcX11IsEmbed(xcb_window_t) 0346 { 0347 return false; 0348 } 0349 0350 #if 0 0351 QTC_EXPORT void* 0352 qtcX11RgbaVisual(unsigned long*, int*, int) 0353 { 0354 return nullptr; 0355 } 0356 #endif 0357 0358 #endif