File indexing completed on 2024-04-28 16:55:26
0001 /* 0002 * Copyright © 2006 Novell, Inc. 0003 * 0004 * This program is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU General Public License 0006 * as published by the Free Software Foundation; either version 2 0007 * of the License, or (at your option) any later version. 0008 * 0009 * This program is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 * GNU General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU General Public License 0015 * along with this program; if not, write to the Free Software 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0017 * 0018 */ 0019 0020 #define NEED_BUTTON_BISTATES 0021 #define NEED_BUTTON_STATE_FLAGS 0022 #define NEED_BUTTON_ACTIONS 0023 #define NEED_BUTTON_FILE_NAMES 0024 #include <emerald.h> 0025 #include <engine.h> 0026 0027 extern gboolean load_engine(gchar *, window_settings *); 0028 extern void load_engine_settings(GKeyFile *, window_settings *); 0029 extern int update_shadow(frame_settings *); 0030 0031 #define C(name) { 0, XC_ ## name } 0032 #define BUTTON_NOT_VISIBLE(ddd, xxx) \ 0033 ((ddd)->tobj_item_state[(xxx)] == 3 || !((ddd)->actions & button_actions[(xxx)])) 0034 0035 //static gboolean enable_tooltips = TRUE; 0036 0037 static gint get_b_offset(gint b) 0038 { 0039 int boffset[B_COUNT+1]; 0040 gint i, b_t = 0; 0041 0042 for (i = 0; i < B_COUNT; i++) 0043 { 0044 boffset[i] = b_t; 0045 if (btbistate[b_t]) 0046 { 0047 boffset[i+1] = b_t; 0048 i++; 0049 } 0050 b_t++; 0051 } 0052 return boffset[b]; 0053 } 0054 0055 static gint get_b_t_offset(gint b_t) 0056 { 0057 int btoffset[B_T_COUNT]; 0058 gint i, b = 0; 0059 0060 for (i = 0; i < B_T_COUNT; i++) 0061 { 0062 btoffset[i] = b; 0063 b++; 0064 if (btbistate[i]) 0065 b++; 0066 } 0067 return btoffset[b_t]; 0068 } 0069 #if 0 /* ************************ */ 0070 //window_settings *global_ws; 0071 static gint get_real_pos(window_settings * ws, gint tobj, decor_t * d) 0072 { 0073 switch (d->tobj_item_state[tobj]) 0074 { 0075 case 1: 0076 return ((d->width + ws->left_space - ws->right_space + 0077 d->tobj_size[0] - d->tobj_size[1] - d->tobj_size[2]) / 2 + 0078 d->tobj_item_pos[tobj]); 0079 case 2: 0080 return (d->width - ws->right_space - d->tobj_size[2] + 0081 d->tobj_item_pos[tobj]); 0082 case 3: 0083 return -1; 0084 default: 0085 return (ws->left_space + d->tobj_item_pos[tobj]); 0086 } 0087 } 0088 #endif 0089 static void update_window_extents(window_settings * ws) 0090 { 0091 //where 4 is v_corn_rad (8 is 2*4), 6 is...? 0092 // 0, 0, L_EXT+4, TT_H+4, 0,0,0,0 0093 // L_EXT+4 0, -8, T_EXT+2, 0,0,1,0 0094 // L_EXT-4, 0, R_EXT+4, TT_H+4, 1,0,0,0 0095 // 0, T_EXT+6, L_EXT, TT_H-6, 0,0,0,1 0096 // L_EXT, T_EXT+2, 0, TT_H-2, 0,0,1,0 0097 // L_EXT, T_EXT+6, R_EXT, TT_H-6, 1,0,0,1 0098 // 0, TT_H, L_EXT+4, B_EXT+4, 0,1,0,0 0099 // L_EXT+4, TT_H+4, -8, B_EXT, 0,1,1,0 0100 // L_EXT-4, TT_H, R_EXT+4, B_EXT+4, 1,1,0,0 0101 gint l_ext = ws->win_extents.left; 0102 gint r_ext = ws->win_extents.right; 0103 gint t_ext = ws->win_extents.top; 0104 gint b_ext = ws->win_extents.bottom; 0105 gint tt_h = ws->titlebar_height; 0106 0107 /*pos_t newpos[3][3] = { 0108 { 0109 { 0, 0, 10, 21, 0, 0, 0, 0 }, 0110 { 10, 0, -8, 6, 0, 0, 1, 0 }, 0111 { 2, 0, 10, 21, 1, 0, 0, 0 } 0112 }, { 0113 { 0, 10, 6, 11, 0, 0, 0, 1 }, 0114 { 6, 6, 0, 15, 0, 0, 1, 0 }, 0115 { 6, 10, 6, 11, 1, 0, 0, 1 } 0116 }, { 0117 { 0, 17, 10, 10, 0, 1, 0, 0 }, 0118 { 10, 21, -8, 6, 0, 1, 1, 0 }, 0119 { 2, 17, 10, 10, 1, 1, 0, 0 } 0120 } 0121 }; */ 0122 pos_t newpos[3][3] = { { 0123 {0, 0, l_ext + 4, tt_h + 4, 0, 0, 0, 0}, 0124 {l_ext + 4, 0, -8, t_ext + 2, 0, 0, 1, 0}, 0125 {l_ext - 4, 0, r_ext + 4, tt_h + 4, 1, 0, 0, 0} 0126 }, { 0127 {0, t_ext + 6, l_ext, tt_h - 6, 0, 0, 0, 1}, 0128 {l_ext, t_ext + 2, 0, tt_h - 2, 0, 0, 1, 0}, 0129 {l_ext, t_ext + 6, r_ext, tt_h - 6, 1, 0, 0, 1} 0130 }, { 0131 {0, tt_h, l_ext + 4, b_ext + 4, 0, 1, 0, 0132 0}, 0133 {l_ext + 4, tt_h + 4, -8, b_ext, 0, 1, 1, 0134 0}, 0135 {l_ext - 4, tt_h, r_ext + 4, b_ext + 4, 1, 0136 1, 0, 0} 0137 } 0138 }; 0139 memcpy(ws->pos, newpos, sizeof(pos_t) * 9); 0140 } 0141 #if 0 0142 static void 0143 gdk_cairo_set_source_color_alpha(cairo_t * cr, GdkColor * color, double alpha) 0144 { 0145 cairo_set_source_rgba(cr, 0146 color->red / 65535.0, 0147 color->green / 65535.0, 0148 color->blue / 65535.0, alpha); 0149 } 0150 0151 static void draw_shadow_background(decor_t * d, cairo_t * cr) 0152 { 0153 cairo_matrix_t matrix; 0154 double w, h, x2, y2; 0155 gint width, height; 0156 gint left, right, top, bottom; 0157 window_settings *ws = d->fs->ws; 0158 0159 if (!ws->large_shadow_pixmap) 0160 { 0161 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); 0162 cairo_paint(cr); 0163 0164 return; 0165 } 0166 0167 gdk_drawable_get_size(ws->large_shadow_pixmap, &width, &height); 0168 0169 left = ws->left_space + ws->left_corner_space; 0170 right = ws->right_space + ws->right_corner_space; 0171 top = ws->top_space + ws->top_corner_space; 0172 bottom = ws->bottom_space + ws->bottom_corner_space; 0173 0174 if (d->width - left - right < 0) 0175 { 0176 left = d->width / 2; 0177 right = d->width - left; 0178 } 0179 0180 if (d->height - top - bottom < 0) 0181 { 0182 top = d->height / 2; 0183 bottom = d->height - top; 0184 } 0185 0186 w = d->width - left - right; 0187 h = d->height - top - bottom; 0188 0189 x2 = d->width - right; 0190 y2 = d->height - bottom; 0191 0192 /* top left */ 0193 cairo_matrix_init_identity(&matrix); 0194 cairo_pattern_set_matrix(ws->shadow_pattern, &matrix); 0195 cairo_set_source(cr, ws->shadow_pattern); 0196 cairo_rectangle(cr, 0.0, 0.0, left, top); 0197 cairo_fill(cr); 0198 0199 /* top */ 0200 if (w > 0) 0201 { 0202 cairo_matrix_init_translate(&matrix, left, 0.0); 0203 cairo_matrix_scale(&matrix, 1.0 / w, 1.0); 0204 cairo_matrix_translate(&matrix, -left, 0.0); 0205 cairo_pattern_set_matrix(ws->shadow_pattern, &matrix); 0206 cairo_set_source(cr, ws->shadow_pattern); 0207 cairo_rectangle(cr, left, 0.0, w, top); 0208 cairo_fill(cr); 0209 } 0210 0211 /* top right */ 0212 cairo_matrix_init_translate(&matrix, width - right - x2, 0.0); 0213 cairo_pattern_set_matrix(ws->shadow_pattern, &matrix); 0214 cairo_set_source(cr, ws->shadow_pattern); 0215 cairo_rectangle(cr, x2, 0.0, right, top); 0216 cairo_fill(cr); 0217 0218 /* left */ 0219 if (h > 0) 0220 { 0221 cairo_matrix_init_translate(&matrix, 0.0, top); 0222 cairo_matrix_scale(&matrix, 1.0, 1.0 / h); 0223 cairo_matrix_translate(&matrix, 0.0, -top); 0224 cairo_pattern_set_matrix(ws->shadow_pattern, &matrix); 0225 cairo_set_source(cr, ws->shadow_pattern); 0226 cairo_rectangle(cr, 0.0, top, left, h); 0227 cairo_fill(cr); 0228 } 0229 0230 /* right */ 0231 if (h > 0) 0232 { 0233 cairo_matrix_init_translate(&matrix, width - right - x2, top); 0234 cairo_matrix_scale(&matrix, 1.0, 1.0 / h); 0235 cairo_matrix_translate(&matrix, 0.0, -top); 0236 cairo_pattern_set_matrix(ws->shadow_pattern, &matrix); 0237 cairo_set_source(cr, ws->shadow_pattern); 0238 cairo_rectangle(cr, x2, top, right, h); 0239 cairo_fill(cr); 0240 } 0241 0242 /* bottom left */ 0243 cairo_matrix_init_translate(&matrix, 0.0, height - bottom - y2); 0244 cairo_pattern_set_matrix(ws->shadow_pattern, &matrix); 0245 cairo_set_source(cr, ws->shadow_pattern); 0246 cairo_rectangle(cr, 0.0, y2, left, bottom); 0247 cairo_fill(cr); 0248 0249 /* bottom */ 0250 if (w > 0) 0251 { 0252 cairo_matrix_init_translate(&matrix, left, height - bottom - y2); 0253 cairo_matrix_scale(&matrix, 1.0 / w, 1.0); 0254 cairo_matrix_translate(&matrix, -left, 0.0); 0255 cairo_pattern_set_matrix(ws->shadow_pattern, &matrix); 0256 cairo_set_source(cr, ws->shadow_pattern); 0257 cairo_rectangle(cr, left, y2, w, bottom); 0258 cairo_fill(cr); 0259 } 0260 0261 /* bottom right */ 0262 cairo_matrix_init_translate(&matrix, width - right - x2, 0263 height - bottom - y2); 0264 cairo_pattern_set_matrix(ws->shadow_pattern, &matrix); 0265 cairo_set_source(cr, ws->shadow_pattern); 0266 cairo_rectangle(cr, x2, y2, right, bottom); 0267 cairo_fill(cr); 0268 } 0269 #endif 0270 0271 static void draw_help_button(decor_t * d, cairo_t * cr, double s) 0272 { 0273 cairo_rel_move_to(cr, 0.0, 6.0); 0274 cairo_rel_line_to(cr, 0.0, 3.0); 0275 cairo_rel_line_to(cr, 4.5, 0.0); 0276 cairo_rel_line_to(cr, 0.0, 4.5); 0277 cairo_rel_line_to(cr, 3.0, 0.0); 0278 cairo_rel_line_to(cr, 0.0, -4.5); 0279 0280 cairo_rel_line_to(cr, 4.5, 0.0); 0281 0282 cairo_rel_line_to(cr, 0.0, -3.0); 0283 cairo_rel_line_to(cr, -4.5, 0.0); 0284 cairo_rel_line_to(cr, 0.0, -4.5); 0285 cairo_rel_line_to(cr, -3.0, 0.0); 0286 cairo_rel_line_to(cr, 0.0, 4.5); 0287 0288 cairo_close_path(cr); 0289 } 0290 static void draw_close_button(decor_t * d, cairo_t * cr, double s) 0291 { 0292 cairo_rel_move_to(cr, 0.0, s); 0293 0294 cairo_rel_line_to(cr, s, -s); 0295 cairo_rel_line_to(cr, s, s); 0296 cairo_rel_line_to(cr, s, -s); 0297 cairo_rel_line_to(cr, s, s); 0298 0299 cairo_rel_line_to(cr, -s, s); 0300 cairo_rel_line_to(cr, s, s); 0301 cairo_rel_line_to(cr, -s, s); 0302 cairo_rel_line_to(cr, -s, -s); 0303 0304 cairo_rel_line_to(cr, -s, s); 0305 cairo_rel_line_to(cr, -s, -s); 0306 cairo_rel_line_to(cr, s, -s); 0307 0308 cairo_close_path(cr); 0309 } 0310 0311 static void draw_max_button(decor_t * d, cairo_t * cr, double s) 0312 { 0313 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); 0314 0315 cairo_rel_line_to(cr, 12.0, 0.0); 0316 cairo_rel_line_to(cr, 0.0, 12.0); 0317 cairo_rel_line_to(cr, -12.0, 0.0); 0318 0319 cairo_close_path(cr); 0320 0321 cairo_rel_move_to(cr, 2.0, s); 0322 0323 cairo_rel_line_to(cr, 8.0, 0.0); 0324 cairo_rel_line_to(cr, 0.0, 10.0 - s); 0325 cairo_rel_line_to(cr, -8.0, 0.0); 0326 0327 cairo_close_path(cr); 0328 } 0329 0330 static void draw_unmax_button(decor_t * d, cairo_t * cr, double s) 0331 { 0332 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); 0333 0334 cairo_rel_move_to(cr, 1.0, 1.0); 0335 0336 cairo_rel_line_to(cr, 10.0, 0.0); 0337 cairo_rel_line_to(cr, 0.0, 10.0); 0338 cairo_rel_line_to(cr, -10.0, 0.0); 0339 0340 cairo_close_path(cr); 0341 0342 cairo_rel_move_to(cr, 2.0, s); 0343 0344 cairo_rel_line_to(cr, 6.0, 0.0); 0345 cairo_rel_line_to(cr, 0.0, 8.0 - s); 0346 cairo_rel_line_to(cr, -6.0, 0.0); 0347 0348 cairo_close_path(cr); 0349 } 0350 0351 static void draw_min_button(decor_t * d, cairo_t * cr, double s) 0352 { 0353 cairo_rel_move_to(cr, 0.0, 8.0); 0354 0355 cairo_rel_line_to(cr, 12.0, 0.0); 0356 cairo_rel_line_to(cr, 0.0, s); 0357 cairo_rel_line_to(cr, -12.0, 0.0); 0358 0359 cairo_close_path(cr); 0360 } 0361 #if 0 0362 typedef void (*draw_proc) (cairo_t * cr); 0363 static void 0364 get_button_pos(window_settings * ws, gint b_t, 0365 decor_t * d, gdouble y1, gdouble * rx, gdouble * ry) 0366 { 0367 //y1 - 4.0 + ws->titlebar_height / 2, 0368 *ry = y1 + ws->button_offset; 0369 *rx = get_real_pos(ws, b_t, d); 0370 } 0371 #endif 0372 static void 0373 button_state_paint(cairo_t * cr, 0374 alpha_color * color, alpha_color * color_2, guint state) 0375 { 0376 double alpha; 0377 0378 if (state & IN_EVENT_WINDOW) 0379 alpha = 1.0; 0380 else 0381 alpha = color->alpha; 0382 0383 if ((state & (PRESSED_EVENT_WINDOW | IN_EVENT_WINDOW)) 0384 == (PRESSED_EVENT_WINDOW | IN_EVENT_WINDOW)) 0385 { 0386 cairo_set_source_rgba(cr, color->color.r, color->color.g, 0387 color->color.b, alpha); 0388 0389 cairo_fill_preserve(cr); 0390 0391 cairo_set_source_alpha_color(cr, color_2); 0392 0393 cairo_set_line_width(cr, 1.0); 0394 cairo_stroke(cr); 0395 cairo_set_line_width(cr, 2.0); 0396 } 0397 else 0398 { 0399 cairo_set_source_alpha_color(cr, color_2); 0400 cairo_stroke_preserve(cr); 0401 0402 cairo_set_source_rgba(cr, color->color.r, color->color.g, 0403 color->color.b, alpha); 0404 0405 cairo_fill(cr); 0406 } 0407 } 0408 static int get_b_state(decor_t * d, int button) 0409 { 0410 int ret = d->active ? 0 : 3; 0411 0412 if (d->button_states[button] & IN_EVENT_WINDOW) 0413 { 0414 ret++; 0415 if (d->button_states[button] & PRESSED_EVENT_WINDOW) 0416 ret++; 0417 } 0418 return ret; 0419 } 0420 static void 0421 draw_pixbuf(GdkPixbuf * pixbuf, cairo_t * cr, 0422 gdouble x, gdouble y, gdouble x2, gdouble y2, gdouble alpha) 0423 { 0424 #if 0 0425 cairo_save(cr); 0426 cairo_rectangle(cr, x, y, x2-x, y2-y); 0427 cairo_clip(cr); 0428 gdk_cairo_set_source_pixbuf(cr, pixbuf, x, y); 0429 cairo_paint_with_alpha(cr, alpha); 0430 cairo_restore(cr); 0431 #endif 0432 } 0433 void 0434 draw_button_with_glow_alpha_bstate(gint b_t, decor_t * d, cairo_t * cr, 0435 gint y1, gdouble button_alpha, 0436 gdouble glow_alpha, int b_state) 0437 { 0438 gint b = b_t; 0439 gdouble x, y; 0440 gdouble x2, y2; 0441 gdouble glow_x, glow_y; // glow top left coordinates 0442 gdouble glow_x2, glow_y2; // glow bottom right coordinates 0443 window_settings *ws = d->fs->ws; 0444 0445 #if 0 0446 if (b_state < 0) 0447 b_state = get_b_state(d, b_t); 0448 0449 b = get_b_t_offset(b_t); 0450 0451 if (btbistate[b_t]) 0452 if (d->state & btstateflag[b_t]) 0453 b++; 0454 0455 if (BUTTON_NOT_VISIBLE(d, b_t)) 0456 return; 0457 #endif 0458 button_region_t *button_region = 0459 (d->active ? &d->button_region[b_t] : &d-> 0460 button_region_inact[b_t]); 0461 x = button_region->base_x1; 0462 y = button_region->base_y1; 0463 0464 if (ws->use_pixmap_buttons) 0465 { 0466 x2 = button_region->base_x2; 0467 y2 = button_region->base_y2; 0468 draw_pixbuf(ws->ButtonPix[b_state + b * S_COUNT], cr, x, y, x2, y2, 0469 button_alpha); 0470 0471 if (glow_alpha > 1e-5) // i.e. glow is on 0472 { 0473 glow_x = button_region->glow_x1; 0474 glow_y = button_region->glow_y1; 0475 glow_x2 = button_region->glow_x2; 0476 glow_y2 = button_region->glow_y2; 0477 if (d->active) 0478 { // Draw glow 0479 draw_pixbuf(ws->ButtonGlowPix[b], cr, glow_x, glow_y, glow_x2, 0480 glow_y2, glow_alpha); 0481 } 0482 else // assume this function won't be called with glow_alpha>0 0483 { // if ws->use_inactive_glow is false 0484 // Draw inactive glow 0485 draw_pixbuf(ws->ButtonInactiveGlowPix[b], cr, glow_x, glow_y, 0486 glow_x2, glow_y2, glow_alpha); 0487 } 0488 } 0489 } 0490 else 0491 { 0492 y += 3; 0493 x += 1; 0494 cairo_set_line_width(cr, 2.0); 0495 cairo_move_to(cr, x, y); 0496 switch (b) 0497 { 0498 case B_CLOSE: 0499 draw_close_button(d, cr, 3.1); 0500 break; 0501 case B_MAXIMIZE: 0502 draw_max_button(d, cr, 4.0); 0503 break; 0504 case B_RESTORE: 0505 draw_unmax_button(d, cr, 4.0); 0506 break; 0507 case B_MINIMIZE: 0508 draw_min_button(d, cr, 4.0); 0509 break; 0510 case B_HELP: 0511 cairo_move_to(cr, x, y); 0512 draw_help_button(d, cr, 3.1); 0513 break; 0514 default: 0515 //FIXME - do something here 0516 break; 0517 } 0518 button_state_paint(cr, &d->fs->button, &d->fs->button_halo, 0519 b_state); 0520 } 0521 } 0522 #if 0 0523 static void 0524 draw_button_with_glow(gint b_t, decor_t * d, cairo_t * cr, gint y1, 0525 gboolean with_glow) 0526 { 0527 draw_button_with_glow_alpha_bstate(b_t, d, cr, y1, 1.0, 0528 (with_glow ? 1.0 : 0.0), -1); 0529 } 0530 static void draw_button(gint b_t, decor_t * d, cairo_t * cr, gint y1) 0531 { 0532 draw_button_with_glow_alpha_bstate(b_t, d, cr, y1, 1.0, 0.0, -1); 0533 } 0534 static void reset_buttons_bg_and_fade(decor_t * d) 0535 { 0536 d->draw_only_buttons_region = FALSE; 0537 d->button_fade_info.cr = NULL; 0538 d->button_fade_info.timer = -1; 0539 int b_t; 0540 0541 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0542 { 0543 d->button_fade_info.counters[b_t] = 0; 0544 d->button_fade_info.pulsating[b_t] = 0; 0545 d->button_region[b_t].base_x1 = -100; 0546 d->button_region[b_t].glow_x1 = -100; 0547 if (d->button_region[b_t].bg_pixmap) 0548 g_object_unref (G_OBJECT (d->button_region[b_t].bg_pixmap)); 0549 d->button_region[b_t].bg_pixmap = NULL; 0550 d->button_region_inact[b_t].base_x1 = -100; 0551 d->button_region_inact[b_t].glow_x1 = -100; 0552 if (d->button_region_inact[b_t].bg_pixmap) 0553 g_object_unref (G_OBJECT (d->button_region_inact[b_t].bg_pixmap)); 0554 d->button_region_inact[b_t].bg_pixmap = NULL; 0555 d->button_last_drawn_state[b_t] = 0; 0556 } 0557 } 0558 static void stop_button_fade(decor_t * d) 0559 { 0560 int j; 0561 0562 if (d->button_fade_info.cr) 0563 { 0564 cairo_destroy(d->button_fade_info.cr); 0565 d->button_fade_info.cr = NULL; 0566 } 0567 if (d->button_fade_info.timer >= 0) 0568 { 0569 g_source_remove(d->button_fade_info.timer); 0570 d->button_fade_info.timer = -1; 0571 } 0572 for (j = 0; j < B_T_COUNT; j++) 0573 d->button_fade_info.counters[j] = 0; 0574 } 0575 static void draw_button_backgrounds(decor_t * d, int *necessary_update_type) 0576 { 0577 int b_t; 0578 window_settings *ws = d->fs->ws; 0579 0580 // Draw button backgrounds 0581 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0582 { 0583 if (BUTTON_NOT_VISIBLE(d, b_t)) 0584 continue; 0585 button_region_t *button_region = (d->active ? &d->button_region[b_t] : 0586 &d->button_region_inact[b_t]); 0587 gint src_x = 0, src_y = 0, w = 0, h = 0, dest_x = 0, dest_y = 0; 0588 0589 if (necessary_update_type[b_t] == 1) 0590 { 0591 w = button_region->base_x2 - button_region->base_x1; 0592 h = button_region->base_y2 - button_region->base_y1; 0593 if (ws->use_pixmap_buttons) 0594 { 0595 dest_x = button_region->base_x1; 0596 dest_y = button_region->base_y1; 0597 if ((ws->use_button_glow && d->active) || 0598 (ws->use_button_inactive_glow && !d->active)) 0599 { 0600 src_x = button_region->base_x1 - button_region->glow_x1; 0601 src_y = button_region->base_y1 - button_region->glow_y1; 0602 } 0603 } 0604 else 0605 { 0606 dest_x = button_region->base_x1 - 2; 0607 dest_y = button_region->base_y1 + 1; 0608 } 0609 } 0610 else if (necessary_update_type[b_t] == 2) 0611 { 0612 dest_x = button_region->glow_x1; 0613 dest_y = button_region->glow_y1; 0614 w = button_region->glow_x2 - button_region->glow_x1; 0615 h = button_region->glow_y2 - button_region->glow_y1; 0616 } 0617 else 0618 return; 0619 if (button_region->bg_pixmap) 0620 gdk_draw_drawable(IS_VALID(d->buffer_pixmap) ? d->buffer_pixmap : 0621 d->pixmap, 0622 d->gc, button_region->bg_pixmap, src_x, src_y, 0623 dest_x, dest_y, w, h); 0624 d->min_drawn_buttons_region.x1 = 0625 MIN(d->min_drawn_buttons_region.x1, dest_x); 0626 d->min_drawn_buttons_region.y1 = 0627 MIN(d->min_drawn_buttons_region.y1, dest_y); 0628 d->min_drawn_buttons_region.x2 = 0629 MAX(d->min_drawn_buttons_region.x2, dest_x + w); 0630 d->min_drawn_buttons_region.y2 = 0631 MAX(d->min_drawn_buttons_region.y2, dest_y + h); 0632 } 0633 } 0634 0635 gint draw_buttons_timer_func(gpointer data) 0636 { 0637 button_fade_info_t *fade_info = (button_fade_info_t *) data; 0638 decor_t *d = (decor_t *) (fade_info->d); 0639 window_settings *ws = d->fs->ws; 0640 int num_steps = ws->button_fade_num_steps; 0641 0642 /* decorations no longer available? */ 0643 if (!d->buffer_pixmap && !d->pixmap) 0644 { 0645 stop_button_fade(d); 0646 return FALSE; 0647 } 0648 0649 d->min_drawn_buttons_region.x1 = 10000; 0650 d->min_drawn_buttons_region.y1 = 10000; 0651 d->min_drawn_buttons_region.x2 = -100; 0652 d->min_drawn_buttons_region.y2 = -100; 0653 0654 if (!fade_info->cr) 0655 { 0656 fade_info->cr = 0657 gdk_cairo_create(GDK_DRAWABLE 0658 (IS_VALID(d->buffer_pixmap) ? d->buffer_pixmap : 0659 d->pixmap)); 0660 cairo_set_operator(fade_info->cr, CAIRO_OPERATOR_OVER); 0661 } 0662 0663 // Determine necessary updates 0664 int b_t; 0665 int necessary_update_type[B_T_COUNT]; // 0: none, 1: only base, 2: base+glow 0666 0667 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0668 necessary_update_type[b_t] = (ws->use_button_glow && d->active) || 0669 (ws->use_button_inactive_glow && !d->active) ? 2:1; 0670 draw_button_backgrounds(d, necessary_update_type); 0671 0672 // Draw the buttons that are in "non-hovered" or pressed state 0673 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0674 { 0675 if (BUTTON_NOT_VISIBLE(d, b_t) || fade_info->counters[b_t] || 0676 necessary_update_type[b_t] == 0) 0677 continue; 0678 int b_state = get_b_state(d, b_t); 0679 int toBeDrawnState = 0680 (d-> 0681 active ? (b_state == S_ACTIVE_PRESS ? 2 : 0) : (b_state == 0682 S_INACTIVE_PRESS 0683 ? 5 : 3)); 0684 draw_button_with_glow_alpha_bstate(b_t, d, fade_info->cr, fade_info->y1, 1.0, 0.0, toBeDrawnState); // no glow here 0685 } 0686 0687 // Draw the buttons that are in "hovered" state (fading in/out or at max fade) 0688 double button_alphas[B_T_COUNT]; 0689 0690 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0691 { 0692 button_alphas[b_t] = 0; 0693 if (BUTTON_NOT_VISIBLE(d, b_t) || 0694 (!fade_info->pulsating[b_t] && !fade_info->counters[b_t])) 0695 continue; 0696 0697 if (ws->button_fade_pulse_len_steps > 0 && fade_info->counters[b_t] && 0698 fade_info->pulsating[b_t]) 0699 { 0700 // If it is time, reverse the fade 0701 if (fade_info->counters[b_t] == 0702 -num_steps + ws->button_fade_pulse_len_steps) 0703 fade_info->counters[b_t] = 1 - fade_info->counters[b_t]; 0704 if (fade_info->counters[b_t] == 0705 num_steps + 1 + ws->button_fade_pulse_wait_steps) 0706 fade_info->counters[b_t] = 0707 1 - MIN(fade_info->counters[b_t], num_steps + 1); 0708 } 0709 if (ws->button_fade_pulse_len_steps > 0 && 0710 fade_info->counters[b_t] == num_steps) 0711 fade_info->pulsating[b_t] = TRUE; // start pulse 0712 0713 if (fade_info->counters[b_t] != num_steps + 1 || // unless fade is at max 0714 (ws->button_fade_pulse_len_steps > 0 && // or at pulse max 0715 fade_info->counters[b_t] != 0716 num_steps + 1 + ws->button_fade_pulse_wait_steps)) 0717 { 0718 fade_info->counters[b_t]++; // increment fade counter 0719 } 0720 d->button_last_drawn_state[b_t] = fade_info->counters[b_t]; 0721 0722 gdouble alpha; 0723 0724 if (fade_info->counters[b_t] > 0) 0725 alpha = (MIN(fade_info->counters[b_t], num_steps + 1) - 0726 1) / (gdouble) num_steps; 0727 else 0728 alpha = -fade_info->counters[b_t] / (gdouble) num_steps; 0729 0730 if (fade_info->counters[b_t] < num_steps + 1) // not at max fade 0731 { 0732 // Draw button's non-hovered version (with 1-alpha) 0733 draw_button_with_glow_alpha_bstate(b_t, d, fade_info->cr, 0734 fade_info->y1, pow(1 - alpha, 0735 0.4), 0.0, 0736 d->active ? 0 : 3); 0737 } 0738 button_alphas[b_t] = alpha; 0739 } 0740 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0741 { 0742 if (button_alphas[b_t] > 1e-4) 0743 { 0744 gdouble glow_alpha = 0.0; 0745 0746 if ((ws->use_button_glow && d->active) || 0747 (ws->use_button_inactive_glow && !d->active)) 0748 glow_alpha = button_alphas[b_t]; 0749 0750 // Draw button's hovered version (with alpha) 0751 draw_button_with_glow_alpha_bstate(b_t, d, fade_info->cr, 0752 fade_info->y1, 0753 button_alphas[b_t], glow_alpha, 0754 d->active ? 1 : 4); 0755 } 0756 } 0757 0758 // Check if the fade has come to an end 0759 gboolean any_active_buttons = FALSE; 0760 0761 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0762 if (!BUTTON_NOT_VISIBLE(d, b_t) && 0763 ((fade_info->counters[b_t] && 0764 fade_info->counters[b_t] < num_steps + 1) || 0765 fade_info->pulsating[b_t])) 0766 { 0767 any_active_buttons = TRUE; 0768 break; 0769 } 0770 0771 if (IS_VALID(d->buffer_pixmap) && !d->button_fade_info.first_draw && 0772 d->min_drawn_buttons_region.x1 < 10000) 0773 { 0774 // if region is updated at least once 0775 gdk_draw_drawable(d->pixmap, 0776 d->gc, 0777 d->buffer_pixmap, 0778 d->min_drawn_buttons_region.x1, 0779 d->min_drawn_buttons_region.y1, 0780 d->min_drawn_buttons_region.x1, 0781 d->min_drawn_buttons_region.y1, 0782 d->min_drawn_buttons_region.x2 - 0783 d->min_drawn_buttons_region.x1, 0784 d->min_drawn_buttons_region.y2 - 0785 d->min_drawn_buttons_region.y1); 0786 } 0787 fade_info->first_draw = FALSE; 0788 if (!any_active_buttons) 0789 { 0790 cairo_destroy(fade_info->cr); 0791 fade_info->cr = NULL; 0792 if (fade_info->timer >= 0) 0793 { 0794 g_source_remove(fade_info->timer); 0795 fade_info->timer = -1; 0796 } 0797 return FALSE; 0798 } 0799 return TRUE; 0800 } 0801 static void draw_buttons_with_fade(decor_t * d, cairo_t * cr, double y1) 0802 { 0803 window_settings *ws = d->fs->ws; 0804 int b_t; 0805 0806 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0807 { 0808 if (BUTTON_NOT_VISIBLE(d, b_t)) 0809 continue; 0810 if (!(d->active ? d->button_region[b_t] : d->button_region_inact[b_t]).bg_pixmap) // don't draw if bg_pixmaps are not valid 0811 return; 0812 } 0813 button_fade_info_t *fade_info = &(d->button_fade_info); 0814 gboolean button_pressed = FALSE; 0815 0816 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0817 { 0818 if (BUTTON_NOT_VISIBLE(d, b_t)) 0819 continue; 0820 int b_state = get_b_state(d, b_t); 0821 0822 if (fade_info->counters[b_t] != 0 && 0823 (b_state == S_ACTIVE_PRESS || b_state == S_INACTIVE_PRESS)) 0824 { 0825 // Button pressed, stop fade 0826 fade_info->counters[b_t] = 0; 0827 button_pressed = TRUE; 0828 } 0829 else if (fade_info->counters[b_t] > 0 && (b_state == S_ACTIVE || b_state == S_INACTIVE)) // moved out 0830 { 0831 // Change fade in -> out and proceed 1 step 0832 fade_info->counters[b_t] = 0833 1 - MIN(fade_info->counters[b_t], 0834 ws->button_fade_num_steps + 1); 0835 } 0836 else if (fade_info->counters[b_t] < 0 && 0837 (b_state == S_ACTIVE_HOVER || b_state == S_INACTIVE_HOVER)) 0838 { 0839 // Change fade out -> in and proceed 1 step 0840 fade_info->counters[b_t] = 1 - fade_info->counters[b_t]; 0841 } 0842 else if (fade_info->counters[b_t] == 0 && 0843 (b_state == S_ACTIVE_HOVER || b_state == S_INACTIVE_HOVER)) 0844 { 0845 // Start fade in 0846 fade_info->counters[b_t] = 1; 0847 } 0848 if (fade_info->pulsating[b_t] && 0849 b_state != S_ACTIVE_HOVER && b_state != S_INACTIVE_HOVER) 0850 { 0851 // Stop pulse 0852 fade_info->pulsating[b_t] = FALSE; 0853 } 0854 } 0855 0856 if (fade_info->timer == -1 || button_pressed) 0857 // button_pressed is needed because sometimes after a button is pressed, 0858 // this function is called twice, first with S_(IN)ACTIVE, then with S_(IN)ACTIVE_PRESS 0859 // where it should have been only once with S_(IN)ACTIVE_PRESS 0860 { 0861 fade_info->d = (gpointer) d; 0862 fade_info->y1 = y1; 0863 if (draw_buttons_timer_func((gpointer) fade_info) == TRUE) // call once now 0864 { 0865 // and start a new timer for the next step 0866 fade_info->timer = 0867 g_timeout_add(ws->button_fade_step_duration, 0868 draw_buttons_timer_func, 0869 (gpointer) fade_info); 0870 } 0871 } 0872 } 0873 static void draw_buttons_without_fade(decor_t * d, cairo_t * cr, double y1) 0874 { 0875 window_settings *ws = d->fs->ws; 0876 0877 d->min_drawn_buttons_region.x1 = 10000; 0878 d->min_drawn_buttons_region.y1 = 10000; 0879 d->min_drawn_buttons_region.x2 = -100; 0880 d->min_drawn_buttons_region.y2 = -100; 0881 0882 int b_t; 0883 int necessary_update_type[B_T_COUNT]; // 0: none, 1: only base, 2: base+glow 0884 0885 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0886 necessary_update_type[b_t] = (ws->use_button_glow && d->active) || 0887 (ws->use_button_inactive_glow && !d->active) ? 2:1; 0888 //necessary_update_type[b_t] = 2; 0889 0890 draw_button_backgrounds(d, necessary_update_type); 0891 0892 // Draw buttons 0893 gint button_hovered_on = -1; 0894 0895 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0896 { 0897 if (necessary_update_type[b_t] == 0) 0898 continue; 0899 int b_state = get_b_state(d, b_t); 0900 0901 if (ws->use_pixmap_buttons && 0902 ((ws->use_button_glow && b_state == S_ACTIVE_HOVER) || 0903 (ws->use_button_inactive_glow && b_state == S_INACTIVE_HOVER))) 0904 { 0905 // skip the one being hovered on, if any 0906 button_hovered_on = b_t; 0907 } 0908 else 0909 draw_button(b_t, d, cr, y1); 0910 } 0911 if (button_hovered_on >= 0) 0912 { 0913 // Draw the button and the glow for the button hovered on 0914 draw_button_with_glow(button_hovered_on, d, cr, y1, TRUE); 0915 } 0916 } 0917 static void update_button_regions(decor_t * d) 0918 { 0919 window_settings *ws = d->fs->ws; 0920 gint y1 = ws->top_space - ws->win_extents.top; 0921 0922 gint b_t, b_t2; 0923 gdouble x, y; 0924 gdouble glow_x, glow_y; // glow top left coordinates 0925 0926 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0927 { 0928 if (BUTTON_NOT_VISIBLE(d, b_t)) 0929 continue; 0930 button_region_t *button_region = &(d->button_region[b_t]); 0931 0932 if (button_region->bg_pixmap) 0933 { 0934 g_object_unref (G_OBJECT (button_region->bg_pixmap)); 0935 button_region->bg_pixmap = NULL; 0936 } 0937 if (d->button_region_inact[b_t].bg_pixmap) 0938 { 0939 g_object_unref (G_OBJECT (d->button_region_inact[b_t].bg_pixmap)); 0940 d->button_region_inact[b_t].bg_pixmap = NULL; 0941 } 0942 // Reset overlaps 0943 for (b_t2 = 0; b_t2 < b_t; b_t2++) 0944 if (!BUTTON_NOT_VISIBLE(d, b_t2)) 0945 d->button_region[b_t].overlap_buttons[b_t2] = FALSE; 0946 for (b_t2 = 0; b_t2 < b_t; b_t2++) 0947 if (!BUTTON_NOT_VISIBLE(d, b_t2)) 0948 d->button_region_inact[b_t].overlap_buttons[b_t2] = FALSE; 0949 } 0950 d->button_fade_info.first_draw = TRUE; 0951 0952 if (ws->use_pixmap_buttons) 0953 { 0954 if ((d->active && ws->use_button_glow) || 0955 (!d->active && ws->use_button_inactive_glow)) 0956 { 0957 for (b_t = 0; b_t < B_T_COUNT; b_t++) 0958 { 0959 if (BUTTON_NOT_VISIBLE(d, b_t)) 0960 continue; 0961 get_button_pos(ws, b_t, d, y1, &x, &y); 0962 button_region_t *button_region = &(d->button_region[b_t]); 0963 0964 glow_x = x - (ws->c_glow_size.w - ws->c_icon_size[b_t].w) / 2; 0965 glow_y = y - (ws->c_glow_size.h - ws->c_icon_size[b_t].h) / 2; 0966 0967 button_region->base_x1 = x; 0968 button_region->base_y1 = y; 0969 button_region->base_x2 = x + ws->c_icon_size[b_t].w; 0970 button_region->base_y2 = MIN(y + ws->c_icon_size[b_t].h, 0971 ws->top_space + 0972 ws->titlebar_height); 0973 0974 button_region->glow_x1 = glow_x; 0975 button_region->glow_y1 = glow_y; 0976 button_region->glow_x2 = glow_x + ws->c_glow_size.w; 0977 button_region->glow_y2 = MIN(glow_y + ws->c_glow_size.h, 0978 ws->top_space + 0979 ws->titlebar_height); 0980 0981 // Update glow overlaps of each pair 0982 0983 for (b_t2 = 0; b_t2 < b_t; b_t2++) 0984 { // coordinates for these b_t2's will be ready for this b_t here 0985 if (BUTTON_NOT_VISIBLE(d, b_t2)) 0986 continue; 0987 if ((button_region->base_x1 > d->button_region[b_t2].base_x1 && //right of b_t2 0988 button_region->glow_x1 <= d->button_region[b_t2].base_x2) || (button_region->base_x1 < d->button_region[b_t2].base_x1 && //left of b_t2 0989 button_region-> 0990 glow_x2 0991 >= 0992 d-> 0993 button_region 0994 [b_t2]. 0995 base_x1)) 0996 { 0997 button_region->overlap_buttons[b_t2] = TRUE; 0998 } 0999 else 1000 button_region->overlap_buttons[b_t2] = FALSE; 1001 1002 // buttons' protruding glow length might be asymmetric 1003 if ((d->button_region[b_t2].base_x1 > button_region->base_x1 && //left of b_t2 1004 d->button_region[b_t2].glow_x1 <= button_region->base_x2) || (d->button_region[b_t2].base_x1 < button_region->base_x1 && //right of b_t2 1005 d-> 1006 button_region 1007 [b_t2]. 1008 glow_x2 1009 >= 1010 button_region-> 1011 base_x1)) 1012 { 1013 d->button_region[b_t2].overlap_buttons[b_t] = TRUE; 1014 } 1015 else 1016 d->button_region[b_t2].overlap_buttons[b_t] = FALSE; 1017 } 1018 } 1019 } 1020 else 1021 { 1022 for (b_t = 0; b_t < B_T_COUNT; b_t++) 1023 { 1024 if (BUTTON_NOT_VISIBLE(d, b_t)) 1025 continue; 1026 get_button_pos(ws, b_t, d, y1, &x, &y); 1027 button_region_t *button_region = &(d->button_region[b_t]); 1028 1029 button_region->base_x1 = x; 1030 button_region->base_y1 = y; 1031 button_region->base_x2 = x + ws->c_icon_size[b_t].w; 1032 button_region->base_y2 = MIN(y + ws->c_icon_size[b_t].h, 1033 ws->top_space + 1034 ws->titlebar_height); 1035 } 1036 } 1037 } 1038 else 1039 { 1040 for (b_t = 0; b_t < B_T_COUNT; b_t++) 1041 { 1042 if (BUTTON_NOT_VISIBLE(d, b_t)) 1043 continue; 1044 get_button_pos(ws, b_t, d, y1, &x, &y); 1045 button_region_t *button_region = &(d->button_region[b_t]); 1046 1047 button_region->base_x1 = x; 1048 button_region->base_y1 = y; 1049 button_region->base_x2 = x + 16; 1050 button_region->base_y2 = y + 16; 1051 } 1052 } 1053 for (b_t = 0; b_t < B_T_COUNT; b_t++) 1054 { 1055 button_region_t *button_region = &(d->button_region[b_t]); 1056 button_region_t *button_region_inact = &(d->button_region_inact[b_t]); 1057 1058 memcpy(button_region_inact, button_region, sizeof(button_region_t)); 1059 } 1060 } 1061 static void draw_window_decoration_real(decor_t * d, gboolean shadow_time) 1062 { 1063 cairo_t *cr; 1064 double x1, y1, x2, y2, h; 1065 int top; 1066 frame_settings *fs = d->fs; 1067 window_settings *ws = fs->ws; 1068 1069 if (!d->pixmap) 1070 return; 1071 1072 top = ws->win_extents.top + ws->titlebar_height; 1073 1074 x1 = ws->left_space - ws->win_extents.left; 1075 y1 = ws->top_space - ws->win_extents.top; 1076 x2 = d->width - ws->right_space + ws->win_extents.right; 1077 y2 = d->height - ws->bottom_space + ws->win_extents.bottom; 1078 1079 h = d->height - ws->top_space - ws->titlebar_height - ws->bottom_space; 1080 1081 if (!d->draw_only_buttons_region) // if not only drawing buttons 1082 { 1083 cr = gdk_cairo_create(GDK_DRAWABLE 1084 (IS_VALID(d->buffer_pixmap) ? d->buffer_pixmap : 1085 d->pixmap)); 1086 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); 1087 cairo_set_line_width(cr, 1.0); 1088 cairo_save(cr); 1089 draw_shadow_background(d, cr); 1090 engine_draw_frame(d, cr); 1091 cairo_restore(cr); 1092 cairo_set_operator(cr, CAIRO_OPERATOR_OVER); 1093 cairo_set_line_width(cr, 2.0); 1094 1095 /*color.r = 1; 1096 color.g = 1; 1097 color.b = 1; */ 1098 1099 // the buttons were previously drawn here, so we need to save the cairo state here 1100 cairo_save(cr); 1101 1102 if (d->layout && d->tobj_item_state[TBT_TITLE] != 3) 1103 { 1104 pango_layout_set_alignment(d->layout, ws->title_text_align); 1105 cairo_move_to(cr, 1106 get_real_pos(ws, TBT_TITLE, d), 1107 y1 + 2.0 + (ws->titlebar_height - 1108 ws->text_height) / 2.0); 1109 1110 /* ===================active text colors */ 1111 cairo_set_source_alpha_color(cr, &fs->text_halo); 1112 pango_cairo_layout_path(cr, d->layout); 1113 cairo_stroke(cr); 1114 1115 cairo_set_source_alpha_color(cr, &fs->text); 1116 1117 cairo_move_to(cr, 1118 get_real_pos(ws, TBT_TITLE, d), 1119 y1 + 2.0 + (ws->titlebar_height - 1120 ws->text_height) / 2.0); 1121 1122 pango_cairo_show_layout(cr, d->layout); 1123 } 1124 if (d->icon && d->tobj_item_state[TBT_ICON] != 3) 1125 { 1126 cairo_translate(cr, get_real_pos(ws, TBT_ICON, d), 1127 y1 - 5.0 + ws->titlebar_height / 2); 1128 1129 cairo_set_source(cr, d->icon); 1130 cairo_rectangle(cr, 0.0, 0.0, 16.0, 16.0); 1131 cairo_clip(cr); 1132 cairo_paint(cr); 1133 } 1134 // Copy button region backgrounds to buffers 1135 // for fast drawing of buttons from now on 1136 // when drawing is done for buttons 1137 gboolean bg_pixmaps_update_needed = FALSE; 1138 int b_t; 1139 1140 for (b_t = 0; b_t < B_T_COUNT; b_t++) 1141 { 1142 button_region_t *button_region = 1143 (d->active ? &d->button_region[b_t] : &d-> 1144 button_region_inact[b_t]); 1145 if (BUTTON_NOT_VISIBLE(d, b_t)) 1146 continue; 1147 if (!button_region->bg_pixmap && button_region->base_x1 >= 0) // if region is valid 1148 { 1149 bg_pixmaps_update_needed = TRUE; 1150 break; 1151 } 1152 } 1153 if (bg_pixmaps_update_needed && !shadow_time) 1154 { 1155 for (b_t = 0; b_t < B_T_COUNT; b_t++) 1156 { 1157 if (BUTTON_NOT_VISIBLE(d, b_t)) 1158 continue; 1159 1160 button_region_t *button_region = 1161 (d->active ? &d->button_region[b_t] : &d-> 1162 button_region_inact[b_t]); 1163 gint rx, ry, rw, rh; 1164 1165 if (ws->use_pixmap_buttons && 1166 ((ws->use_button_glow && d->active) || 1167 (ws->use_button_inactive_glow && !d->active))) 1168 { 1169 if (button_region->glow_x1 == -100) // skip uninitialized regions 1170 continue; 1171 rx = button_region->glow_x1; 1172 ry = button_region->glow_y1; 1173 rw = button_region->glow_x2 - button_region->glow_x1; 1174 rh = button_region->glow_y2 - button_region->glow_y1; 1175 } 1176 else 1177 { 1178 if (button_region->base_x1 == -100) // skip uninitialized regions 1179 continue; 1180 rx = button_region->base_x1; 1181 ry = button_region->base_y1; 1182 if (!ws->use_pixmap_buttons) // offset: (-2,1) 1183 { 1184 rx -= 2; 1185 ry++; 1186 } 1187 rw = button_region->base_x2 - button_region->base_x1; 1188 rh = button_region->base_y2 - button_region->base_y1; 1189 } 1190 if (!button_region->bg_pixmap) 1191 button_region->bg_pixmap = create_pixmap(rw, rh); 1192 if (!button_region->bg_pixmap) 1193 { 1194 fprintf(stderr, 1195 "%s: Error allocating buffer.\n", program_name); 1196 } 1197 else 1198 { 1199 gdk_draw_drawable(button_region->bg_pixmap, d->gc, 1200 IS_VALID(d->buffer_pixmap) ? 1201 d->buffer_pixmap : d->pixmap, 1202 rx, ry, 0, 0, 1203 rw, rh); 1204 } 1205 } 1206 } 1207 cairo_restore(cr); // and restore the state for button drawing 1208 /*if (!shadow_time) 1209 { 1210 //workaround for slowness, will grab and rotate the two side-pieces 1211 gint w, h; 1212 cairo_surface_t * csur; 1213 cairo_pattern_t * sr; 1214 cairo_matrix_t cm; 1215 cairo_destroy(cr); 1216 gint topspace = ws->top_space + ws->titlebar_height; 1217 cr = gdk_cairo_create (GDK_DRAWABLE (d->buffer_pixmap ? d->buffer_pixmap : d->pixmap)); 1218 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); 1219 1220 gdk_drawable_get_size(pbuff,&w,&h); 1221 csur = cairo_xlib_surface_create( 1222 GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), 1223 GDK_PIXMAP_XID(pbuff), 1224 GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(pbuff)), 1225 w,h); 1226 1227 cairo_set_source_surface(cr, csur, 0, 0); 1228 sr = cairo_get_source(cr); 1229 cairo_pattern_get_matrix(sr, &cm); 1230 1231 //draw all four quads from the old one to the new one 1232 //first top quad 1233 cairo_save(cr); 1234 cairo_rectangle(cr, 0, 0, d->width, topspace); 1235 cairo_clip(cr); 1236 cairo_pattern_set_matrix(sr, &cm); 1237 cairo_paint(cr); 1238 cairo_restore(cr); 1239 1240 //then bottom, easiest this way 1241 cairo_save(cr); 1242 cairo_rectangle(cr, 0, topspace, d->width, ws->bottom_space); 1243 cairo_clip(cr); 1244 cm.y0 = d->height - (top_space + ws->bottom_space); 1245 cm.x0 = 0; 1246 cairo_pattern_set_matrix(sr,&cm); 1247 cairo_paint(cr); 1248 cairo_restore(cr); 1249 1250 //now left 1251 cairo_save(cr); 1252 cairo_rectangle(cr, 0, topspace + ws->bottom_space, 1253 d->height-(topspace + ws->bottom_space), ws->left_space); 1254 cairo_clip(cr); 1255 cm.xx=0; 1256 cm.xy=1; 1257 cm.yx=1; 1258 cm.yy=0; 1259 cm.x0 = - topspace - ws->bottom_space; 1260 cm.y0 = topspace; 1261 cairo_pattern_set_matrix(sr,&cm); 1262 cairo_paint(cr); 1263 cairo_restore(cr); 1264 1265 //now right 1266 cairo_save(cr); 1267 cairo_rectangle(cr, 0, topspace + ws->bottom_space + ws->left_space, 1268 d->height-(topspace + ws->bottom_space), ws->right_space); 1269 cairo_clip(cr); 1270 cm.y0 = topspace; 1271 cm.x0 = d->width- 1272 (topspace + ws->bottom_space + ws->left_space + ws->right_space); 1273 cairo_pattern_set_matrix(sr,&cm); 1274 cairo_paint(cr); 1275 cairo_restore(cr); 1276 1277 1278 cairo_destroy(cr); 1279 g_object_unref (G_OBJECT (pbuff)); 1280 cairo_surface_destroy(csur); 1281 } 1282 */ 1283 } 1284 // Draw buttons 1285 1286 cr = gdk_cairo_create(GDK_DRAWABLE (IS_VALID(d->buffer_pixmap) ? 1287 d->buffer_pixmap : d->pixmap)); 1288 1289 cairo_set_operator(cr, CAIRO_OPERATOR_OVER); 1290 1291 if (ws->use_button_fade && ws->use_pixmap_buttons) 1292 draw_buttons_with_fade(d, cr, y1); 1293 else 1294 draw_buttons_without_fade(d, cr, y1); 1295 1296 cairo_destroy(cr); 1297 1298 if (IS_VALID(d->buffer_pixmap)) 1299 { 1300 /*if (d->draw_only_buttons_region && d->min_drawn_buttons_region.x1 < 10000) // if region is updated at least once 1301 { 1302 gdk_draw_drawable(d->pixmap, 1303 d->gc, 1304 d->buffer_pixmap, 1305 d->min_drawn_buttons_region.x1, 1306 d->min_drawn_buttons_region.y1, 1307 d->min_drawn_buttons_region.x1, 1308 d->min_drawn_buttons_region.y1, 1309 d->min_drawn_buttons_region.x2 - 1310 d->min_drawn_buttons_region.x1, 1311 d->min_drawn_buttons_region.y2 - 1312 d->min_drawn_buttons_region.y1); 1313 } 1314 else*/ 1315 { 1316 gdk_draw_drawable(d->pixmap, 1317 d->gc, 1318 d->buffer_pixmap, 1319 0, 1320 0, 1321 0, 1322 0, 1323 d->width, 1324 d->height); 1325 //ws->top_space + ws->bottom_space + 1326 //ws->titlebar_height + 2); 1327 } 1328 } 1329 } 1330 1331 static void draw_window_decoration(decor_t * d) 1332 { 1333 if (d->active) 1334 { 1335 d->pixmap = d->p_active; 1336 d->buffer_pixmap = d->p_active_buffer; 1337 } 1338 else 1339 { 1340 d->pixmap = d->p_inactive; 1341 d->buffer_pixmap = d->p_inactive_buffer; 1342 } 1343 if (d->draw_only_buttons_region) 1344 draw_window_decoration_real(d, FALSE); 1345 if (!d->only_change_active) 1346 { 1347 gboolean save = d->active; 1348 frame_settings *fs = d->fs; 1349 1350 d->active = TRUE; 1351 d->fs = d->fs->ws->fs_act; 1352 d->pixmap = d->p_active; 1353 d->buffer_pixmap = d->p_active_buffer; 1354 draw_window_decoration_real(d, FALSE); 1355 d->active = FALSE; 1356 d->fs = d->fs->ws->fs_inact; 1357 d->pixmap = d->p_inactive; 1358 d->buffer_pixmap = d->p_inactive_buffer; 1359 draw_window_decoration_real(d, FALSE); 1360 d->active = save; 1361 d->fs = fs; 1362 } 1363 else 1364 { 1365 d->only_change_active = FALSE; 1366 } 1367 if (d->active) 1368 { 1369 d->pixmap = d->p_active; 1370 d->buffer_pixmap = d->p_active_buffer; 1371 } 1372 else 1373 { 1374 d->pixmap = d->p_inactive; 1375 d->buffer_pixmap = d->p_inactive_buffer; 1376 } 1377 if (d->prop_xid) 1378 { 1379 decor_update_window_property(d); 1380 d->prop_xid = 0; 1381 } 1382 d->draw_only_buttons_region = FALSE; 1383 } 1384 static void draw_shadow_window(decor_t * d) 1385 { 1386 draw_window_decoration_real(d, TRUE); 1387 } 1388 1389 /* to save some memory, value is specific to current decorations */ 1390 #define CORNER_REDUCTION 3 1391 1392 static int update_shadow(frame_settings * fs) 1393 { 1394 #if 0 1395 Display *xdisplay = gdk_display; 1396 XRenderPictFormat *format; 1397 GdkPixmap *pixmap; 1398 Picture src, dst, tmp; 1399 XFixed *params; 1400 XFilters *filters; 1401 char *filter = NULL; 1402 int size, n_params = 0; 1403 #endif 1404 cairo_t *cr; 1405 decor_t d; 1406 1407 bzero(&d, sizeof(decor_t)); 1408 window_settings *ws = fs->ws; 1409 #if 0 1410 // double save_decoration_alpha; 1411 static XRenderColor color; 1412 static XRenderColor clear = { 0x0000, 0x0000, 0x0000, 0x0000 }; 1413 static XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff }; 1414 1415 color.red = ws->shadow_color[0]; 1416 color.green = ws->shadow_color[1]; 1417 color.blue = ws->shadow_color[2]; 1418 color.alpha = 0xffff; 1419 1420 /* compute a gaussian convolution kernel */ 1421 params = create_gaussian_kernel(ws->shadow_radius, ws->shadow_radius / 2.0, // SIGMA 1422 ws->shadow_radius, // ALPHA 1423 ws->shadow_opacity, &size); 1424 if (!params) 1425 ws->shadow_offset_x = ws->shadow_offset_y = size = 0; 1426 1427 if (ws->shadow_radius <= 0.0 && ws->shadow_offset_x == 0 && 1428 ws->shadow_offset_y == 0) 1429 size = 0; 1430 1431 n_params = size + 2; 1432 size = size / 2; 1433 #endif 1434 ws->left_space = ws->win_extents.left + size - ws->shadow_offset_x; 1435 ws->right_space = ws->win_extents.right + size + ws->shadow_offset_x; 1436 ws->top_space = ws->win_extents.top + size - ws->shadow_offset_y; 1437 ws->bottom_space = ws->win_extents.bottom + size + ws->shadow_offset_y; 1438 1439 1440 ws->left_space = MAX(ws->win_extents.left, ws->left_space); 1441 ws->right_space = MAX(ws->win_extents.right, ws->right_space); 1442 ws->top_space = MAX(ws->win_extents.top, ws->top_space); 1443 ws->bottom_space = MAX(ws->win_extents.bottom, ws->bottom_space); 1444 1445 ws->shadow_left_space = MAX(0, size - ws->shadow_offset_x); 1446 ws->shadow_right_space = MAX(0, size + ws->shadow_offset_x); 1447 ws->shadow_top_space = MAX(0, size - ws->shadow_offset_y); 1448 ws->shadow_bottom_space = MAX(0, size + ws->shadow_offset_y); 1449 1450 ws->shadow_left_corner_space = MAX(0, size + ws->shadow_offset_x); 1451 ws->shadow_right_corner_space = MAX(0, size - ws->shadow_offset_x); 1452 ws->shadow_top_corner_space = MAX(0, size + ws->shadow_offset_y); 1453 ws->shadow_bottom_corner_space = MAX(0, size - ws->shadow_offset_y); 1454 1455 ws->left_corner_space = 1456 MAX(0, ws->shadow_left_corner_space - CORNER_REDUCTION); 1457 ws->right_corner_space = 1458 MAX(0, ws->shadow_right_corner_space - CORNER_REDUCTION); 1459 ws->top_corner_space = 1460 MAX(0, ws->shadow_top_corner_space - CORNER_REDUCTION); 1461 ws->bottom_corner_space = 1462 MAX(0, ws->shadow_bottom_corner_space - CORNER_REDUCTION); 1463 1464 ws->normal_top_corner_space = 1465 MAX(0, ws->top_corner_space - ws->titlebar_height); 1466 ws->switcher_top_corner_space = 1467 MAX(0, ws->top_corner_space - SWITCHER_TOP_EXTRA); 1468 ws->switcher_bottom_corner_space = 1469 MAX(0, ws->bottom_corner_space - SWITCHER_SPACE); 1470 1471 d.buffer_pixmap = NULL; 1472 d.layout = NULL; 1473 d.icon = NULL; 1474 d.state = 0; 1475 d.actions = 0; 1476 d.prop_xid = 0; 1477 d.draw = draw_shadow_window; 1478 d.active = TRUE; 1479 d.fs = fs; 1480 1481 reset_buttons_bg_and_fade(&d); 1482 1483 d.width = 1484 ws->left_space + ws->left_corner_space + 1 + 1485 ws->right_corner_space + ws->right_space; 1486 d.height = 1487 ws->top_space + ws->titlebar_height + 1488 ws->normal_top_corner_space + 2 + ws->bottom_corner_space + 1489 ws->bottom_space; 1490 #if 0 1491 /* all pixmaps are ARGB32 */ 1492 format = XRenderFindStandardFormat(xdisplay, PictStandardARGB32); 1493 1494 /* shadow color */ 1495 src = XRenderCreateSolidFill(xdisplay, &color); 1496 1497 if (ws->large_shadow_pixmap) 1498 { 1499 g_object_unref (G_OBJECT (ws->large_shadow_pixmap)); 1500 ws->large_shadow_pixmap = NULL; 1501 } 1502 1503 if (ws->shadow_pattern) 1504 { 1505 cairo_pattern_destroy(ws->shadow_pattern); 1506 ws->shadow_pattern = NULL; 1507 } 1508 1509 if (ws->shadow_pixmap) 1510 { 1511 g_object_unref (G_OBJECT (ws->shadow_pixmap)); 1512 ws->shadow_pixmap = NULL; 1513 } 1514 1515 /* no shadow */ 1516 if (size <= 0) 1517 { 1518 if (params) 1519 g_free(params); 1520 1521 return 1; 1522 } 1523 1524 pixmap = create_pixmap(d.width, d.height); 1525 if (!pixmap) 1526 { 1527 g_free(params); 1528 return 0; 1529 } 1530 1531 /* query server for convolution filter */ 1532 filters = XRenderQueryFilters(xdisplay, GDK_PIXMAP_XID(pixmap)); 1533 if (filters) 1534 { 1535 int i; 1536 1537 for (i = 0; i < filters->nfilter; i++) 1538 { 1539 if (strcmp(filters->filter[i], FilterConvolution) == 0) 1540 { 1541 filter = FilterConvolution; 1542 break; 1543 } 1544 } 1545 1546 XFree(filters); 1547 } 1548 1549 if (!filter) 1550 { 1551 fprintf(stderr, "can't generate shadows, X server doesn't support " 1552 "convolution filters\n"); 1553 1554 g_free(params); 1555 g_object_unref (G_OBJECT (pixmap)); 1556 return 1; 1557 } 1558 1559 /* WINDOWS WITH DECORATION */ 1560 1561 d.pixmap = create_pixmap(d.width, d.height); 1562 if (!d.pixmap) 1563 { 1564 g_free(params); 1565 g_object_unref (G_OBJECT (pixmap)); 1566 return 0; 1567 } 1568 1569 /* draw decorations */ 1570 (*d.draw) (&d); 1571 1572 dst = XRenderCreatePicture(xdisplay, GDK_PIXMAP_XID(d.pixmap), 1573 format, 0, NULL); 1574 tmp = XRenderCreatePicture(xdisplay, GDK_PIXMAP_XID(pixmap), 1575 format, 0, NULL); 1576 1577 /* first pass */ 1578 params[0] = (n_params - 2) << 16; 1579 params[1] = 1 << 16; 1580 1581 set_picture_transform(xdisplay, dst, ws->shadow_offset_x, 0); 1582 XRenderSetPictureFilter(xdisplay, dst, filter, params, n_params); 1583 XRenderComposite(xdisplay, 1584 PictOpSrc, 1585 src, dst, tmp, 0, 0, 0, 0, 0, 0, d.width, d.height); 1586 1587 /* second pass */ 1588 params[0] = 1 << 16; 1589 params[1] = (n_params - 2) << 16; 1590 1591 set_picture_transform(xdisplay, tmp, 0, ws->shadow_offset_y); 1592 XRenderSetPictureFilter(xdisplay, tmp, filter, params, n_params); 1593 XRenderComposite(xdisplay, 1594 PictOpSrc, 1595 src, tmp, dst, 0, 0, 0, 0, 0, 0, d.width, d.height); 1596 1597 XRenderFreePicture(xdisplay, tmp); 1598 XRenderFreePicture(xdisplay, dst); 1599 1600 g_object_unref (G_OBJECT (pixmap)); 1601 1602 ws->large_shadow_pixmap = d.pixmap; 1603 1604 cr = gdk_cairo_create(GDK_DRAWABLE(ws->large_shadow_pixmap)); 1605 ws->shadow_pattern = 1606 cairo_pattern_create_for_surface(cairo_get_target(cr)); 1607 cairo_pattern_set_filter(ws->shadow_pattern, CAIRO_FILTER_NEAREST); 1608 cairo_destroy(cr); 1609 1610 1611 /* WINDOWS WITHOUT DECORATIONS */ 1612 1613 d.width = ws->shadow_left_space + ws->shadow_left_corner_space + 1 + 1614 ws->shadow_right_space + ws->shadow_right_corner_space; 1615 d.height = ws->shadow_top_space + ws->shadow_top_corner_space + 1 + 1616 ws->shadow_bottom_space + ws->shadow_bottom_corner_space; 1617 1618 pixmap = create_pixmap(d.width, d.height); 1619 if (!pixmap) 1620 { 1621 g_free(params); 1622 return 0; 1623 } 1624 1625 d.pixmap = create_pixmap(d.width, d.height); 1626 if (!d.pixmap) 1627 { 1628 g_object_unref (G_OBJECT (pixmap)); 1629 g_free(params); 1630 return 0; 1631 } 1632 1633 dst = XRenderCreatePicture(xdisplay, GDK_PIXMAP_XID(d.pixmap), 1634 format, 0, NULL); 1635 1636 /* draw rectangle */ 1637 XRenderFillRectangle(xdisplay, PictOpSrc, dst, &clear, 1638 0, 0, d.width, d.height); 1639 XRenderFillRectangle(xdisplay, PictOpSrc, dst, &white, 1640 ws->shadow_left_space, 1641 ws->shadow_top_space, 1642 d.width - ws->shadow_left_space - 1643 ws->shadow_right_space, 1644 d.height - ws->shadow_top_space - 1645 ws->shadow_bottom_space); 1646 1647 tmp = XRenderCreatePicture(xdisplay, GDK_PIXMAP_XID(pixmap), 1648 format, 0, NULL); 1649 1650 /* first pass */ 1651 params[0] = (n_params - 2) << 16; 1652 params[1] = 1 << 16; 1653 1654 set_picture_transform(xdisplay, dst, ws->shadow_offset_x, 0); 1655 XRenderSetPictureFilter(xdisplay, dst, filter, params, n_params); 1656 XRenderComposite(xdisplay, 1657 PictOpSrc, 1658 src, dst, tmp, 0, 0, 0, 0, 0, 0, d.width, d.height); 1659 1660 /* second pass */ 1661 params[0] = 1 << 16; 1662 params[1] = (n_params - 2) << 16; 1663 1664 set_picture_transform(xdisplay, tmp, 0, ws->shadow_offset_y); 1665 XRenderSetPictureFilter(xdisplay, tmp, filter, params, n_params); 1666 XRenderComposite(xdisplay, 1667 PictOpSrc, 1668 src, tmp, dst, 0, 0, 0, 0, 0, 0, d.width, d.height); 1669 1670 XRenderFreePicture(xdisplay, tmp); 1671 XRenderFreePicture(xdisplay, dst); 1672 XRenderFreePicture(xdisplay, src); 1673 1674 g_object_unref (G_OBJECT (pixmap)); 1675 1676 g_free(params); 1677 1678 ws->shadow_pixmap = d.pixmap; 1679 #endif 1680 return 1; 1681 } 1682 #endif /* ************************ */ 1683 static void titlebar_font_changed(window_settings * ws) 1684 { 1685 #if 0 1686 PangoFontMetrics *metrics; 1687 PangoLanguage *lang; 1688 1689 pango_context_set_font_description(ws->pango_context, ws->font_desc); 1690 lang = pango_context_get_language(ws->pango_context); 1691 metrics = 1692 pango_context_get_metrics(ws->pango_context, ws->font_desc, lang); 1693 1694 ws->text_height = PANGO_PIXELS(pango_font_metrics_get_ascent(metrics) + 1695 pango_font_metrics_get_descent(metrics)); 1696 #endif 1697 ws->titlebar_height = ws->text_height; 1698 if (ws->titlebar_height < ws->min_titlebar_height) 1699 ws->titlebar_height = ws->min_titlebar_height; 1700 1701 // pango_font_metrics_unref(metrics); 1702 1703 } 1704 1705 static void load_buttons_image(window_settings * ws, gint y) 1706 { 1707 gchar *file; 1708 int x, pix_width, pix_height, rel_button; 1709 1710 rel_button = get_b_offset(y); 1711 1712 1713 1714 if (ws->ButtonArray[y]) 1715 g_object_unref(ws->ButtonArray[y]); 1716 file = make_filename("buttons", b_types[y], "png"); 1717 if (!file || !(ws->ButtonArray[y] = gdk_pixbuf_new_from_file(file, NULL))) 1718 ws->ButtonArray[y] = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 16 * S_COUNT, 16); // create a blank pixbuf 1719 g_free(file); 1720 1721 pix_width = gdk_pixbuf_get_width(ws->ButtonArray[y]) / S_COUNT; 1722 pix_height = gdk_pixbuf_get_height(ws->ButtonArray[y]); 1723 ws->c_icon_size[rel_button].w = pix_width; 1724 ws->c_icon_size[rel_button].h = pix_height; 1725 for (x = 0; x < S_COUNT; x++) 1726 { 1727 if (ws->ButtonPix[x + y * S_COUNT]) 1728 g_object_unref(ws->ButtonPix[x + y * S_COUNT]); 1729 1730 ws->ButtonPix[x + y * S_COUNT] = 1731 gdk_pixbuf_new_subpixbuf(ws->ButtonArray[y], x * pix_width, 0, 1732 pix_width, pix_height); 1733 } 1734 } 1735 static void load_buttons_glow_images(window_settings * ws) 1736 { 1737 gchar *file1 = NULL; 1738 gchar *file2 = NULL; 1739 int x, pix_width, pix_height; 1740 int pix_width2, pix_height2; 1741 gboolean success1 = FALSE; 1742 gboolean success2 = FALSE; 1743 1744 if (ws->use_button_glow) 1745 { 1746 if (ws->ButtonGlowArray) 1747 g_object_unref(ws->ButtonGlowArray); 1748 file1 = make_filename("buttons", "glow", "png"); 1749 if (file1 && 1750 (ws->ButtonGlowArray = gdk_pixbuf_new_from_file(file1, NULL))) 1751 success1 = TRUE; 1752 } 1753 if (ws->use_button_inactive_glow) 1754 { 1755 if (ws->ButtonInactiveGlowArray) 1756 g_object_unref(ws->ButtonInactiveGlowArray); 1757 file2 = make_filename("buttons", "inactive_glow", "png"); 1758 if (file2 && 1759 (ws->ButtonInactiveGlowArray = 1760 gdk_pixbuf_new_from_file(file2, NULL))) 1761 success2 = TRUE; 1762 } 1763 if (success1 && success2) 1764 { 1765 pix_width = gdk_pixbuf_get_width(ws->ButtonGlowArray) / B_COUNT; 1766 pix_height = gdk_pixbuf_get_height(ws->ButtonGlowArray); 1767 pix_width2 = 1768 gdk_pixbuf_get_width(ws->ButtonInactiveGlowArray) / B_COUNT; 1769 pix_height2 = gdk_pixbuf_get_height(ws->ButtonInactiveGlowArray); 1770 1771 if (pix_width != pix_width2 || pix_height != pix_height2) 1772 { 1773 g_warning 1774 ("Choose same size glow images for active and inactive windows." 1775 "\nInactive glow image is scaled for now."); 1776 // Scale the inactive one 1777 GdkPixbuf *tmp_pixbuf = 1778 gdk_pixbuf_new(gdk_pixbuf_get_colorspace 1779 (ws->ButtonGlowArray), 1780 TRUE, 1781 gdk_pixbuf_get_bits_per_sample(ws-> 1782 ButtonGlowArray), 1783 pix_width * B_COUNT, 1784 pix_height); 1785 1786 gdk_pixbuf_scale(ws->ButtonInactiveGlowArray, tmp_pixbuf, 1787 0, 0, 1788 pix_width * B_COUNT, pix_height, 1789 0, 0, 1790 pix_width / (double)pix_width2, 1791 pix_height / (double)pix_height2, 1792 GDK_INTERP_BILINEAR); 1793 g_object_unref(ws->ButtonInactiveGlowArray); 1794 ws->ButtonInactiveGlowArray = tmp_pixbuf; 1795 } 1796 } 1797 else 1798 { 1799 pix_width = 16; 1800 pix_height = 16; 1801 if (success1) 1802 { 1803 pix_width = gdk_pixbuf_get_width(ws->ButtonGlowArray) / B_COUNT; 1804 pix_height = gdk_pixbuf_get_height(ws->ButtonGlowArray); 1805 } 1806 else if (success2) 1807 { 1808 pix_width = 1809 gdk_pixbuf_get_width(ws->ButtonInactiveGlowArray) / 1810 B_COUNT; 1811 pix_height = gdk_pixbuf_get_height(ws->ButtonInactiveGlowArray); 1812 } 1813 if (!success1 && ws->use_button_glow) 1814 ws->ButtonGlowArray = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, pix_width * B_COUNT, pix_height); // create a blank pixbuf 1815 if (!success2 && ws->use_button_inactive_glow) 1816 ws->ButtonInactiveGlowArray = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, pix_width * B_COUNT, pix_height); // create a blank pixbuf 1817 } 1818 ws->c_glow_size.w = pix_width; 1819 ws->c_glow_size.h = pix_height; 1820 1821 if (ws->use_button_glow) 1822 { 1823 g_free(file1); 1824 for (x = 0; x < B_COUNT; x++) 1825 { 1826 if (ws->ButtonGlowPix[x]) 1827 g_object_unref(ws->ButtonGlowPix[x]); 1828 ws->ButtonGlowPix[x] = 1829 gdk_pixbuf_new_subpixbuf(ws->ButtonGlowArray, 1830 x * pix_width, 0, pix_width, 1831 pix_height); 1832 } 1833 } 1834 if (ws->use_button_inactive_glow) 1835 { 1836 g_free(file2); 1837 for (x = 0; x < B_COUNT; x++) 1838 { 1839 if (ws->ButtonInactiveGlowPix[x]) 1840 g_object_unref(ws->ButtonInactiveGlowPix[x]); 1841 ws->ButtonInactiveGlowPix[x] = 1842 gdk_pixbuf_new_subpixbuf(ws->ButtonInactiveGlowArray, 1843 x * pix_width, 0, pix_width, 1844 pix_height); 1845 } 1846 } 1847 } 1848 void load_button_image_setting(window_settings * ws) 1849 { 1850 gint i; 1851 1852 for (i = 0; i < B_COUNT; i++) 1853 load_buttons_image(ws, i); 1854 1855 // load active and inactive glow image 1856 if (ws->use_button_glow || ws->use_button_inactive_glow) 1857 load_buttons_glow_images(ws); 1858 } 1859 static void load_settings(window_settings * ws) 1860 { 1861 gchar *engine = NULL; 1862 1863 gchar *path = 1864 g_strjoin("/", g_get_home_dir(), ".emerald/settings.ini", NULL); 1865 GKeyFile *f = g_key_file_new(); 1866 1867 // copy_from_defaults_if_needed(); 1868 1869 //settings 1870 g_key_file_load_from_file(f, path, 0, NULL); 1871 g_free(path); 1872 load_int_setting(f, &ws->double_click_action, "double_click_action", 1873 "titlebars"); 1874 load_int_setting(f, &ws->button_hover_cursor, "hover_cursor", "buttons"); 1875 load_bool_setting(f, &ws->use_decoration_cropping, 1876 "use_decoration_cropping", "decorations"); 1877 load_bool_setting(f, &ws->use_button_fade, "use_button_fade", "buttons"); 1878 gint button_fade_step_duration = ws->button_fade_step_duration; 1879 1880 load_int_setting(f, &button_fade_step_duration, 1881 "button_fade_step_duration", "buttons"); 1882 if (button_fade_step_duration > 0) 1883 ws->button_fade_step_duration = button_fade_step_duration; 1884 gint button_fade_total_duration = 250; 1885 1886 load_int_setting(f, &button_fade_total_duration, 1887 "button_fade_total_duration", "buttons"); 1888 if (button_fade_total_duration > 0) 1889 ws->button_fade_num_steps = 1890 button_fade_total_duration / ws->button_fade_step_duration; 1891 if (ws->button_fade_num_steps == 0) 1892 ws->button_fade_num_steps = 1; 1893 gboolean use_button_fade_pulse = FALSE; 1894 1895 load_bool_setting(f, &use_button_fade_pulse, "use_button_fade_pulse", 1896 "buttons"); 1897 1898 ws->button_fade_pulse_wait_steps = 0; 1899 if (use_button_fade_pulse) 1900 { 1901 gint button_fade_pulse_min_opacity = 0; 1902 1903 load_int_setting(f, &button_fade_pulse_min_opacity, 1904 "button_fade_pulse_min_opacity", "buttons"); 1905 ws->button_fade_pulse_len_steps = 1906 ws->button_fade_num_steps * (100 - 1907 button_fade_pulse_min_opacity) / 1908 100; 1909 gint button_fade_pulse_wait_duration = 0; 1910 1911 load_int_setting(f, &button_fade_pulse_wait_duration, 1912 "button_fade_pulse_wait_duration", "buttons"); 1913 if (button_fade_pulse_wait_duration > 0) 1914 ws->button_fade_pulse_wait_steps = 1915 button_fade_pulse_wait_duration / 1916 ws->button_fade_step_duration; 1917 } 1918 else 1919 ws->button_fade_pulse_len_steps = 0; 1920 1921 // load_bool_setting(f, &enable_tooltips, "enable_tooltips", "buttons"); 1922 load_int_setting(f, &ws->blur_type, 1923 "blur_type", "decorations"); 1924 1925 //theme 1926 path = g_strjoin("/", g_get_home_dir(), ".emerald/theme/theme.ini", NULL); 1927 g_key_file_load_from_file(f, path, 0, NULL); 1928 g_free(path); 1929 load_string_setting(f, &engine, "engine", "engine"); 1930 1931 if (!load_engine(engine, ws)) 1932 { 1933 if (engine) 1934 g_free(engine); 1935 engine = g_strdup("legacy"); 1936 load_engine(engine, ws); 1937 } 1938 LFACSS(text, titlebar); 1939 LFACSS(text_halo, titlebar); 1940 LFACSS(button, buttons); 1941 LFACSS(button_halo, buttons); 1942 load_engine_settings(f, ws); 1943 load_font_setting(f, &ws->font_desc, "titlebar_font", "titlebar"); 1944 load_bool_setting(f, &ws->use_pixmap_buttons, "use_pixmap_buttons", 1945 "buttons"); 1946 load_bool_setting(f, &ws->use_button_glow, "use_button_glow", "buttons"); 1947 load_bool_setting(f, &ws->use_button_inactive_glow, 1948 "use_button_inactive_glow", "buttons"); 1949 1950 if (ws->use_pixmap_buttons) 1951 load_button_image_setting(ws); 1952 load_shadow_color_setting(f, ws->shadow_color, "shadow_color", "shadow"); 1953 load_int_setting(f, &ws->shadow_offset_x, "shadow_offset_x", "shadow"); 1954 load_int_setting(f, &ws->shadow_offset_y, "shadow_offset_y", "shadow"); 1955 load_float_setting(f, &ws->shadow_radius, "shadow_radius", "shadow"); 1956 load_float_setting(f, &ws->shadow_opacity, "shadow_opacity", "shadow"); 1957 load_string_setting(f, &ws->tobj_layout, "title_object_layout", 1958 "titlebar"); 1959 load_int_setting(f, &ws->button_offset, "vertical_offset", "buttons"); 1960 load_int_setting(f, &ws->button_hoffset, "horizontal_offset", "buttons"); 1961 load_int_setting(f, &ws->win_extents.top, "top", "borders"); 1962 load_int_setting(f, &ws->win_extents.left, "left", "borders"); 1963 load_int_setting(f, &ws->win_extents.right, "right", "borders"); 1964 load_int_setting(f, &ws->win_extents.bottom, "bottom", "borders"); 1965 load_int_setting(f, &ws->min_titlebar_height, "min_titlebar_height", 1966 "titlebar"); 1967 g_key_file_free(f); 1968 } 1969 void update_settings(window_settings * ws) 1970 { 1971 #if 0 1972 //assumes ws is fully allocated 1973 1974 GdkDisplay *gdkdisplay; 1975 1976 // Display *xdisplay; 1977 GdkScreen *gdkscreen; 1978 WnckScreen *screen = wnck_screen_get_default(); 1979 GList *windows; 1980 #endif 1981 1982 load_settings(ws); 1983 1984 #if 0 1985 gdkdisplay = gdk_display_get_default(); 1986 // xdisplay = gdk_x11_display_get_xdisplay (gdkdisplay); 1987 gdkscreen = gdk_display_get_default_screen(gdkdisplay); 1988 #endif 1989 1990 titlebar_font_changed(ws); 1991 update_window_extents(ws); 1992 update_shadow(ws->fs_act); 1993 #if 0 1994 update_default_decorations(gdkscreen, ws->fs_act, ws->fs_inact); 1995 1996 windows = wnck_screen_get_windows(screen); 1997 while (windows) 1998 { 1999 decor_t *d = g_object_get_data(G_OBJECT(windows->data), "decor"); 2000 2001 if (d->decorated) 2002 { 2003 d->width = d->height = 0; 2004 update_window_decoration_size(WNCK_WINDOW(windows->data)); 2005 update_event_windows(WNCK_WINDOW(windows->data)); 2006 } 2007 windows = windows->next; 2008 } 2009 #endif 2010 } 2011 2012 window_settings *create_settings() 2013 { 2014 gchar *engine = NULL; 2015 int i; 2016 2017 frame_settings *pfs; 2018 window_settings *ws; 2019 2020 ws = malloc(sizeof(window_settings)); 2021 bzero(ws, sizeof(window_settings)); 2022 #if 0 2023 global_ws = ws; 2024 setlocale(LC_ALL, ""); 2025 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); 2026 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); 2027 textdomain(GETTEXT_PACKAGE); 2028 #endif 2029 2030 ws->win_extents.left = 6; 2031 ws->win_extents.top = 4; 2032 ws->win_extents.right = 6; 2033 ws->win_extents.bottom = 6; 2034 ws->corner_radius = 5; 2035 ws->shadow_radius = 15; 2036 ws->shadow_opacity = .8; 2037 ws->min_titlebar_height = 17; 2038 ws->double_click_action = DOUBLE_CLICK_SHADE; 2039 ws->button_hover_cursor = 1; 2040 ws->button_offset = 1; 2041 ws->button_hoffset = 1; 2042 ws->button_fade_step_duration = 50; 2043 ws->button_fade_num_steps = 5; 2044 ws->blur_type = BLUR_TYPE_NONE; 2045 2046 ws->tobj_layout = g_strdup("IT::HNXC"); // DEFAULT TITLE OBJECT LAYOUT, does not use any odd buttons 2047 //ws->tobj_layout=g_strdup("CNX:IT:HM"); 2048 2049 pfs = malloc(sizeof(frame_settings)); 2050 bzero(pfs, sizeof(frame_settings)); 2051 pfs->ws = ws; 2052 ACOLOR(text, 1.0, 1.0, 1.0, 1.0); 2053 ACOLOR(text_halo, 0.0, 0.0, 0.0, 0.2); 2054 ACOLOR(button, 1.0, 1.0, 1.0, 0.8); 2055 ACOLOR(button_halo, 0.0, 0.0, 0.0, 0.2); 2056 ws->fs_act = pfs; 2057 2058 pfs = malloc(sizeof(frame_settings)); 2059 bzero(pfs, sizeof(frame_settings)); 2060 pfs->ws = ws; 2061 ACOLOR(text, 0.8, 0.8, 0.8, 0.8); 2062 ACOLOR(text_halo, 0.0, 0.0, 0.0, 0.2); 2063 ACOLOR(button, 0.8, 0.8, 0.8, 0.8); 2064 ACOLOR(button_halo, 0.0, 0.0, 0.0, 0.2); 2065 ws->fs_inact = pfs; 2066 2067 ws->round_top_left = TRUE; 2068 ws->round_top_right = TRUE; 2069 ws->round_bottom_left = TRUE; 2070 ws->round_bottom_right = TRUE; 2071 2072 engine = g_strdup("legacy"); 2073 load_engine(engine, ws); // assumed to always return TRUE 2074 2075 // program_name = argv[0]; 2076 2077 //ws->ButtonBase = NULL; 2078 for (i = 0; i < (S_COUNT * B_COUNT); i++) 2079 { 2080 ws->ButtonPix[i] = NULL; 2081 } 2082 return ws; 2083 } 2084