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 #include "config.h" 0023 0024 #include "x11shadow_p.h" 0025 #include "x11wmmove.h" 0026 #include "x11blur.h" 0027 #include "x11qtc.h" 0028 #include "x11wrap.h" 0029 0030 static int shadow_size = 30; 0031 0032 #ifdef QTC_ENABLE_X11 0033 0034 #include "log.h" 0035 #include "number.h" 0036 #include "shadow_p.h" 0037 #include "x11utils_p.h" 0038 #include <X11/Xlib.h> 0039 #include <X11/Xatom.h> 0040 0041 /** 0042 * shadow atom and property specification available at 0043 * http://community.kde.org/KWin/Shadow 0044 **/ 0045 0046 static uint32_t shadow_xpixmaps[8]; 0047 static uint32_t shadow_data_xcb[8 + 4]; 0048 /** 0049 * Use XCB to set window property receives BadWindow errors for menus in 0050 * Qt4 kpartsplugin here, probably because of the order of some pending 0051 * event/requests in Xlib. Calling #XFlush before #xcb_change_property 0052 * doesn't solve the problem for unknown reason but using #XChangeProperty 0053 * works. 0054 * NOTE: #XChangeProperty want `unsigned long` for format 32. So we need 0055 * two separate data buffers. 0056 **/ 0057 static unsigned long shadow_data_xlib[8 + 4]; 0058 0059 static xcb_pixmap_t 0060 qtcX11ShadowCreatePixmap(const QtCurve::Image *data) 0061 { 0062 xcb_pixmap_t pixmap = qtcX11GenerateId(); 0063 0064 // create X11 pixmap 0065 qtcX11CallVoid(create_pixmap, 32, pixmap, qtc_root_window, 0066 data->width, data->height); 0067 xcb_gcontext_t cid = qtcX11GenerateId(); 0068 qtcX11CallVoid(create_gc, cid, pixmap, 0, (const uint32_t*)0); 0069 qtcX11CallVoid(put_image, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, cid, 0070 data->width, data->height, 0, 0, 0, 32, data->data.size(), 0071 (unsigned char*)&data->data[0]); 0072 qtcX11CallVoid(free_gc, cid); 0073 qtcX11Flush(); 0074 return pixmap; 0075 } 0076 0077 void 0078 qtcX11ShadowInit() 0079 { 0080 int shadow_radius = 4; 0081 QtcColor c1 = {0.4, 0.4, 0.4}; 0082 QtcColor c2 = {0.2, 0.2, 0.2}; 0083 QtCurve::Image *shadow_images[8]; 0084 qtcShadowCreate(shadow_size, &c1, &c2, shadow_radius, false, 0085 QTC_PIXEL_XCB, shadow_images); 0086 for (int i = 0;i < 8;i++) { 0087 shadow_xpixmaps[i] = qtcX11ShadowCreatePixmap(shadow_images[i]); 0088 delete shadow_images[i]; 0089 } 0090 0091 memcpy(shadow_data_xcb, shadow_xpixmaps, sizeof(shadow_xpixmaps)); 0092 for (int i = 0;i < 8;i++) { 0093 shadow_data_xlib[i] = shadow_xpixmaps[i]; 0094 } 0095 for (int i = 8;i < 12;i++) { 0096 shadow_data_xlib[i] = shadow_data_xcb[i] = shadow_size - 1; 0097 } 0098 } 0099 0100 // Necessary? 0101 void 0102 qtcX11ShadowDestroy() 0103 { 0104 QTC_RET_IF_FAIL(qtc_xcb_conn); 0105 for (unsigned int i = 0; 0106 i < sizeof(shadow_xpixmaps) / sizeof(shadow_xpixmaps[0]);i++) { 0107 qtcX11CallVoid(free_pixmap, shadow_xpixmaps[i]); 0108 } 0109 qtcX11Flush(); 0110 } 0111 0112 QTC_EXPORT void 0113 qtcX11ShadowInstall(xcb_window_t win, const int margins[4]) 0114 { 0115 QTC_RET_IF_FAIL(win); 0116 if (qtcUnlikely(!margins)) { 0117 qtcX11ShadowInstall(win); 0118 return; 0119 } 0120 // In principle, I should check for _KDE_NET_WM_SHADOW in _NET_SUPPORTED. 0121 // However, it's complicated and we will gain nothing. 0122 xcb_atom_t atom = qtc_x11_kde_net_wm_shadow; 0123 if (qtc_disp) { 0124 unsigned long shadow_data[8 + 4]; 0125 memcpy(shadow_data, shadow_data_xlib, 12 * sizeof(unsigned long)); 0126 for (int i = 0;i < 4;i++) { 0127 shadow_data[i + 8] -= margins[i]; 0128 } 0129 XChangeProperty((Display*)qtc_disp, win, atom, XA_CARDINAL, 32, 0130 PropModeReplace, (unsigned char*)shadow_data, 12); 0131 } else { 0132 uint32_t shadow_data[8 + 4]; 0133 memcpy(shadow_data, shadow_data_xcb, 12 * sizeof(uint32_t)); 0134 for (int i = 0;i < 4;i++) { 0135 shadow_data[i + 8] -= margins[i]; 0136 } 0137 qtcX11ChangeProperty(XCB_PROP_MODE_REPLACE, win, atom, 0138 XCB_ATOM_CARDINAL, 32, 12, shadow_data); 0139 qtcX11Flush(); 0140 } 0141 } 0142 0143 QTC_EXPORT void 0144 qtcX11ShadowInstall(xcb_window_t win) 0145 { 0146 QTC_RET_IF_FAIL(win); 0147 // In principle, I should check for _KDE_NET_WM_SHADOW in _NET_SUPPORTED. 0148 // However, it's complicated and we will gain nothing. 0149 xcb_atom_t atom = qtc_x11_kde_net_wm_shadow; 0150 if (qtc_disp) { 0151 XChangeProperty((Display*)qtc_disp, win, atom, XA_CARDINAL, 32, 0152 PropModeReplace, (unsigned char*)shadow_data_xlib, 12); 0153 } else { 0154 qtcX11ChangeProperty(XCB_PROP_MODE_REPLACE, win, atom, 0155 XCB_ATOM_CARDINAL, 32, 12, shadow_data_xcb); 0156 qtcX11Flush(); 0157 } 0158 } 0159 0160 QTC_EXPORT void 0161 qtcX11ShadowUninstall(xcb_window_t win) 0162 { 0163 QTC_RET_IF_FAIL(win); 0164 qtcX11CallVoid(delete_property, win, qtc_x11_kde_net_wm_shadow); 0165 qtcX11Flush(); 0166 } 0167 0168 // WM Move 0169 QTC_EXPORT void 0170 qtcX11MoveTrigger(xcb_window_t wid, uint32_t x, uint32_t y) 0171 { 0172 QTC_RET_IF_FAIL(wid); 0173 qtcX11FlushXlib(); 0174 qtcX11CallVoid(ungrab_pointer, XCB_TIME_CURRENT_TIME); 0175 union { 0176 char _buff[32]; 0177 xcb_client_message_event_t ev; 0178 } buff; 0179 memset(&buff, 0, sizeof(buff)); 0180 // ...Taken from bespin... 0181 // stolen... errr "adapted!" from QSizeGrip 0182 // Well now it is "ported" 0183 xcb_client_message_event_t *xev = &buff.ev; 0184 xev->response_type = XCB_CLIENT_MESSAGE; 0185 xev->format = 32; 0186 xev->window = wid; 0187 xev->type = qtc_x11_net_wm_moveresize; 0188 xev->data.data32[0] = x; 0189 xev->data.data32[1] = y; 0190 xev->data.data32[2] = 8; // NET::Move 0191 xev->data.data32[3] = XCB_KEY_BUT_MASK_BUTTON_1; 0192 qtcX11SendEvent(false, qtc_root_window, 0193 XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | 0194 XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, xev); 0195 qtcX11Flush(); 0196 } 0197 0198 // Blur 0199 QTC_EXPORT void 0200 qtcX11BlurTrigger(xcb_window_t wid, bool enable, unsigned prop_num, 0201 const uint32_t *props) 0202 { 0203 QTC_RET_IF_FAIL(wid); 0204 xcb_atom_t atom = qtc_x11_kde_net_wm_blur_behind_region; 0205 if (enable) { 0206 if (qtc_disp) { 0207 QtCurve::LocalBuff<unsigned long, 256> xlib_props(prop_num); 0208 for (unsigned i = 0;i < prop_num;i++) { 0209 xlib_props[i] = props[i]; 0210 } 0211 XChangeProperty((Display*)qtc_disp, wid, atom, XA_CARDINAL, 32, 0212 PropModeReplace, (unsigned char*)xlib_props.get(), 0213 prop_num); 0214 } else { 0215 qtcX11ChangeProperty(XCB_PROP_MODE_REPLACE, wid, atom, 0216 XCB_ATOM_CARDINAL, 32, prop_num, props); 0217 } 0218 } else { 0219 qtcX11CallVoid(delete_property, wid, atom); 0220 } 0221 qtcX11Flush(); 0222 } 0223 0224 QTC_EXPORT int32_t 0225 qtcX11GetShortProp(xcb_window_t win, xcb_atom_t atom) 0226 { 0227 QTC_RET_IF_FAIL(qtc_xcb_conn && win, -1); 0228 int32_t res = -1; 0229 xcb_get_property_reply_t *reply = 0230 qtcX11GetProperty(0, win, atom, XCB_ATOM_CARDINAL, 0, 1); 0231 QTC_RET_IF_FAIL(reply, -1); 0232 if (xcb_get_property_value_length(reply) > 0) { 0233 uint32_t val = *(int32_t*)xcb_get_property_value(reply); 0234 if (val < 512) { 0235 res = val; 0236 } 0237 } 0238 free(reply); 0239 return res; 0240 } 0241 0242 static inline void 0243 qtcX11SetShortProp(xcb_window_t win, xcb_atom_t atom, unsigned short prop) 0244 { 0245 qtcX11ChangeProperty(XCB_PROP_MODE_REPLACE, win, atom, 0246 XCB_ATOM_CARDINAL, 16, 1, &prop); 0247 qtcX11Flush(); 0248 } 0249 0250 QTC_EXPORT void 0251 qtcX11SetMenubarSize(xcb_window_t win, unsigned short s) 0252 { 0253 qtcX11SetShortProp(win, qtc_x11_qtc_menubar_size, s); 0254 } 0255 0256 QTC_EXPORT void 0257 qtcX11SetStatusBar(xcb_window_t win) 0258 { 0259 qtcX11SetShortProp(win, qtc_x11_qtc_statusbar, 1); 0260 } 0261 0262 QTC_EXPORT void 0263 qtcX11SetOpacity(xcb_window_t win, unsigned short o) 0264 { 0265 qtcX11SetShortProp(win, qtc_x11_qtc_opacity, o); 0266 } 0267 0268 QTC_EXPORT void 0269 qtcX11SetBgnd(xcb_window_t win, uint32_t prop) 0270 { 0271 qtcX11ChangeProperty(XCB_PROP_MODE_REPLACE, win, qtc_x11_qtc_bgnd, 0272 XCB_ATOM_CARDINAL, 32, 1, &prop); 0273 qtcX11Flush(); 0274 } 0275 0276 #else 0277 0278 QTC_EXPORT void 0279 qtcX11ShadowInstall(xcb_window_t, const int[4]) 0280 { 0281 } 0282 0283 QTC_EXPORT void 0284 qtcX11ShadowInstall(xcb_window_t) 0285 { 0286 } 0287 0288 QTC_EXPORT void 0289 qtcX11ShadowUninstall(xcb_window_t) 0290 { 0291 } 0292 0293 // WM Move 0294 QTC_EXPORT void 0295 qtcX11MoveTrigger(xcb_window_t, uint32_t, uint32_t) 0296 { 0297 } 0298 0299 // Blur 0300 QTC_EXPORT void 0301 qtcX11BlurTrigger(xcb_window_t, bool, unsigned, const uint32_t*) 0302 { 0303 } 0304 0305 QTC_EXPORT int32_t 0306 qtcX11GetShortProp(xcb_window_t, xcb_atom_t) 0307 { 0308 return -1; 0309 } 0310 0311 QTC_EXPORT void 0312 qtcX11SetMenubarSize(xcb_window_t, unsigned short) 0313 { 0314 } 0315 0316 QTC_EXPORT void 0317 qtcX11SetStatusBar(xcb_window_t) 0318 { 0319 } 0320 0321 QTC_EXPORT void 0322 qtcX11SetOpacity(xcb_window_t, unsigned short) 0323 { 0324 } 0325 0326 QTC_EXPORT void 0327 qtcX11SetBgnd(xcb_window_t, uint32_t) 0328 { 0329 } 0330 0331 #endif 0332 0333 QTC_EXPORT void 0334 qtcX11SetShadowSize(int size) 0335 { 0336 if (size >= 0 && size != shadow_size) { 0337 shadow_size = size; 0338 #ifdef QTC_ENABLE_X11 0339 qtcX11ShadowDestroy(); 0340 qtcX11ShadowInit(); 0341 #endif 0342 } 0343 } 0344 0345 QTC_EXPORT int 0346 qtcX11ShadowSize() 0347 { 0348 return shadow_size; 0349 } 0350