File indexing completed on 2024-03-24 05:49:53
0001 /***************************************************************************** 0002 * Copyright 2003 - 2010 Craig Drummond <craig.p.drummond@gmail.com> * 0003 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU Lesser General Public License as * 0007 * published by the Free Software Foundation; either version 2.1 of the * 0008 * License, or (at your option) version 3, or any later version accepted * 0009 * by the membership of KDE e.V. (or its successor approved by the * 0010 * membership of KDE e.V.), which shall act as a proxy defined in * 0011 * Section 6 of version 3 of the license. * 0012 * * 0013 * This program is distributed in the hope that it will be useful, * 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0016 * Lesser General Public License for more details. * 0017 * * 0018 * You should have received a copy of the GNU Lesser General Public * 0019 * License along with this library. If not, * 0020 * see <http://www.gnu.org/licenses/>. * 0021 *****************************************************************************/ 0022 0023 #include "config.h" 0024 0025 #include <qtcurve-utils/color.h> 0026 #include <qtcurve-utils/strs.h> 0027 #include <qtcurve-utils/gtkprops.h> 0028 #include <qtcurve-utils/x11base.h> 0029 #include <qtcurve-cairo/draw.h> 0030 0031 #include <gmodule.h> 0032 #include <gdk/gdk.h> 0033 #include <gdk/gdkx.h> 0034 #include <cairo.h> 0035 #include "compatability.h" 0036 #include <common/config_file.h> 0037 0038 #define MO_ARROW(MENU, COL) \ 0039 (!MENU && MO_NONE != opts.coloredMouseOver && \ 0040 GTK_STATE_PRELIGHT == state ? \ 0041 &qtcPalette.mouseover[ARROW_MO_SHADE] : (COL)) 0042 0043 #include "qt_settings.h" 0044 #include "animation.h" 0045 #include "menu.h" 0046 #include "tab.h" 0047 #include "widgetmap.h" 0048 #include "window.h" 0049 #include "entry.h" 0050 #include "treeview.h" 0051 #include "combobox.h" 0052 #include "scrolledwindow.h" 0053 #include "scrollbar.h" 0054 #include "wmmove.h" 0055 #include "helpers.h" 0056 #include "drawing.h" 0057 #include "pixcache.h" 0058 #include "shadowhelper.h" 0059 #include "config.h" 0060 0061 namespace QtCurve { 0062 0063 static GType style_type = 0; 0064 static GType rc_style_type = 0; 0065 0066 struct StyleClass { 0067 GtkStyleClass parent_class; 0068 }; 0069 0070 struct Style { 0071 GtkStyle parent_instance; 0072 GdkColor *button_text[2]; 0073 GdkColor *menutext[2]; 0074 }; 0075 0076 struct RcStyleClass { 0077 GtkRcStyleClass parent_class; 0078 }; 0079 0080 struct RcStyle { 0081 GtkRcStyle parent_instance; 0082 }; 0083 0084 template<typename T> 0085 static inline bool 0086 isRcStyle(T *object) 0087 { 0088 return G_TYPE_CHECK_INSTANCE_TYPE(object, rc_style_type); 0089 } 0090 0091 static GtkStyleClass *parent_class = nullptr; 0092 0093 #ifdef INCREASE_SB_SLIDER 0094 typedef struct { 0095 GtkStyle *style; 0096 #if GTK_CHECK_VERSION(2, 90, 0) 0097 cairo_t *cr; 0098 #else 0099 GdkWindow *window; 0100 #endif 0101 GtkStateType state; 0102 GtkShadowType shadow; 0103 GtkWidget *widget; 0104 const char *detail; 0105 int x; 0106 int y; 0107 int width; 0108 int height; 0109 GtkOrientation orientation; 0110 } QtCSlider; 0111 0112 static QtCSlider lastSlider; 0113 #endif 0114 0115 template<typename Widget> 0116 static inline bool 0117 widgetIsType(Widget *widget, const char *name) 0118 { 0119 return oneOf(gTypeName(widget), name); 0120 } 0121 0122 static void gtkDrawBox(GtkStyle *style, GdkWindow *window, GtkStateType state, 0123 GtkShadowType shadow, GdkRectangle *area, 0124 GtkWidget *widget, const char *detail, int x, int y, 0125 int width, int height); 0126 0127 static void gtkDrawSlider(GtkStyle *style, GdkWindow *window, 0128 GtkStateType state, GtkShadowType shadow, 0129 GdkRectangle *area, GtkWidget *widget, 0130 const char *detail, int x, int y, int width, 0131 int height, GtkOrientation orientation); 0132 0133 static void 0134 gtkLogHandler(const char*, GLogLevelFlags, const char*, void*) 0135 { 0136 } 0137 0138 static void 0139 gtkDrawFlatBox(GtkStyle *style, GdkWindow *window, GtkStateType state, 0140 GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, 0141 const char *_detail, int x, int y, int width, int height) 0142 { 0143 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 0144 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 0145 const char *detail = _detail ? _detail : ""; 0146 cairo_t *cr = Cairo::gdkCreateClip(window, area); 0147 0148 bool isMenuOrToolTipWindow = 0149 (widget && GTK_IS_WINDOW(widget) && 0150 ((gtk_widget_get_name(widget) && 0151 strcmp(gtk_widget_get_name(widget), "gtk-tooltip") == 0) || 0152 isMenuWindow(widget))); 0153 0154 if (qtSettings.debug == DEBUG_ALL) { 0155 printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %s ", __FUNCTION__, 0156 state, shadow, x, y, width, height, _detail); 0157 debugDisplayWidget(widget, 10); 0158 } 0159 0160 sanitizeSize(window, &width, &height); 0161 0162 if (!opts.gtkButtonOrder && opts.reorderGtkButtons && 0163 GTK_IS_WINDOW(widget) && oneOf(detail, "base")) { 0164 GtkWidget *topLevel = gtk_widget_get_toplevel(widget); 0165 GtkWidgetProps topProps(topLevel); 0166 0167 if (topLevel && GTK_IS_DIALOG(topLevel) && 0168 !topProps->buttonOrderHacked) { 0169 // gtk_dialog_set_alternative_button_order will cause errors to be 0170 // logged, but dont want these so register our own error handler, 0171 // and then unregister afterwards... 0172 unsigned id = g_log_set_handler("Gtk", G_LOG_LEVEL_CRITICAL, 0173 gtkLogHandler, nullptr); 0174 topProps->buttonOrderHacked = true; 0175 0176 gtk_dialog_set_alternative_button_order( 0177 GTK_DIALOG(topLevel), GTK_RESPONSE_HELP, GTK_RESPONSE_OK, 0178 GTK_RESPONSE_YES, GTK_RESPONSE_ACCEPT, GTK_RESPONSE_APPLY, 0179 GTK_RESPONSE_REJECT, GTK_RESPONSE_CLOSE, GTK_RESPONSE_NO, 0180 GTK_RESPONSE_CANCEL, -1); 0181 g_log_remove_handler("Gtk", id); 0182 } 0183 } 0184 0185 if (opts.windowDrag > WM_DRAG_MENU_AND_TOOLBAR && 0186 oneOf(detail, "base", "eventbox", "viewportbin")) { 0187 WMMove::setup(widget); 0188 } 0189 0190 if (widget && ((100!=opts.bgndOpacity && GTK_IS_WINDOW(widget)) || 0191 (100!=opts.dlgOpacity && GTK_IS_DIALOG(widget))) && 0192 !isFixedWidget(widget) && isRgbaWidget(widget)) { 0193 enableBlurBehind(widget, true); 0194 } 0195 0196 if ((opts.menubarHiding || opts.statusbarHiding || BLEND_TITLEBAR || 0197 opts.windowBorder & WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR) && 0198 widget && GTK_IS_WINDOW(widget) && !isFixedWidget(widget) && 0199 !isGimpDockable(widget) && !isMenuOrToolTipWindow) { 0200 if (Window::setup(widget, GTK_IS_DIALOG(widget) ? opts.dlgOpacity : 0201 opts.bgndOpacity)) { 0202 GtkWidget *menuBar = Window::getMenuBar(widget, 0); 0203 GtkWidget *statusBar = (opts.statusbarHiding ? 0204 Window::getStatusBar(widget, 0) : nullptr); 0205 0206 if (menuBar) { 0207 bool hiddenMenubar = 0208 (opts.menubarHiding ? 0209 qtcMenuBarHidden(qtSettings.appName) : false); 0210 QtcRect alloc = Widget::getAllocation(menuBar); 0211 0212 if (hiddenMenubar) 0213 gtk_widget_hide(menuBar); 0214 0215 if (BLEND_TITLEBAR || opts.menubarHiding & HIDE_KWIN || 0216 opts.windowBorder & 0217 WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR) { 0218 Menu::emitSize(menuBar, hiddenMenubar ? 0 : alloc.height); 0219 } 0220 if (opts.menubarHiding&HIDE_KWIN) { 0221 Window::menuBarDBus(widget, 0222 hiddenMenubar ? 0 : alloc.height); 0223 } 0224 } 0225 0226 #if GTK_CHECK_VERSION(2, 90, 0) 0227 if(gtk_window_get_has_resize_grip(GTK_WINDOW(widget))) 0228 gtk_window_set_has_resize_grip(GTK_WINDOW(widget), false); 0229 #else 0230 if(statusBar && gtk_statusbar_get_has_resize_grip(GTK_STATUSBAR(statusBar))) 0231 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(statusBar), false); 0232 #endif 0233 0234 if (opts.statusbarHiding && statusBar) { 0235 bool hiddenStatusBar = qtcStatusBarHidden(qtSettings.appName); 0236 if (hiddenStatusBar) { 0237 gtk_widget_hide(statusBar); 0238 } 0239 if (opts.statusbarHiding & HIDE_KWIN) { 0240 Window::statusBarDBus(widget, !hiddenStatusBar); 0241 Window::setStatusBarProp(widget); 0242 } 0243 } 0244 } 0245 } 0246 0247 if (widget && qtcIsCustomBgnd(opts) && oneOf(detail, "base", "eventbox")) { 0248 Scrollbar::setup(widget); 0249 } 0250 0251 if (qtcIsCustomBgnd(opts) && oneOf(detail, "viewportbin")) { 0252 GtkRcStyle *st = widget ? gtk_widget_get_modifier_style(widget) : nullptr; 0253 // if the app hasn't modified bg, draw background gradient 0254 if (st && !(st->color_flags[state]>K_RC_BG)) { 0255 drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, 0256 x, y, width, height); 0257 Scrollbar::setup(widget); 0258 } else { 0259 parent_class->draw_flat_box(style, window, state, shadow, area, 0260 widget, _detail, x, y, width, height); 0261 } 0262 } else if (qtcIsCustomBgnd(opts) && widget && GTK_IS_WINDOW(widget) && 0263 !isMenuOrToolTipWindow && 0264 drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, 0265 x, y, width, height)) { 0266 Window::setup(widget, GTK_IS_DIALOG(widget) ? opts.dlgOpacity : 0267 opts.bgndOpacity); 0268 } else if (widget && GTK_IS_TREE_VIEW(widget)) { 0269 bool isCombo = isComboBoxPopupWindow(widget, 0); 0270 GtkTreeView *treeView = GTK_TREE_VIEW(widget); 0271 bool checkRules = (opts.forceAlternateLvCols || 0272 gtk_tree_view_get_rules_hint(treeView)); 0273 bool isEven = checkRules && strstr(detail, "cell_even"); 0274 0275 if (qtSettings.app == GTK_APP_JAVA_SWT) 0276 area = nullptr; 0277 0278 /* SWT seems to draw a 'cell_even', and then 'cell_odd' at the same position. This causes the view painting 0279 * to be messed up. Try and hack around this... */ 0280 if (qtSettings.app == GTK_APP_JAVA_SWT && state == GTK_STATE_SELECTED && 0281 checkRules && !isCombo && widget) { 0282 static GtkWidget *lastWidget = nullptr; 0283 static int lastEven = -1; 0284 0285 if (strstr(detail, "cell_even")) { 0286 lastWidget = widget; 0287 lastEven = y; 0288 } else if (strstr(detail, "cell_odd")) { 0289 if (lastWidget == widget) { 0290 if (y == lastEven) { 0291 isEven = true; 0292 } 0293 } 0294 lastWidget = nullptr; 0295 lastEven = -1; 0296 } 0297 } 0298 0299 if (!isCombo || state != GTK_STATE_SELECTED) { 0300 Cairo::rect(cr, (QtcRect*)area, x, y, width, height, 0301 getCellCol(haveAlternateListViewCol() && 0302 checkRules && !isEven ? 0303 &qtSettings.colors[PAL_ACTIVE][COLOR_LV] : 0304 &style->base[GTK_STATE_NORMAL], detail)); 0305 } 0306 if (isCombo) { 0307 if (state == GTK_STATE_SELECTED) { 0308 Cairo::rect(cr, (QtcRect*)area, x, y, width, height, 0309 &style->base[widget && 0310 gtk_widget_has_focus(widget) ? 0311 GTK_STATE_SELECTED : 0312 GTK_STATE_ACTIVE]); 0313 } 0314 } else { 0315 double alpha = 1.0; 0316 int selX = x; 0317 int selW = width; 0318 int factor = 0; 0319 bool forceCellStart = false; 0320 bool forceCellEnd = false; 0321 0322 if (!isFixedWidget(widget)) { 0323 GtkTreePath *path = nullptr; 0324 GtkTreeViewColumn *column = nullptr; 0325 GtkTreeViewColumn *expanderColumn = 0326 gtk_tree_view_get_expander_column(treeView); 0327 int levelIndent = 0; 0328 int expanderSize = 0; 0329 int depth = 0; 0330 0331 TreeView::getCell(treeView, &path, &column, 0332 x, y, width, height); 0333 TreeView::setup(widget); 0334 if (path && TreeView::isCellHovered(widget, path, column)) { 0335 if (state == GTK_STATE_SELECTED) { 0336 factor = 10; 0337 } else { 0338 alpha = 0.2; 0339 } 0340 } 0341 0342 if (column == expanderColumn) { 0343 gtk_widget_style_get(widget, 0344 "expander-size", &expanderSize, nullptr); 0345 levelIndent = gtk_tree_view_get_level_indentation(treeView), 0346 depth = path ? (int)gtk_tree_path_get_depth(path) : 0; 0347 0348 forceCellStart = true; 0349 if (opts.lvLines) { 0350 drawTreeViewLines(cr, &style->mid[GTK_STATE_ACTIVE], 0351 x, y, height, depth, levelIndent, 0352 expanderSize, treeView, path); 0353 } 0354 } else if (column && 0355 TreeView::cellIsLeftOfExpanderColumn(treeView, 0356 column)) { 0357 forceCellEnd = true; 0358 } 0359 0360 if ((state == GTK_STATE_SELECTED || alpha < 1.0) && 0361 column == expanderColumn) { 0362 int offset = (3 + expanderSize * depth + 0363 (4 + levelIndent) * (depth - 1)); 0364 selX += offset; 0365 selW -= offset; 0366 } 0367 0368 if(path) 0369 gtk_tree_path_free(path); 0370 } 0371 0372 if (state == GTK_STATE_SELECTED || alpha < 1.0) { 0373 auto round = ROUNDED_NONE; 0374 if (opts.round != ROUND_NONE) { 0375 if (forceCellStart && forceCellEnd) { 0376 round = ROUNDED_ALL; 0377 } else if (forceCellStart || strstr(detail, "_start")) { 0378 round = ROUNDED_LEFT; 0379 } else if (forceCellEnd || strstr(detail, "_end")) { 0380 round = ROUNDED_RIGHT; 0381 } else if (!strstr(detail, "_middle")) { 0382 round = ROUNDED_ALL; 0383 } 0384 } 0385 drawSelection(cr, style, state, (QtcRect*)area, widget, selX, 0386 y, selW, height, round, true, alpha, factor); 0387 } 0388 } 0389 } else if (oneOf(detail, "checkbutton")) { 0390 if (state == GTK_STATE_PRELIGHT && opts.crHighlight && 0391 width > opts.crSize * 2) { 0392 GdkColor col=shadeColor(&style->bg[state], TO_FACTOR(opts.crHighlight)); 0393 drawSelectionGradient(cr, (QtcRect*)area, x, y, width, height, 0394 ROUNDED_ALL, false, 1.0, &col, true); 0395 } 0396 } else if (oneOf(detail, "expander")) { 0397 if (state == GTK_STATE_PRELIGHT && opts.expanderHighlight) { 0398 GdkColor col = shadeColor(&style->bg[state], 0399 TO_FACTOR(opts.expanderHighlight)); 0400 drawSelectionGradient(cr, (QtcRect*)area, x, y, width, height, 0401 ROUNDED_ALL, false, 1.0, &col, true); 0402 } 0403 } else if (oneOf(detail, "tooltip")) { 0404 drawToolTip(cr, widget, (QtcRect*)area, x, y, width, height); 0405 } else if (oneOf(detail, "icon_view_item")) { 0406 drawSelection(cr, style, state, (QtcRect*)area, widget, x, y, 0407 width, height, ROUNDED_ALL, false, 1.0, 0); 0408 } else if (state != GTK_STATE_SELECTED && 0409 qtcIsCustomBgnd(opts) && oneOf(detail, "eventbox")) { 0410 drawWindowBgnd(cr, style, nullptr, window, widget, x, y, width, height); 0411 } else if (!(qtSettings.app == GTK_APP_JAVA && widget && 0412 GTK_IS_LABEL(widget))) { 0413 if (state != GTK_STATE_PRELIGHT || opts.crHighlight || 0414 noneOf(detail, "checkbutton")) { 0415 parent_class->draw_flat_box(style, window, state, shadow, area, 0416 widget, _detail, x, y, width, height); 0417 } 0418 0419 /* For SWT (e.g. eclipse) apps. For some reason these only seem to allow a ythickness of at max 2 - but 0420 for etching we need 3. So we fake this by drawing the 3rd lines here...*/ 0421 0422 /* 0423 if(DO_EFFECT && GTK_STATE_INSENSITIVE!=state && oneOf(detail, "entry_bg") && 0424 isSwtComboBoxEntry(widget) && gtk_widget_has_focus(widget)) 0425 { 0426 Cairo::hLine(cr, x, y, width, 0427 &qtcPalette.highlight[FRAME_DARK_SHADOW]); 0428 Cairo::hLine(cr, x, y + height - 1, width, 0429 &qtcPalette.highlight[0]); 0430 } 0431 */ 0432 } 0433 cairo_destroy(cr); 0434 } 0435 0436 static void 0437 gtkDrawHandle(GtkStyle *style, GdkWindow *window, GtkStateType state, 0438 GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, 0439 const char *_detail, int x, int y, int width, int height, 0440 GtkOrientation) 0441 { 0442 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 0443 QTC_RET_IF_FAIL(GDK_IS_WINDOW(window)); 0444 const char *detail = _detail ? _detail : ""; 0445 QtcRect *area = (QtcRect*)_area; 0446 bool paf = widgetIsType(widget, "PanelAppletFrame"); 0447 cairo_t *cr = Cairo::gdkCreateClip(window, area); 0448 0449 if (qtSettings.debug == DEBUG_ALL) { 0450 printf(DEBUG_PREFIX "%s %d %d %d %d %s ", __FUNCTION__, state, shadow, 0451 width, height, _detail); 0452 debugDisplayWidget(widget, 10); 0453 } 0454 0455 sanitizeSize(window, &width, &height); 0456 if (qtcIsFlatBgnd(opts.bgndAppearance) || 0457 !(widget && drawWindowBgnd(cr, style, area, window, widget, 0458 x, y, width, height))) { 0459 if (widget && opts.bgndImage.type != IMG_NONE) { 0460 drawWindowBgnd(cr, style, area, window, widget, 0461 x, y, width, height); 0462 } 0463 } 0464 0465 if (oneOf(detail, "paned") || oneOf(detail + 1, "paned")) { 0466 drawSplitter(cr, state, style, area, x, y, width, height); 0467 } else if ((oneOf(detail, "handlebox") && 0468 (qtSettings.app == GTK_APP_JAVA || 0469 (widget && GTK_IS_HANDLE_BOX(widget)))) || 0470 oneOf(detail, "dockitem") || paf) { 0471 /* Note: I'm not sure why the 'widget && GTK_IS_HANDLE_BOX(widget)' is in 0472 * the following 'if' - its been there for a while. But this breaks the 0473 * toolbar handles for Java Swing apps. I'm leaving it in for non Java 0474 * apps, as there must've been a reason for it.... */ 0475 if (widget && state != GTK_STATE_INSENSITIVE) { 0476 state = gtk_widget_get_state(widget); 0477 } 0478 if (paf) { 0479 /* The paf here is expected to be on the gnome panel */ 0480 if (height < width) { 0481 y++; 0482 } else { 0483 x++; 0484 } 0485 } else { 0486 gtkDrawBox(style, window, state, shadow, (GdkRectangle*)area, 0487 widget, "handlebox", x, y, width, height); 0488 } 0489 0490 switch (opts.handles) { 0491 case LINE_1DOT: 0492 Cairo::dot(cr, x, y, width, height, 0493 &qtcPalette.background[QTC_STD_BORDER]); 0494 break; 0495 case LINE_NONE: 0496 break; 0497 case LINE_DOTS: 0498 Cairo::dots(cr, x, y, width, height, height < width, 2, 5, 0499 area, 2, &qtcPalette.background[5], 0500 qtcPalette.background); 0501 break; 0502 case LINE_DASHES: 0503 if (height > width) { 0504 drawLines(cr, x + 3, y, 3, height, true, (height - 8) / 2, 0, 0505 qtcPalette.background, area, 5, opts.handles); 0506 } else { 0507 drawLines(cr, x, y + 3, width, 3, false, (width - 8) / 2, 0508 0, qtcPalette.background, area, 5, opts.handles); 0509 } 0510 break; 0511 case LINE_FLAT: 0512 drawLines(cr, x, y, width, height, height < width, 2, 4, 0513 qtcPalette.background, area, 4, opts.handles); 0514 break; 0515 default: 0516 drawLines(cr, x, y, width, height, height < width, 2, 4, 0517 qtcPalette.background, area, 3, opts.handles); 0518 } 0519 } 0520 cairo_destroy(cr); 0521 } 0522 0523 static void 0524 drawArrow(GdkWindow *window, const GdkColor *col, const QtcRect *area, 0525 GtkArrowType arrow_type, int x, int y, bool small, bool fill) 0526 { 0527 cairo_t *cr = gdk_cairo_create(window); 0528 Cairo::arrow(cr, col, area, arrow_type, x, y, small, fill, opts.vArrows); 0529 cairo_destroy(cr); 0530 } 0531 0532 static void 0533 gtkDrawArrow(GtkStyle *style, GdkWindow *window, GtkStateType state, 0534 GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, 0535 const char *_detail, GtkArrowType arrow_type, gboolean, 0536 int x, int y, int width, int height) 0537 { 0538 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 0539 const char *detail = _detail ? _detail : ""; 0540 if (qtSettings.debug == DEBUG_ALL) { 0541 printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %d %s ", __FUNCTION__, 0542 state, shadow, arrow_type, x, y, width, height, _detail); 0543 debugDisplayWidget(widget, 10); 0544 } 0545 QtcRect *area = (QtcRect*)_area; 0546 cairo_t *cr = gdk_cairo_create(window); 0547 0548 if (oneOf(detail, "arrow")) { 0549 bool onComboEntry = isOnComboEntry(widget, 0); 0550 0551 if (isOnComboBox(widget, 0) && !onComboEntry) { 0552 if (state == GTK_STATE_ACTIVE) 0553 state = GTK_STATE_PRELIGHT; 0554 const GdkColor *arrowColor = 0555 MO_ARROW(false, 0556 &qtSettings.colors[state == GTK_STATE_INSENSITIVE ? 0557 PAL_DISABLED : PAL_ACTIVE] 0558 [COLOR_BUTTON_TEXT]); 0559 x++; 0560 // NOTE: Dont do this for moz - as looks odd fir widgets in 0561 // HTML pages - arrow is shifted too much :-( 0562 if (!(opts.buttonEffect != EFFECT_NONE)) 0563 x += 2; 0564 if (opts.doubleGtkComboArrow) { 0565 int pad = opts.vArrows ? 0 : 1; 0566 Cairo::arrow(cr, arrowColor, area, GTK_ARROW_UP, x + width / 2, 0567 y + height / 2 - (LARGE_ARR_HEIGHT - pad), 0568 false, true, opts.vArrows); 0569 Cairo::arrow(cr, arrowColor, area, GTK_ARROW_DOWN, 0570 x + width / 2, 0571 y + height / 2 + (LARGE_ARR_HEIGHT - pad), 0572 false, true, opts.vArrows); 0573 } else { 0574 GtkWidget *parent = nullptr; 0575 if (!opts.gtkComboMenus && 0576 !((parent = gtk_widget_get_parent(widget)) && 0577 (parent = gtk_widget_get_parent(parent)) && 0578 !ComboBox::hasFrame(parent))) { 0579 x += 2; 0580 } 0581 Cairo::arrow(cr, arrowColor, area, GTK_ARROW_DOWN, 0582 x + width / 2, y + height / 2, false, true, 0583 opts.vArrows); 0584 } 0585 } else { 0586 bool combo = onComboEntry || isOnCombo(widget, 0); 0587 int origState = state; 0588 0589 if (combo && state == GTK_STATE_ACTIVE) 0590 state = GTK_STATE_PRELIGHT; 0591 0592 const GdkColor *col = 0593 (combo || isOnListViewHeader(widget, 0) || 0594 isOnButton(widget, 0, nullptr) ? 0595 &qtSettings.colors[state == GTK_STATE_INSENSITIVE ? 0596 PAL_DISABLED : 0597 PAL_ACTIVE][COLOR_BUTTON_TEXT] : 0598 &style->text[ARROW_STATE(state)]); 0599 if (onComboEntry && origState == GTK_STATE_ACTIVE && 0600 opts.unifyCombo) { 0601 x--; 0602 y--; 0603 } 0604 Cairo::arrow(cr, MO_ARROW(false, col), area, arrow_type, 0605 x + width / 2, y + height / 2, 0606 false, true, opts.vArrows); 0607 } 0608 } else { 0609 int isSpinButton = oneOf(detail, "spinbutton"); 0610 bool isMenuItem = oneOf(detail, "menuitem"); 0611 /* int a_width = LARGE_ARR_WIDTH; */ 0612 /* int a_height = LARGE_ARR_HEIGHT; */ 0613 bool sbar = isSbarDetail(detail); 0614 bool smallArrows = isSpinButton && !opts.unifySpin; 0615 int stepper = (sbar ? getStepper(widget, x, y, opts.sliderWidth, 0616 opts.sliderWidth) : STEPPER_NONE); 0617 0618 sanitizeSize(window, &width, &height); 0619 0620 if (isSpinButton) { 0621 /* if (GTK_ARROW_UP == arrow_type) */ 0622 /* y++; */ 0623 /* a_height = SMALL_ARR_HEIGHT; */ 0624 /* a_width = SMALL_ARR_WIDTH; */ 0625 } else if (oneOf(arrow_type, GTK_ARROW_LEFT, GTK_ARROW_RIGHT) || 0626 isMenuItem) { 0627 /* a_width = LARGE_ARR_HEIGHT; */ 0628 /* a_height = LARGE_ARR_WIDTH; */ 0629 if (isMozilla() && opts.vArrows /* && a_height */ && 0630 height < LARGE_ARR_WIDTH) { 0631 smallArrows = true; 0632 } 0633 } 0634 x += width / 2; 0635 y += height / 2; 0636 if (state == GTK_STATE_ACTIVE && ((sbar && !opts.flatSbarButtons) || 0637 (isSpinButton && !opts.unifySpin))) { 0638 x++; 0639 y++; 0640 } 0641 if (sbar) { 0642 switch (stepper) { 0643 case STEPPER_B: 0644 if (opts.flatSbarButtons || !opts.vArrows) { 0645 if (GTK_ARROW_RIGHT == arrow_type) { 0646 x--; 0647 } else { 0648 y--; 0649 } 0650 } 0651 break; 0652 case STEPPER_C: 0653 if (opts.flatSbarButtons || !opts.vArrows) { 0654 if (GTK_ARROW_LEFT == arrow_type) { 0655 x++; 0656 } else { 0657 y++; 0658 } 0659 } 0660 default: 0661 break; 0662 } 0663 } 0664 0665 if (isSpinButton && isFixedWidget(widget) && isFakeGtk()) { 0666 x--; 0667 } 0668 if (isSpinButton && !(opts.buttonEffect != EFFECT_NONE)) { 0669 y += arrow_type == GTK_ARROW_UP ? -1 : 1; 0670 } 0671 if (opts.unifySpin && isSpinButton && !opts.vArrows && 0672 arrow_type == GTK_ARROW_DOWN) { 0673 y--; 0674 } 0675 if (state == GTK_STATE_ACTIVE && (sbar || isSpinButton) && 0676 opts.coloredMouseOver == MO_GLOW) { 0677 state = GTK_STATE_PRELIGHT; 0678 } 0679 if (isMenuItem && arrow_type == GTK_ARROW_RIGHT && !isFakeGtk()) { 0680 x -= 2; 0681 } 0682 const GdkColor *col = 0683 (isSpinButton || sbar ? 0684 &qtSettings.colors[state == GTK_STATE_INSENSITIVE ? 0685 PAL_DISABLED : PAL_ACTIVE][COLOR_BUTTON_TEXT] : 0686 &style->text[isMenuItem && state == GTK_STATE_PRELIGHT ? 0687 GTK_STATE_SELECTED : ARROW_STATE(state)]); 0688 if (isMenuItem && state != GTK_STATE_PRELIGHT && opts.shadePopupMenu) { 0689 if (opts.shadeMenubars == SHADE_WINDOW_BORDER) { 0690 col = &qtSettings.colors[PAL_ACTIVE][COLOR_WINDOW_BORDER_TEXT]; 0691 } else if (opts.customMenuTextColor) { 0692 col = &opts.customMenuNormTextColor; 0693 } else if (oneOf(opts.shadeMenubars, SHADE_BLEND_SELECTED, 0694 SHADE_SELECTED) || 0695 (opts.shadeMenubars == SHADE_CUSTOM && 0696 TOO_DARK(qtcPalette.menubar[ORIGINAL_SHADE]))) { 0697 col = &style->text[GTK_STATE_SELECTED]; 0698 } 0699 } 0700 Cairo::arrow(cr, MO_ARROW(isMenuItem, col), area, arrow_type, x, y, 0701 smallArrows, true, opts.vArrows); 0702 } 0703 cairo_destroy(cr); 0704 } 0705 0706 static void 0707 drawBox(GtkStyle *style, GdkWindow *window, GtkStateType state, 0708 GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, 0709 const char *_detail, int x, int y, int width, int height, 0710 bool btnDown) 0711 { 0712 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 0713 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 0714 const char *detail = _detail ? _detail : ""; 0715 bool sbar = isSbarDetail(detail); 0716 bool pbar = oneOf(detail, "bar"); // && GTK_IS_PROGRESS_BAR(widget); 0717 bool qtcSlider = !pbar && oneOf(detail, "qtc-slider"); 0718 bool slider = qtcSlider || (!pbar && oneOf(detail, "slider")); 0719 bool hscale = !slider && oneOf(detail, "hscale"); 0720 bool vscale = !hscale && oneOf(detail, "vscale"); 0721 bool menubar = !vscale && oneOf(detail, "menubar"); 0722 bool button = !menubar && oneOf(detail, "button"); 0723 bool togglebutton = !button && oneOf(detail, "togglebutton"); 0724 bool optionmenu = !togglebutton && oneOf(detail, "optionmenu"); 0725 bool stepper = !optionmenu && oneOf(detail, "stepper"); 0726 bool vscrollbar = (!optionmenu && Str::startsWith(detail, "vscrollbar")); 0727 bool hscrollbar = (!vscrollbar && Str::startsWith(detail, "hscrollbar")); 0728 bool spinUp = !hscrollbar && oneOf(detail, "spinbutton_up"); 0729 bool spinDown = !spinUp && oneOf(detail, "spinbutton_down"); 0730 bool menuScroll = strstr(detail, "menu_scroll_arrow_"); 0731 bool rev = (reverseLayout(widget) || 0732 (widget && reverseLayout(gtk_widget_get_parent(widget)))); 0733 bool activeWindow = true; 0734 GdkColor new_cols[TOTAL_SHADES + 1]; 0735 const GdkColor *btnColors = qtcPalette.background; 0736 int bgnd = getFill(state, btnDown); 0737 auto round = getRound(detail, widget, rev); 0738 bool lvh = (isListViewHeader(widget) || 0739 isEvolutionListViewHeader(widget, detail)); 0740 bool sunken = (btnDown || shadow == GTK_SHADOW_IN || 0741 state == GTK_STATE_ACTIVE || bgnd == 2 || bgnd == 3); 0742 GtkWidget *parent = nullptr; 0743 0744 if (button && GTK_IS_TOGGLE_BUTTON(widget)) { 0745 button = false; 0746 togglebutton = true; 0747 } 0748 0749 if (qtSettings.debug == DEBUG_ALL) { 0750 printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %d %s ", __FUNCTION__, 0751 btnDown, state, shadow, x, y, width, height, _detail); 0752 debugDisplayWidget(widget, 10); 0753 } 0754 0755 // FIXME, need to update useButtonColor if the logic below changes right now 0756 if (useButtonColor(detail)) { 0757 if (slider | hscale | vscale | sbar && state == GTK_STATE_INSENSITIVE) { 0758 btnColors = qtcPalette.background; 0759 } else if (QT_CUSTOM_COLOR_BUTTON(style)) { 0760 shadeColors(&style->bg[state], new_cols); 0761 btnColors = new_cols; 0762 } else { 0763 SET_BTN_COLS(slider, hscale | vscale, lvh, state); 0764 } 0765 } 0766 0767 if (menubar && !isFakeGtk() && opts.shadeMenubarOnlyWhenActive) { 0768 GtkWindow *topLevel = GTK_WINDOW(gtk_widget_get_toplevel(widget)); 0769 0770 if (topLevel && GTK_IS_WINDOW(topLevel)) { 0771 GtkWidgetProps topProps(topLevel); 0772 if (!topProps->shadeActiveMBHacked) { 0773 topProps->shadeActiveMBHacked = true; 0774 g_signal_connect(G_OBJECT(topLevel), "event", 0775 G_CALLBACK(windowEvent), widget); 0776 } 0777 activeWindow = Window::isActive(GTK_WIDGET(topLevel)); 0778 } 0779 } 0780 0781 if (opts.menubarMouseOver && GTK_IS_MENU_SHELL(widget) && !isFakeGtk()) { 0782 Menu::shellSetup(widget); 0783 } 0784 0785 cairo_t *cr = Cairo::gdkCreateClip(window, area); 0786 if (spinUp || spinDown) { 0787 if (!opts.unifySpin && (!opts.unifySpinBtns || sunken)) { 0788 EWidget wid = spinUp ? WIDGET_SPIN_UP : WIDGET_SPIN_DOWN; 0789 QtcRect *a = (QtcRect*)area; 0790 QtcRect b; 0791 QtcRect unified; 0792 bool ooOrMoz = isFakeGtk(); 0793 if (!a && isFixedWidget(widget) && ooOrMoz) { 0794 b = qtcRect(x, y, width, height); 0795 a = &b; 0796 } 0797 if (wid == WIDGET_SPIN_UP) { 0798 if (opts.buttonEffect != EFFECT_NONE && opts.etchEntry) { 0799 if (!opts.unifySpinBtns) 0800 drawEtch(cr, a, widget, x - 2, y, width + 2, height * 2, 0801 false, ROUNDED_RIGHT, WIDGET_SPIN_UP); 0802 y++; 0803 width--; 0804 } 0805 height++; 0806 0807 if (opts.unifySpinBtns) { 0808 unified = qtcRect(x, y, width, 0809 height - (state == GTK_STATE_PRELIGHT ? 0810 2 : 1)); 0811 height *= 2; 0812 area = (GdkRectangle*)&unified; 0813 } else if (!opts.etchEntry) { 0814 height++; 0815 } 0816 } else if (opts.buttonEffect != EFFECT_NONE && opts.etchEntry) { 0817 QtcRect clip = {x - 2, y, width + 2, height}; 0818 if (!opts.unifySpinBtns) { 0819 drawEtch(cr, ooOrMoz ? a : &clip, widget, x - 2, y - 2, 0820 width + 2, height + 2, false, 0821 ROUNDED_RIGHT, WIDGET_SPIN_DOWN); 0822 } 0823 height--; 0824 width--; 0825 if (opts.unifySpinBtns) { 0826 unified = qtcRect( 0827 x, y + (state == GTK_STATE_PRELIGHT ? 1 : 0), 0828 width, height - (state == GTK_STATE_PRELIGHT ? 1 : 0)); 0829 y -= height; 0830 height *= 2; 0831 area = (GdkRectangle*)&unified; 0832 } 0833 } 0834 0835 drawBgnd(cr, &btnColors[bgnd], widget, (QtcRect*)area, 0836 x + 1, y + 1, width - 2, height - 2); 0837 drawLightBevel(cr, style, state, (QtcRect*)area, x, y, width, 0838 height - (WIDGET_SPIN_UP == wid && 0839 opts.buttonEffect != EFFECT_NONE ? 1 : 0), 0840 &btnColors[bgnd], btnColors, round, wid, BORDER_FLAT, 0841 DF_DO_BORDER | (sunken ? DF_SUNKEN : 0), widget); 0842 } 0843 } else if (oneOf(detail, "spinbutton")) { 0844 if (qtcIsFlatBgnd(opts.bgndAppearance) || 0845 !(widget && drawWindowBgnd(cr, style, (QtcRect*)area, window, 0846 widget, x, y, width, height))) { 0847 gtk_style_apply_default_background( 0848 style, window, widget && gtk_widget_get_has_window(widget), 0849 state == GTK_STATE_INSENSITIVE ? GTK_STATE_INSENSITIVE : 0850 GTK_STATE_NORMAL, area, x, y, width, height); 0851 if (widget && opts.bgndImage.type != IMG_NONE) { 0852 drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, 0853 x, y, width, height); 0854 } 0855 } 0856 0857 if (opts.unifySpin) { 0858 bool rev = (reverseLayout(widget) || 0859 (widget && 0860 reverseLayout(gtk_widget_get_parent(widget)))); 0861 bool moz = isMozillaWidget(widget); 0862 if (!rev) { 0863 x -= 4; 0864 } 0865 width += 4; 0866 0867 Cairo::Saver saver(cr); 0868 if (moz) { 0869 QtcRect a = {x + 2, y, width - 2, height}; 0870 Cairo::clipRect(cr, &a); 0871 } 0872 drawEntryField(cr, style, state, window, widget, (QtcRect*)area, 0873 x, y, width, height, 0874 rev ? ROUNDED_LEFT : ROUNDED_RIGHT, WIDGET_SPIN); 0875 } else if (opts.unifySpinBtns) { 0876 int offset = (opts.buttonEffect != EFFECT_NONE && opts.etchEntry ? 0877 1 : 0); 0878 if (offset) { 0879 drawEtch(cr, (QtcRect*)area, widget, x, y, width, height, false, 0880 ROUNDED_RIGHT, WIDGET_SPIN); 0881 } 0882 #if GTK_CHECK_VERSION(2, 90, 0) 0883 bgnd = getFill(state == GTK_STATE_ACTIVE ? GTK_STATE_NORMAL : state, 0884 false); 0885 #endif 0886 drawLightBevel(cr, style, state, (QtcRect*)area, x, y + offset, 0887 width - offset, height - 2 * offset, 0888 &btnColors[bgnd], btnColors, ROUNDED_RIGHT, 0889 WIDGET_SPIN, BORDER_FLAT, 0890 DF_DO_BORDER | (sunken ? DF_SUNKEN : 0), widget); 0891 drawFadedLine(cr, x + 2, y + height / 2, width - (offset + 4), 1, 0892 &btnColors[QTC_STD_BORDER], (QtcRect*)area, nullptr, 0893 true, true, true); 0894 } 0895 } else if (!opts.stdSidebarButtons && (button || togglebutton) && 0896 isSideBarBtn(widget)) { 0897 drawSidebarButton(cr, state, style, (QtcRect*)area, 0898 x, y, width, height); 0899 } else if (lvh) { 0900 if (opts.highlightScrollViews && widget) { 0901 GtkWidget *parent = gtk_widget_get_parent(widget); 0902 if (parent && GTK_IS_TREE_VIEW(parent)) { 0903 ScrolledWindow::registerChild(parent); 0904 } 0905 } 0906 drawListViewHeader(cr, state, btnColors, bgnd, (QtcRect*)area, 0907 x, y, width, height); 0908 } else if (isPathButton(widget)) { 0909 if (state == GTK_STATE_PRELIGHT) { 0910 drawSelection(cr, style, state, (QtcRect*)area, widget, 0911 x, y, width, height, ROUNDED_ALL, false, 1.0, 0); 0912 } 0913 if (opts.windowDrag > WM_DRAG_MENU_AND_TOOLBAR) { 0914 WMMove::setup(widget); 0915 } 0916 if (GTK_IS_TOGGLE_BUTTON(widget)) { 0917 drawArrow(window, &qtcPalette.background[5], (QtcRect*)area, 0918 GTK_ARROW_RIGHT, x + width - (LARGE_ARR_WIDTH / 2 + 4), 0919 y + (height - LARGE_ARR_HEIGHT / 2) / 2 + 1, false, true); 0920 } 0921 } else if (button || togglebutton || optionmenu || sbar || 0922 hscale || vscale || stepper || slider) { 0923 bool combo = oneOf(detail, "optionmenu") || isOnComboBox(widget, 0); 0924 bool combo_entry = combo && isOnComboEntry(widget, 0); 0925 bool horiz_tbar; 0926 bool tbar_button = isButtonOnToolbar(widget, &horiz_tbar); 0927 bool handle_button = (!tbar_button && 0928 isButtonOnHandlebox(widget, &horiz_tbar)); 0929 int xAdjust = 0; 0930 int yAdjust = 0; 0931 int wAdjust = 0; 0932 int hAdjust = 0; 0933 bool horiz = ((tbar_button || handle_button) && 0934 IS_GLASS(opts.appearance) && 0935 IS_GLASS(opts.toolbarAppearance) ? horiz_tbar : 0936 (slider && width < height) || vscrollbar || vscale || 0937 (stepper && widget && GTK_IS_VSCROLLBAR(widget)) ? 0938 false : true); 0939 bool defBtn = (state != GTK_STATE_INSENSITIVE && 0940 (button || togglebutton) && widget && 0941 gtk_widget_has_default(widget)); 0942 if (combo && !sunken && isActiveOptionMenu(widget)) { 0943 sunken = true; 0944 bgnd = 4; 0945 } 0946 if (tbar_button && opts.tbarBtns == TBTN_JOINED) { 0947 adjustToolbarButtons(widget, &xAdjust, &yAdjust, &wAdjust, &hAdjust, 0948 &round, horiz_tbar); 0949 x += xAdjust; 0950 y += yAdjust; 0951 width += wAdjust; 0952 height += hAdjust; 0953 } 0954 0955 { 0956 /* Yuck this is a horrible mess!!!!! */ 0957 bool glowFocus = (widget && gtk_widget_has_focus(widget) && 0958 opts.coloredMouseOver == MO_GLOW && 0959 oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)); 0960 EWidget widgetType=isComboBoxButton(widget) 0961 ? WIDGET_COMBO_BUTTON 0962 : slider 0963 ? qtcSlider ? WIDGET_SLIDER : WIDGET_SB_SLIDER 0964 : hscale||vscale 0965 ? WIDGET_SLIDER 0966 : combo || optionmenu 0967 ? WIDGET_COMBO 0968 : tbar_button 0969 ? (opts.coloredTbarMo ? WIDGET_TOOLBAR_BUTTON : WIDGET_UNCOLOURED_MO_BUTTON) 0970 : togglebutton 0971 ? (glowFocus && !sunken ? WIDGET_DEF_BUTTON : WIDGET_TOGGLE_BUTTON) 0972 : button 0973 ? defBtn || glowFocus 0974 ? WIDGET_DEF_BUTTON 0975 : WIDGET_STD_BUTTON 0976 : stepper || sbar 0977 ? WIDGET_SB_BUTTON 0978 : WIDGET_OTHER; 0979 int xo=x, yo=y, wo=width, ho=height, stepper=STEPPER_NONE; 0980 0981 /* Try and guess if this button is a toolbar button... */ 0982 if (oneOf(widgetType, WIDGET_STD_BUTTON, WIDGET_TOGGLE_BUTTON) && 0983 isMozillaWidget(widget) && GTK_IS_BUTTON(widget) && 0984 oneOf(detail, "button") && ((width > 22 && width < 56 && 0985 height > 30) || height >= 32 || 0986 ((width == 30 || width == 45) && 0987 height == 30))) 0988 widgetType = (opts.coloredTbarMo ? WIDGET_TOOLBAR_BUTTON : 0989 WIDGET_UNCOLOURED_MO_BUTTON); 0990 0991 if (ROUND_MAX==opts.round && 0992 ((WIDGET_TOGGLE_BUTTON==widgetType && height>(opts.crSize+8) && width<(height+10)) || 0993 (GTK_APP_GIMP==qtSettings.app && WIDGET_STD_BUTTON==widgetType && widgetIsType(widget, "GimpViewableButton")) || 0994 (opts.stdSidebarButtons && WIDGET_STD_BUTTON==widgetType && widget && isSideBarBtn(widget)) || 0995 (WIDGET_STD_BUTTON==widgetType && GTK_APP_OPEN_OFFICE==qtSettings.app && isFixedWidget(widget) && 0996 height>30 && height<40 && width>16 && width<50) ) ) 0997 widgetType=WIDGET_TOOLBAR_BUTTON; 0998 0999 /* For some reason SWT combo's dont un-prelight when activated! So dont pre-light at all! */ 1000 /* 1001 if(GTK_APP_JAVA_SWT==qtSettings.app && WIDGET_STD_BUTTON==widgetType && GTK_STATE_PRELIGHT==state && WIDGET_COMBO==widgetType) 1002 { 1003 state=GTK_STATE_NORMAL; 1004 bgnd=getFill(state, btnDown); 1005 } 1006 else */ if(WIDGET_SB_BUTTON==widgetType && GTK_APP_MOZILLA!=qtSettings.app) 1007 { 1008 stepper = getStepper(widget, x, y, width, height); 1009 switch (stepper) { 1010 case STEPPER_B: 1011 if (horiz) { 1012 x--; 1013 width++; 1014 } else { 1015 y--; 1016 height++; 1017 } 1018 break; 1019 case STEPPER_C: 1020 if (horiz) { 1021 width++; 1022 } else { 1023 height++; 1024 } 1025 default: 1026 break; 1027 } 1028 } 1029 1030 if(/*GTK_APP_JAVA_SWT==qtSettings.app && */ 1031 widget && !isFixedWidget(widget) && /* Don't do for Firefox, etc. */ 1032 WIDGET_SB_SLIDER==widgetType && GTK_STATE_INSENSITIVE!=state && GTK_IS_RANGE(widget)) 1033 { 1034 QtcRect alloc = Widget::getAllocation(widget); 1035 bool horizontal = !Widget::isHorizontal(widget); 1036 int sbarTroughLen = (horizontal ? alloc.height : alloc.width) - 1037 ((qtcRangeHasStepperA(widget) ? opts.sliderWidth : 0) + 1038 (qtcRangeHasStepperB(widget) ? opts.sliderWidth : 0) + 1039 (qtcRangeHasStepperC(widget) ? opts.sliderWidth : 0) + 1040 (qtcRangeHasStepperD(widget) ? opts.sliderWidth : 0)); 1041 int sliderLen = horizontal ? height : width; 1042 1043 if(sbarTroughLen==sliderLen) 1044 { 1045 state=GTK_STATE_INSENSITIVE; 1046 btnColors=qtcPalette.background; 1047 bgnd=getFill(state, false); 1048 } 1049 } 1050 #ifdef INCREASE_SB_SLIDER 1051 if(slider && widget && GTK_IS_RANGE(widget) && !opts.flatSbarButtons && SCROLLBAR_NONE!=opts.scrollbarType 1052 /*&& !(GTK_STATE_PRELIGHT==state && MO_GLOW==opts.coloredMouseOver)*/) 1053 { 1054 GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); 1055 bool horizontal = Widget::isHorizontal(widget); 1056 #if GTK_CHECK_VERSION(2, 90, 0) 1057 bool hasStartStepper = SCROLLBAR_PLATINUM!=opts.scrollbarType; 1058 bool hasEndStepper = SCROLLBAR_NEXT!=opts.scrollbarType; 1059 #else 1060 bool hasStartStepper = (qtcRangeHasStepperA(widget) || 1061 qtcRangeHasStepperB(widget)); 1062 bool hasEndStepper = (qtcRangeHasStepperC(widget) || 1063 qtcRangeHasStepperD(widget)); 1064 #endif 1065 bool atEnd = false; 1066 double value = gtk_adjustment_get_value(adj); 1067 1068 if (hasStartStepper && value <= gtk_adjustment_get_lower(adj)) { 1069 if (horizontal) { 1070 x--; 1071 width++; 1072 } else { 1073 y--; 1074 height++; 1075 } 1076 atEnd = true; 1077 } 1078 if (hasEndStepper && 1079 value >= (gtk_adjustment_get_upper(adj) - 1080 gtk_adjustment_get_page_size(adj))) { 1081 if (horizontal) { 1082 width++; 1083 } else { 1084 height++; 1085 } 1086 atEnd = true; 1087 } 1088 if (!isMozilla() && widget && 1089 lastSlider.widget == widget && !atEnd) { 1090 lastSlider.widget = nullptr; 1091 } 1092 } 1093 #endif 1094 1095 #if !GTK_CHECK_VERSION(2, 90, 0) /* Gtk3:TODO !!! */ 1096 if(GTK_APP_OPEN_OFFICE==qtSettings.app && opts.flatSbarButtons && slider && 1097 (SCROLLBAR_KDE==opts.scrollbarType || SCROLLBAR_WINDOWS==opts.scrollbarType) && 1098 widget && GTK_IS_RANGE(widget) && isFixedWidget(widget)) { 1099 if (!Widget::isHorizontal(widget)) { 1100 y++; 1101 height--; 1102 } else { 1103 x += 2; 1104 width -= 2; 1105 } 1106 } 1107 #endif 1108 if(WIDGET_COMBO==widgetType && !opts.gtkComboMenus && !isMozilla() && 1109 ((parent=gtk_widget_get_parent(widget)) && GTK_IS_COMBO_BOX(parent) && !QTC_COMBO_ENTRY(parent))) 1110 { 1111 GtkWidget *mapped = nullptr; 1112 bool changedFocus = false; 1113 bool draw = true; 1114 int mod = 7; 1115 1116 if (!opts.gtkComboMenus && !ComboBox::hasFrame(parent)) { 1117 mod = 0; 1118 draw = oneOf(state, GTK_STATE_ACTIVE, GTK_STATE_PRELIGHT); 1119 ComboBox::setup(nullptr, parent); 1120 } else { 1121 changedFocus = ComboBox::isFocusChanged(widget); 1122 mapped = WidgetMap::getWidget(parent, 1); 1123 WidgetMap::setup(parent, widget, 0); 1124 1125 if (parent && ComboBox::isHovered(parent)) { 1126 state = GTK_STATE_PRELIGHT; 1127 } 1128 } 1129 1130 if (draw) 1131 drawLightBevel(cr, style, state, (QtcRect*)area, x - mod, y, 1132 width + mod, height, &btnColors[bgnd], 1133 btnColors, round, WIDGET_TOOLBAR_BUTTON, 1134 BORDER_FLAT, (state == GTK_STATE_ACTIVE ? 1135 DF_SUNKEN : 0) | DF_DO_BORDER, 1136 widget); 1137 1138 if(mapped) 1139 { 1140 if(changedFocus) 1141 gtk_widget_queue_draw(mapped); 1142 else 1143 { 1144 GtkStateType mappedState=gtk_widget_get_state(mapped); 1145 if(GTK_STATE_INSENSITIVE==state && GTK_STATE_INSENSITIVE!=mappedState) 1146 state=mappedState; 1147 if(mappedState!=gtk_widget_get_state(widget) && GTK_STATE_INSENSITIVE!=mappedState && GTK_STATE_INSENSITIVE!=state) 1148 gtk_widget_set_state(mapped, state); 1149 } 1150 } 1151 } 1152 else if(opts.unifyCombo && WIDGET_COMBO_BUTTON==widgetType) 1153 { 1154 GtkWidget *parent=widget ? gtk_widget_get_parent(widget) : nullptr; 1155 GtkWidget *entry=parent ? getComboEntry(parent) : nullptr; 1156 GtkStateType entryState=entry ? gtk_widget_get_state(entry) : GTK_STATE_NORMAL; 1157 bool rev = false; 1158 bool mozToolbar = (isMozilla() && parent && 1159 GTK_IS_TOGGLE_BUTTON(widget) && 1160 QTC_COMBO_ENTRY(parent) && 1161 (parent = gtk_widget_get_parent(parent)) && 1162 GTK_IS_FIXED(parent) && 1163 (parent = gtk_widget_get_parent(parent)) && 1164 GTK_IS_WINDOW(parent) && 1165 strcmp(gtk_widget_get_name(parent), 1166 "MozillaGtkWidget") == 0); 1167 1168 if (!entry && widget && gtk_widget_get_parent(widget)) { 1169 entry = WidgetMap::getWidget( 1170 gtk_widget_get_parent(widget), 1); 1171 } 1172 1173 if(entry) 1174 rev=reverseLayout(entry); 1175 1176 if(!rev) 1177 x-=4; 1178 width+=4; 1179 if((mozToolbar && state==GTK_STATE_PRELIGHT) || state==GTK_STATE_ACTIVE) 1180 state=GTK_STATE_NORMAL; 1181 1182 // When we draw the entry, if its highlighted we want to highlight this button as well. 1183 // Unfortunately, when the entry of a GtkComboBoxEntry draws itself, there is no way to 1184 // determine the button associated with it. So, we store the mapping here... 1185 if(!mozToolbar && parent && QTC_COMBO_ENTRY(parent)) 1186 WidgetMap::setup(parent, widget, 0); 1187 // If the button is disabled, but the entry field is not - then use entry field's state 1188 // for the button. This fixes an issue with LinuxDC++ and Gtk 2.18 1189 if(GTK_STATE_INSENSITIVE==state && entry && GTK_STATE_INSENSITIVE!=entryState) 1190 state=entryState; 1191 1192 drawEntryField(cr, style, state, window, entry, (QtcRect*)area, x, y, width, height, rev ? ROUNDED_LEFT : ROUNDED_RIGHT, WIDGET_COMBO_BUTTON); 1193 1194 // Get entry to redraw by setting its state... 1195 // ...cant do a queue redraw, as then entry does for the button, else we get stuck in a loop! 1196 if(!mozToolbar && widget && entry && entryState!=gtk_widget_get_state(widget) && GTK_STATE_INSENSITIVE!=entryState && 1197 GTK_STATE_INSENSITIVE!=state) 1198 gtk_widget_set_state(entry, state); 1199 } else if (opts.flatSbarButtons && WIDGET_SB_BUTTON==widgetType) { 1200 #if !GTK_CHECK_VERSION(2, 90, 0) 1201 if (isMozilla()) { 1202 /* This section messes up Gtk3 scrollbars with custom background - and doesnt seem to be required for Gtk2 either. remove at 1.7.1 */ 1203 /* Re-added in 1.7.2 as needed by Mozilla! */ 1204 if(opts.gtkScrollViews && qtcIsFlat(opts.sbarBgndAppearance) && 0!=opts.tabBgnd && widget && gtk_widget_get_parent(widget) && gtk_widget_get_parent(widget)->parent && 1205 GTK_IS_SCROLLED_WINDOW(gtk_widget_get_parent(widget)) && GTK_IS_NOTEBOOK(gtk_widget_get_parent(widget)->parent)) 1206 drawAreaModColor(cr, (QtcRect*)area, &qtcPalette.background[ORIGINAL_SHADE], TO_FACTOR(opts.tabBgnd), xo, yo, wo, ho); 1207 else if(qtcIsFlatBgnd(opts.bgndAppearance) || !(opts.gtkScrollViews && qtcIsFlat(opts.sbarBgndAppearance) && 1208 widget && drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, xo, yo, wo, ho))) 1209 { 1210 if (!qtcIsFlat(opts.sbarBgndAppearance) && 1211 opts.scrollbarType != SCROLLBAR_NONE) { 1212 drawBevelGradient( 1213 cr, (QtcRect*)area, xo, yo, wo, ho, 1214 &qtcPalette.background[ORIGINAL_SHADE], horiz, 1215 false, opts.sbarBgndAppearance, WIDGET_SB_BGND); 1216 } else { 1217 drawBgnd( 1218 cr, &qtcPalette.background[ORIGINAL_SHADE], 1219 widget, (QtcRect*)area, xo, yo, wo, ho); 1220 } 1221 } 1222 } 1223 #endif 1224 } else { 1225 const GdkColor *cols = 1226 (defBtn && oneOf(opts.defBtnIndicator, IND_TINT, 1227 IND_COLORED, IND_SELECTED) ? 1228 qtcPalette.defbtn : widgetType == WIDGET_COMBO_BUTTON && 1229 qtcPalette.combobtn && state != GTK_STATE_INSENSITIVE ? 1230 qtcPalette.combobtn : btnColors); 1231 int bg = (WIDGET_COMBO_BUTTON==widgetType && 1232 (SHADE_DARKEN==opts.comboBtn || 1233 (SHADE_NONE != opts.comboBtn && GTK_STATE_INSENSITIVE==state))) || 1234 (WIDGET_SB_SLIDER==widgetType && SHADE_DARKEN==opts.shadeSliders) || 1235 (defBtn && IND_DARKEN==opts.defBtnIndicator) 1236 ? getFill(state, btnDown, true) : bgnd; 1237 1238 drawLightBevel(cr, style, state, (QtcRect*)area, x, y, width, 1239 height, &cols[bg], cols, round, widgetType, 1240 BORDER_FLAT, (sunken ? DF_SUNKEN : 0) | 1241 DF_DO_BORDER | (horiz ? 0 : DF_VERT), widget); 1242 1243 if(tbar_button && TBTN_JOINED==opts.tbarBtns) 1244 { 1245 const int constSpace=4; 1246 int xo=x-xAdjust, yo=y-yAdjust, wo=width-wAdjust, ho=height-hAdjust; 1247 1248 if(xAdjust) 1249 drawFadedLine(cr, xo, yo + constSpace, 1, 1250 ho - 2 * constSpace, &btnColors[0], 1251 (QtcRect*)area, nullptr, true, true, false); 1252 if (yAdjust) 1253 drawFadedLine(cr, xo + constSpace, yo, 1254 wo - 2 * constSpace, 1, &btnColors[0], 1255 (QtcRect*)area, nullptr, true, true, true); 1256 if(wAdjust && ROUNDED_RIGHT!=round) 1257 drawFadedLine(cr, xo + wo - 1, yo + constSpace, 1, 1258 ho - 2 * constSpace, 1259 &btnColors[QTC_STD_BORDER], 1260 (QtcRect*)area, nullptr, true, true, false); 1261 if (hAdjust && ROUNDED_BOTTOM!=round) 1262 drawFadedLine(cr, xo + constSpace, yo + ho - 1, 1263 wo - 2 * constSpace, 1, 1264 &btnColors[QTC_STD_BORDER], 1265 (QtcRect*)area, nullptr, true, true, true); 1266 } 1267 } 1268 1269 #ifdef INCREASE_SB_SLIDER 1270 /* Gtk draws slider first, and then the buttons. But if we have a shaded slider, and extend this so that it 1271 overlaps (by 1 pixel) the buttons, then the top/bottom is vut off if this is shaded... 1272 So, work-around this by re-drawing the slider here! */ 1273 if(!opts.flatSbarButtons && SHADE_NONE!=opts.shadeSliders && SCROLLBAR_NONE!=opts.scrollbarType && 1274 WIDGET_SB_BUTTON==widgetType && widget && widget==lastSlider.widget && !isMozilla() && 1275 ( (SCROLLBAR_NEXT==opts.scrollbarType && STEPPER_B==stepper) || STEPPER_D==stepper)) 1276 { 1277 #if GTK_CHECK_VERSION(2, 90, 0) 1278 gtkDrawSlider(lastSlider.style, lastSlider.cr, lastSlider.state, lastSlider.shadow, lastSlider.widget, 1279 lastSlider.detail, lastSlider.x, lastSlider.y, lastSlider.width, lastSlider.height, lastSlider.orientation); 1280 #else 1281 gtkDrawSlider(lastSlider.style, lastSlider.window, lastSlider.state, lastSlider.shadow, nullptr, lastSlider.widget, 1282 lastSlider.detail, lastSlider.x, lastSlider.y, lastSlider.width, lastSlider.height, lastSlider.orientation); 1283 #endif 1284 lastSlider.widget=nullptr; 1285 } 1286 #endif 1287 } 1288 if (defBtn) { 1289 drawDefBtnIndicator(cr, state, btnColors, bgnd, sunken, 1290 (QtcRect*)area, x, y, width, height); 1291 } 1292 if (opts.comboSplitter || opts.comboBtn != SHADE_NONE) { 1293 if (optionmenu) { 1294 GtkRequisition indicator_size; 1295 GtkBorder indicator_spacing; 1296 int cx=x, cy=y, cheight=height, cwidth=width, 1297 ind_width=0, 1298 darkLine=BORDER_VAL(GTK_STATE_INSENSITIVE!=state); 1299 1300 optionMenuGetProps(widget, &indicator_size, &indicator_spacing); 1301 1302 ind_width=indicator_size.width+indicator_spacing.left+indicator_spacing.right; 1303 1304 if (opts.buttonEffect != EFFECT_NONE) 1305 cx--; 1306 1307 cy+=3; 1308 cheight-=6; 1309 1310 if (opts.comboBtn != SHADE_NONE) { 1311 const GdkColor *cols = (qtcPalette.combobtn && 1312 state != GTK_STATE_INSENSITIVE ? 1313 qtcPalette.combobtn : btnColors); 1314 int bg = SHADE_DARKEN==opts.comboBtn || (GTK_STATE_INSENSITIVE==state && SHADE_NONE!=opts.comboBtn) ? getFill(state, btnDown, true) : bgnd; 1315 1316 QtcRect btn = { 1317 cx + (rev ? ind_width + style->xthickness : 1318 (cwidth - ind_width - style->xthickness) + 1), 1319 y, ind_width + 3, height 1320 }; 1321 Cairo::Saver saver(cr); 1322 if (!opts.comboSplitter) { 1323 Cairo::clipRect(cr, &btn); 1324 } 1325 if (rev) { 1326 btn.width += 3; 1327 } else { 1328 btn.x -= 3; 1329 if (opts.buttonEffect != EFFECT_NONE) { 1330 btn.width += 3; 1331 } else { 1332 btn.width += 1; 1333 } 1334 } 1335 drawLightBevel(cr, style, state, (QtcRect*)area, 1336 btn.x, btn.y, btn.width, btn.height, 1337 &cols[bg], cols, 1338 rev ? ROUNDED_LEFT : ROUNDED_RIGHT, 1339 WIDGET_COMBO, BORDER_FLAT, 1340 (sunken ? DF_SUNKEN : 0) | DF_DO_BORDER | 1341 DF_HIDE_EFFECT, widget); 1342 } else if (opts.comboSplitter) { 1343 if(sunken) 1344 cx++, cy++, cheight--; 1345 1346 drawFadedLine( 1347 cr, cx + (rev ? ind_width + style->xthickness : 1348 cwidth - ind_width - style->xthickness), 1349 cy + style->ythickness - 1, 1, cheight - 3, 1350 &btnColors[darkLine], (QtcRect*)area, nullptr, 1351 true, true, false); 1352 1353 if (!sunken) { 1354 drawFadedLine( 1355 cr, cx + 1 + (rev ? ind_width + style->xthickness : 1356 cwidth - ind_width - 1357 style->xthickness), 1358 cy + style->ythickness-1, 1, cheight - 3, 1359 &btnColors[0], (QtcRect*)area, nullptr, 1360 true, true, false); 1361 } 1362 } 1363 } else if((button || togglebutton) && (combo || combo_entry)) { 1364 int vx = x + (width - (1 + (combo_entry ? 24 : 20))); 1365 /* int vwidth = width - (vx - x); */ 1366 int darkLine = BORDER_VAL(GTK_STATE_INSENSITIVE != state); 1367 1368 if (rev) { 1369 vx = x + LARGE_ARR_WIDTH; 1370 if (combo_entry) { 1371 vx += 2; 1372 } 1373 } 1374 1375 if (opts.buttonEffect != EFFECT_NONE) 1376 vx -= 2; 1377 1378 if (!combo_entry) { 1379 if (opts.comboBtn != SHADE_NONE) { 1380 const GdkColor *cols = 1381 (qtcPalette.combobtn && 1382 state != GTK_STATE_INSENSITIVE ? 1383 qtcPalette.combobtn : btnColors); 1384 int bg = SHADE_DARKEN==opts.comboBtn || 1385 (GTK_STATE_INSENSITIVE==state && SHADE_NONE!=opts.comboBtn) ? getFill(state, btnDown, true) : bgnd; 1386 1387 QtcRect btn = { 1388 vx + (rev ? LARGE_ARR_WIDTH + 4 : 0), 1389 y, 20 + 3, height 1390 }; 1391 Cairo::Saver saver(cr); 1392 if (!opts.comboSplitter) { 1393 Cairo::clipRect(cr, &btn); 1394 } 1395 if (rev) { 1396 btn.width += 3; 1397 } else { 1398 btn.x -= 3; 1399 if (opts.buttonEffect != EFFECT_NONE) { 1400 btn.width += 3; 1401 } 1402 } 1403 drawLightBevel(cr, style, state, (QtcRect*)area, btn.x, btn.y, 1404 btn.width, btn.height, &cols[bg], cols, 1405 rev ? ROUNDED_LEFT : ROUNDED_RIGHT, 1406 WIDGET_COMBO, BORDER_FLAT, 1407 (sunken ? DF_SUNKEN : 0) | DF_DO_BORDER | 1408 DF_HIDE_EFFECT, widget); 1409 } else if (opts.comboSplitter) { 1410 drawFadedLine(cr, vx + (rev ? LARGE_ARR_WIDTH + 4 : 0), 1411 y + 4, 1, height - 8, 1412 &btnColors[darkLine], (QtcRect*)area, 1413 nullptr, true, true, false); 1414 1415 if(!sunken) 1416 drawFadedLine(cr, vx + 1 + 1417 (rev ? LARGE_ARR_WIDTH + 4 : 0), 1418 y + 4, 1, height - 8, &btnColors[0], 1419 (QtcRect*)area, nullptr, 1420 true, true, false); 1421 } 1422 } 1423 } 1424 } 1425 } else if (oneOf(detail, "buttondefault", "togglebuttondefault")) { 1426 } else if (widget && (oneOf(detail, "trough") || 1427 Str::startsWith(detail, "trough-"))) { 1428 bool list = isList(widget); 1429 bool pbar = list || GTK_IS_PROGRESS_BAR(widget); 1430 bool scale = !pbar && GTK_IS_SCALE(widget); 1431 /* int border = BORDER_VAL(GTK_STATE_INSENSITIVE != state || !scale); */ 1432 bool horiz = (GTK_IS_RANGE(widget) ? Widget::isHorizontal(widget) : 1433 width > height); 1434 1435 if (scale) { 1436 drawSliderGroove(cr, style, state, widget, detail, (QtcRect*)area, 1437 x, y, width, height, horiz); 1438 } else if (pbar) { 1439 drawProgressGroove(cr, style, state, window, widget, (QtcRect*)area, 1440 x, y, width, height, list, horiz); 1441 } else { 1442 drawScrollbarGroove(cr, style, state, widget, (QtcRect*)area, 1443 x, y, width, height, horiz); 1444 } 1445 } else if (oneOf(detail, "entry-progress")) { 1446 int adjust = (opts.fillProgress ? 4 : 3) - (opts.etchEntry ? 1 : 0); 1447 drawProgress(cr, style, state, widget, (QtcRect*)area, x - adjust, 1448 y - adjust, width + adjust, height + 2 * adjust, 1449 rev, true); 1450 } else if (oneOf(detail, "dockitem", "dockitem_bin")) { 1451 if (qtcIsCustomBgnd(opts) && widget) { 1452 drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, 1453 x, y, width, height); 1454 } 1455 } else if (widget && ((menubar || oneOf(detail, "toolbar", "handlebox", 1456 "handlebox_bin")) || 1457 widgetIsType(widget, "PanelAppletFrame"))) { 1458 //if(GTK_SHADOW_NONE!=shadow) 1459 { 1460 const GdkColor *col = menubar && (GTK_STATE_INSENSITIVE!=state || SHADE_NONE!=opts.shadeMenubars) 1461 ? &menuColors(activeWindow)[ORIGINAL_SHADE] 1462 : &style->bg[state]; 1463 EAppearance app=menubar ? opts.menubarAppearance : opts.toolbarAppearance; 1464 int menuBarAdjust=0, 1465 opacity=getOpacity(widget); 1466 double alpha=opacity!=100 ? (opacity/100.00) : 1.0; 1467 bool drawGradient = shadow != GTK_SHADOW_NONE && !qtcIsFlat(app); 1468 bool fillBackground = menubar && opts.shadeMenubars != SHADE_NONE; 1469 1470 if ((menubar && opts.windowDrag) || 1471 opts.windowDrag > WM_DRAG_MENUBAR) { 1472 WMMove::setup(widget); 1473 } 1474 1475 if (menubar && BLEND_TITLEBAR) { 1476 menuBarAdjust = qtcGetWindowBorderSize(false).titleHeight; 1477 if (widget && Menu::emitSize(widget, height) && 1478 (opts.menubarHiding || 1479 opts.windowBorder & 1480 WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR)) { 1481 Window::menuBarDBus(widget, height); 1482 } 1483 } 1484 1485 if (widget && (opacity!=100 || qtcIsCustomBgnd(opts))) { 1486 drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, 1487 x, y, width, height); 1488 } 1489 if (drawGradient) { 1490 drawBevelGradient(cr, (QtcRect*)area, x, y - menuBarAdjust, width, 1491 height + menuBarAdjust, col, 1492 (menubar ? true : oneOf(detail, "handlebox") ? 1493 width < height : width > height), 1494 false, MODIFY_AGUA(app), WIDGET_OTHER, alpha); 1495 } else if (fillBackground) { 1496 Cairo::rect(cr, (QtcRect*)area, x, y, width, height, 1497 col, alpha); 1498 } 1499 if (shadow != GTK_SHADOW_NONE && opts.toolbarBorders != TB_NONE) { 1500 drawToolbarBorders(cr, state, x, y, width, height, 1501 menubar && activeWindow, detail); 1502 } 1503 } 1504 } else if (widget && pbar) { 1505 drawProgress(cr, style, state, widget, (QtcRect*)area, 1506 x, y, width, height, rev, false); 1507 } else if (oneOf(detail, "menuitem")) { 1508 drawMenuItem(cr, state, style, widget, (QtcRect*)area, 1509 x, y, width, height); 1510 } else if (oneOf(detail, "menu")) { 1511 drawMenu(cr, widget, (QtcRect*)area, x, y, width, height); 1512 } else if ((!strcmp(detail, "paned") || !strcmp(detail + 1, "paned"))) { 1513 gtkDrawHandle(style, window, state, shadow, area, widget, detail, 1514 x, y, width, height, 1515 *detail == 'h' ? GTK_ORIENTATION_VERTICAL : 1516 GTK_ORIENTATION_HORIZONTAL); 1517 } else if (strcmp(detail + 1, "ruler") == 0) { 1518 drawBevelGradient(cr, (QtcRect*)area, x, y, width, height, 1519 &qtcPalette.background[ORIGINAL_SHADE], 1520 detail[0] == 'h', false, opts.lvAppearance, 1521 WIDGET_LISTVIEW_HEADER); 1522 1523 // if(qtcIsFlatBgnd(opts.bgndAppearance) || !widget || !drawWindowBgnd(cr, style, area, widget, x, y, width, height)) 1524 // { 1525 // drawAreaColor(cr, area, &style->bg[state], x, y, width, height); 1526 // if(widget && IMG_NONE!=opts.bgndImage.type) 1527 // drawWindowBgnd(cr, style, area, widget, x, y, width, height); 1528 // } 1529 } else if (oneOf(detail, "hseparator")) { 1530 bool isMenuItem = widget && GTK_IS_MENU_ITEM(widget); 1531 const GdkColor *cols=qtcPalette.background; 1532 int offset=opts.menuStripe && (isMozilla() || isMenuItem) ? 20 : 0; 1533 1534 if(offset && isFakeGtk()) 1535 offset+=2; 1536 1537 if (isMenuItem && (opts.lighterPopupMenuBgnd || opts.shadePopupMenu)) { 1538 cols = qtcPalette.menu; 1539 } 1540 1541 drawFadedLine(cr, x + 1 + offset, y + height / 2, width - (1 + offset), 1542 1, &cols[isMenuItem ? MENU_SEP_SHADE : QTC_STD_BORDER], 1543 (QtcRect*)area, nullptr, true, true, true); 1544 } else if (oneOf(detail, "vseparator")) { 1545 drawFadedLine(cr, x + width / 2, y, 1, height, 1546 &qtcPalette.background[QTC_STD_BORDER], (QtcRect*)area, 1547 nullptr, true, true, false); 1548 } else { 1549 EWidget wt = (!_detail && GTK_IS_TREE_VIEW(widget) ? 1550 WIDGET_PBAR_TROUGH : WIDGET_FRAME); 1551 Cairo::Saver saver(cr); 1552 qtcClipPath(cr, x + 1, y + 1, width - 2, height - 2, 1553 WIDGET_OTHER, RADIUS_INTERNAL, round); 1554 if (qtcIsFlatBgnd(opts.bgndAppearance) || !widget || 1555 !drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, 1556 x + 1, y + 1, width - 2, height - 2)) { 1557 Cairo::rect(cr, (QtcRect*)area, x + 1, y + 1, 1558 width - 2, height - 2, &style->bg[state]); 1559 if (widget && opts.bgndImage.type != IMG_NONE) { 1560 drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, x, y, 1561 width, height); 1562 } 1563 } 1564 saver.restore(); 1565 1566 if (wt == WIDGET_PBAR_TROUGH) { 1567 drawProgressGroove(cr, style, state, window, widget, 1568 (QtcRect*)area, x, y, width, height, true, true); 1569 } else { 1570 drawBorder(cr, style, state, (QtcRect*)area, x, y, width, height, 1571 nullptr, (menuScroll || opts.square & SQUARE_FRAME ? 1572 ROUNDED_NONE : ROUNDED_ALL), 1573 shadowToBorder(shadow), wt, QTC_STD_BORDER); 1574 } 1575 } 1576 cairo_destroy(cr); 1577 } 1578 1579 static void 1580 gtkDrawBox(GtkStyle *style, GdkWindow *window, GtkStateType state, 1581 GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, 1582 const char *detail, int x, int y, int width, int height) 1583 { 1584 sanitizeSize(window, &width, &height); 1585 drawBox(style, window, state, shadow, area, widget, detail, x, y, 1586 width, height, 1587 state == GTK_STATE_ACTIVE || shadow == GTK_SHADOW_IN); 1588 } 1589 1590 static void 1591 gtkDrawShadow(GtkStyle *style, GdkWindow *window, GtkStateType state, 1592 GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, 1593 const char *_detail, int x, int y, int width, int height) 1594 { 1595 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 1596 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 1597 const char *detail = _detail ? _detail : ""; 1598 sanitizeSize(window, &width, &height); 1599 cairo_t *cr = Cairo::gdkCreateClip(window, area); 1600 bool comboBoxList = isComboBoxList(widget); 1601 bool comboList = !comboBoxList && isComboList(widget); 1602 1603 if (comboBoxList || comboList) { 1604 bool square = opts.square & SQUARE_POPUP_MENUS; 1605 1606 if ((!square || opts.popupBorder) && 1607 (!comboList || noneOf(detail, "viewport"))) { 1608 bool nonGtk = square || isFakeGtk(); 1609 bool composActive = !nonGtk && compositingActive(widget); 1610 bool isAlphaWidget = (!nonGtk && composActive && 1611 isRgbaWidget(widget)); 1612 bool useAlpha = !nonGtk && qtSettings.useAlpha && isAlphaWidget; 1613 1614 if (opts.popupBorder && square) { 1615 Cairo::rect(cr, (QtcRect*)area, x, y, width, height, 1616 &style->base[state]); 1617 cairo_new_path(cr); 1618 cairo_rectangle(cr, x + 0.5, y + 0.5, width - 1, height - 1); 1619 Cairo::setColor(cr, &qtcPalette.background[QTC_STD_BORDER]); 1620 cairo_stroke(cr); 1621 } else /* if (!opts.popupBorder || */ 1622 /* !(opts.square & SQUARE_POPUP_MENUS)) */ { 1623 if (useAlpha) { 1624 cairo_rectangle(cr, x, y, width, height); 1625 cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); 1626 cairo_set_source_rgba(cr, 0, 0, 0, 1); 1627 cairo_fill(cr); 1628 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); 1629 clearRoundedMask(widget, false); 1630 } else { 1631 createRoundedMask(widget, x, y, width, height, 1632 opts.round >= ROUND_FULL ? 5.0 : 2.5, 1633 false); 1634 } 1635 1636 Cairo::clipWhole(cr, x, y, width, height, 1637 opts.round >= ROUND_FULL ? 5.0 : 2.5, 1638 ROUNDED_ALL); 1639 Cairo::rect(cr, (QtcRect*)area, x, y, width, height, 1640 &style->base[state]); 1641 if(useAlpha) 1642 cairo_set_operator(cr, CAIRO_OPERATOR_OVER); 1643 if (opts.popupBorder) { 1644 Cairo::pathWhole(cr, x + 0.5, y + 0.5, width - 1, 1645 height - 1, (opts.round >= ROUND_FULL ? 1646 5.0 : 2.5) - 1, 1647 ROUNDED_ALL); 1648 Cairo::setColor(cr, 1649 &qtcPalette.background[QTC_STD_BORDER]); 1650 cairo_stroke(cr); 1651 } 1652 } 1653 } else { 1654 Cairo::rect(cr, (QtcRect*)area, x, y, width, height, 1655 &style->base[state]); 1656 } 1657 } 1658 else if(!opts.gtkComboMenus && !isMozilla() && isComboFrame(widget)) 1659 { 1660 GdkColor newColors[TOTAL_SHADES + 1]; 1661 GdkColor *btnColors; 1662 int bgnd = getFill(state, false); // TODO!!! btnDown??? 1663 bool sunken = //btnDown || (GTK_IS_BUTTON(widget) && qtcButtonIsDepressed(widget)) || 1664 state == GTK_STATE_ACTIVE || oneOf(bgnd, 2, 3); 1665 GtkWidget *parent = gtk_widget_get_parent(widget); 1666 GtkWidget *mapped = parent ? WidgetMap::getWidget(parent, 0) : nullptr; 1667 1668 if(parent && ComboBox::isHovered(parent)) 1669 state=GTK_STATE_PRELIGHT; 1670 1671 if(QT_CUSTOM_COLOR_BUTTON(style)) 1672 { 1673 shadeColors(&style->bg[state], newColors); 1674 btnColors=newColors; 1675 } 1676 else 1677 btnColors=qtcPalette.button[GTK_STATE_INSENSITIVE==state ? PAL_DISABLED : PAL_ACTIVE]; 1678 1679 drawLightBevel(cr, style, state, (QtcRect*)area, x, y, width + 4, height, 1680 &btnColors[bgnd], btnColors, ROUNDED_LEFT, 1681 WIDGET_TOOLBAR_BUTTON, BORDER_FLAT, 1682 (sunken ? DF_SUNKEN : 0) | DF_DO_BORDER | 1683 (ComboBox::hasFocus(widget, mapped) ? DF_HAS_FOCUS : 0), 1684 widget); 1685 1686 if(GTK_STATE_PRELIGHT!=state) 1687 { 1688 if(mapped && GTK_STATE_PRELIGHT==gtk_widget_get_state(mapped)) 1689 state=GTK_STATE_PRELIGHT, gtk_widget_set_state(widget, GTK_STATE_PRELIGHT); 1690 } 1691 if(mapped && GTK_STATE_INSENSITIVE!=gtk_widget_get_state(widget)) 1692 gtk_widget_queue_draw(mapped); 1693 1694 WidgetMap::setup(parent, widget, 1); 1695 ComboBox::setup(widget, parent); 1696 } else if (oneOf(detail, "entry", "text")) { 1697 GtkWidget *parent=widget ? gtk_widget_get_parent(widget) : nullptr; 1698 if (parent && isList(parent)) { 1699 // Dont draw shadow for entries in listviews... 1700 // Fixes RealPlayer's in-line editing of its favourites. 1701 } else { 1702 bool combo = isComboBoxEntry(widget); 1703 bool isSpin = !combo && isSpinButton(widget); 1704 bool rev = reverseLayout(widget) || (combo && parent && 1705 reverseLayout(parent)); 1706 GtkWidget *btn = nullptr; 1707 /* GtkStateType savedState = state; */ 1708 1709 #if GTK_CHECK_VERSION(2, 16, 0) 1710 #if !GTK_CHECK_VERSION(2, 90, 0) /* Gtk3:TODO !!! */ 1711 if (isSpin && widget && 1712 width == Widget::getAllocation(widget).width) { 1713 int btnWidth, dummy; 1714 gdk_drawable_get_size(GTK_SPIN_BUTTON(widget)->panel, &btnWidth, &dummy); 1715 width-=btnWidth; 1716 if(rev) 1717 x+=btnWidth; 1718 } 1719 #endif 1720 #endif 1721 if((opts.unifySpin && isSpin) || (combo && opts.unifyCombo)) 1722 width+=(combo ? 4 : 2); 1723 1724 // If we're a combo entry, and not prelight, check to see if the button is 1725 // prelighted, if so so are we! 1726 if(GTK_STATE_PRELIGHT!=state && combo && opts.unifyCombo && parent) 1727 { 1728 btn=getComboButton(parent); 1729 if (!btn && parent) { 1730 btn = WidgetMap::getWidget(parent, 0); 1731 } 1732 if(btn && GTK_STATE_PRELIGHT==gtk_widget_get_state(btn)) 1733 state=GTK_STATE_PRELIGHT, gtk_widget_set_state(widget, GTK_STATE_PRELIGHT); 1734 } 1735 1736 #if GTK_CHECK_VERSION(2, 90, 0) 1737 if(!opts.unifySpin && isSpin) 1738 width-=16; 1739 #endif 1740 drawEntryField(cr, style, state, window, widget, (QtcRect*)area, 1741 x, y, width, height, combo || isSpin ? rev ? 1742 ROUNDED_RIGHT : ROUNDED_LEFT : ROUNDED_ALL, 1743 WIDGET_ENTRY); 1744 if(combo && opts.unifyCombo && parent) 1745 { 1746 if(btn && GTK_STATE_INSENSITIVE!=gtk_widget_get_state(widget)) 1747 gtk_widget_queue_draw(btn); 1748 1749 if (QTC_COMBO_ENTRY(parent)) { 1750 WidgetMap::setup(parent, widget, 1); 1751 } 1752 } 1753 } 1754 } else { 1755 bool frame = !_detail || strcmp(detail, "frame") == 0; 1756 bool scrolledWindow = oneOf(detail, "scrolled_window"); 1757 bool viewport = !scrolledWindow && strstr(detail, "viewport"); 1758 bool drawSquare = ((frame && opts.square & SQUARE_FRAME) || 1759 (!viewport && !scrolledWindow && 1760 !_detail && !widget)); 1761 bool statusBar = (isFakeGtk() ? frame : isStatusBarFrame(widget)); 1762 bool checkScrollViewState = (opts.highlightScrollViews && widget && 1763 GTK_IS_SCROLLED_WINDOW(widget)); 1764 bool isHovered = false; 1765 bool hasFocus = false; 1766 GdkColor *cols = nullptr; 1767 1768 if (qtSettings.debug == DEBUG_ALL) { 1769 printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %s ", __FUNCTION__, 1770 state, shadow, x, y, width, height, _detail); 1771 debugDisplayWidget(widget, 10); 1772 } 1773 1774 if(scrolledWindow && GTK_SHADOW_IN!=shadow && widget && GTK_IS_SCROLLED_WINDOW(widget) && 1775 GTK_IS_TREE_VIEW(gtk_bin_get_child(GTK_BIN(widget)))) 1776 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(widget), GTK_SHADOW_IN), shadow=GTK_SHADOW_IN; 1777 else if(frame && !statusBar && GTK_IS_FRAME(widget)) 1778 { 1779 /* 1780 check for scrolled windows embedded in frames, that contain a treeview. 1781 if found, change the shadowtypes for consistency with normal -sunken- scrolled windows. 1782 this should improve rendering of most mandriva drake tools 1783 */ 1784 GtkWidget *child=gtk_bin_get_child(GTK_BIN(widget)); 1785 if(GTK_IS_SCROLLED_WINDOW(child) && GTK_IS_TREE_VIEW(gtk_bin_get_child(GTK_BIN(child)))) 1786 { 1787 gtk_frame_set_shadow_type(GTK_FRAME(widget), GTK_SHADOW_NONE); 1788 shadow=GTK_SHADOW_NONE; 1789 1790 // also change scrolled window shadow if needed 1791 GtkScrolledWindow *sw=GTK_SCROLLED_WINDOW(child); 1792 if(GTK_SHADOW_IN!=gtk_scrolled_window_get_shadow_type(sw)) 1793 gtk_scrolled_window_set_shadow_type(sw, GTK_SHADOW_IN); 1794 } 1795 } 1796 1797 if (checkScrollViewState) { 1798 ScrolledWindow::setup(widget); 1799 isHovered = ScrolledWindow::hovered(widget); 1800 hasFocus = !isHovered && ScrolledWindow::hasFocus(widget); 1801 } 1802 1803 cols=isHovered ? qtcPalette.mouseover 1804 : hasFocus 1805 ? qtcPalette.focus 1806 : qtcPalette.background; 1807 if(!statusBar && !drawSquare && (frame || scrolledWindow || viewport/* || drawSquare*/)) // && ROUNDED) 1808 { 1809 if (shadow != GTK_SHADOW_NONE && 1810 (!frame || opts.drawStatusBarFrames || !isFakeGtk())) { 1811 GtkWidget *parent = (widget ? gtk_widget_get_parent(widget) : 1812 nullptr); 1813 bool doBorder = !viewport && !drawSquare; 1814 bool windowFrame = (parent && !isFixedWidget(widget) && 1815 GTK_IS_FRAME(widget) && 1816 GTK_IS_WINDOW(parent)); 1817 1818 if (windowFrame) { 1819 QtcRect wAlloc = Widget::getAllocation(widget); 1820 QtcRect pAlloc = Widget::getAllocation(parent); 1821 windowFrame = Rect::equal(wAlloc, pAlloc); 1822 } 1823 1824 // if(!drawSquare && widget && gtk_widget_get_parent(widget) && !isFixedWidget(widget) && 1825 // GTK_IS_FRAME(widget) && GTK_IS_WINDOW(gtk_widget_get_parent(widget))) 1826 // drawSquare=true; 1827 1828 if(scrolledWindow) 1829 { 1830 /* See code in qt_settings.c as to isMozill part */ 1831 if((opts.square&SQUARE_SCROLLVIEW && !opts.highlightScrollViews) || isMozillaWidget(widget)) 1832 { 1833 /* Flat style... 1834 drawBorder(cr, style, state, area, x, y, width, height, 1835 nullptr, ROUNDED_NONE, BORDER_FLAT, WIDGET_SCROLLVIEW, 0); 1836 */ 1837 /* 3d... */ 1838 Cairo::setColor(cr, &cols[QTC_STD_BORDER]); 1839 Cairo::pathTopLeft(cr, x + 0.5, y + 0.5, width - 1, 1840 height - 1, 0.0, ROUNDED_NONE); 1841 cairo_stroke(cr); 1842 if(!opts.gtkScrollViews) 1843 Cairo::setColor(cr, &cols[QTC_STD_BORDER], 1844 LOWER_BORDER_ALPHA); 1845 /* Cairo::setColor(cr, &qtcPalette.background[ */ 1846 /* STD_BORDER_BR]); */ 1847 Cairo::pathBottomRight(cr, x + 0.5, y + 0.5, width - 1, 1848 height - 1, 0, ROUNDED_NONE); 1849 cairo_stroke(cr); 1850 doBorder=false; 1851 } else if (opts.etchEntry) { 1852 drawEtch(cr, (QtcRect*)area, widget, x, y, width, 1853 height, false, ROUNDED_ALL, WIDGET_SCROLLVIEW); 1854 x++; 1855 y++; 1856 width -= 2; 1857 height -= 2; 1858 } 1859 } 1860 if (viewport || windowFrame/* || drawSquare*/) { 1861 cairo_new_path(cr); 1862 cairo_rectangle(cr, x + 0.5, y + 0.5, 1863 width - 1, height - 1); 1864 if (windowFrame) { 1865 Cairo::setColor(cr, &cols[QTC_STD_BORDER]); 1866 } else { 1867 Cairo::setColor(cr, &cols[ORIGINAL_SHADE]); 1868 } 1869 cairo_stroke(cr); 1870 } 1871 else if(doBorder) 1872 drawBorder(cr, style, state, (QtcRect*)area, x, y, width, 1873 height, cols, ROUNDED_ALL, 1874 scrolledWindow ? BORDER_SUNKEN : BORDER_FLAT, 1875 scrolledWindow ? WIDGET_SCROLLVIEW : 1876 WIDGET_FRAME, DF_BLEND); 1877 } 1878 } else if (!statusBar || opts.drawStatusBarFrames) { 1879 int c1 = 0; 1880 int c2 = 0; 1881 1882 switch(shadow) { 1883 case GTK_SHADOW_NONE: 1884 if (!statusBar) 1885 break; 1886 shadow = GTK_SHADOW_IN; 1887 /* FALLTHROUGH */ 1888 case GTK_SHADOW_IN: 1889 case GTK_SHADOW_ETCHED_IN: 1890 c1 = 0; 1891 c2 = QTC_STD_BORDER; 1892 break; 1893 case GTK_SHADOW_OUT: 1894 case GTK_SHADOW_ETCHED_OUT: 1895 c1 = QTC_STD_BORDER; 1896 c2 = 0; 1897 break; 1898 } 1899 1900 switch(shadow) { 1901 case GTK_SHADOW_NONE: 1902 if (!frame) { 1903 cairo_new_path(cr); 1904 cairo_rectangle(cr, x + 0.5, y + 0.5, 1905 width - 1, height - 1); 1906 Cairo::setColor(cr, &cols[QTC_STD_BORDER]); 1907 cairo_stroke(cr); 1908 } 1909 break; 1910 case GTK_SHADOW_IN: 1911 case GTK_SHADOW_OUT: 1912 // if(drawSquare || frame || !ROUNDED) 1913 { 1914 double c2Alpha = 1915 shadow == GTK_SHADOW_IN ? 1.0 : LOWER_BORDER_ALPHA; 1916 double c1Alpha = 1917 shadow == GTK_SHADOW_OUT ? 1.0 : LOWER_BORDER_ALPHA; 1918 Cairo::hLine(cr, x, y, width, 1919 &cols[QTC_STD_BORDER], c2Alpha); 1920 Cairo::vLine(cr, x, y, height, 1921 &cols[QTC_STD_BORDER], c2Alpha); 1922 if (opts.appearance != APPEARANCE_FLAT) { 1923 Cairo::hLine(cr, x, y + height - 1, width, 1924 &cols[QTC_STD_BORDER], c1Alpha); 1925 Cairo::vLine(cr, x + width - 1, y, height, 1926 &cols[QTC_STD_BORDER], c1Alpha); 1927 } 1928 break; 1929 } 1930 case GTK_SHADOW_ETCHED_IN: 1931 cairo_new_path(cr); 1932 cairo_rectangle(cr, x + 1.5, y + 1.5, width - 2, height - 2); 1933 Cairo::setColor(cr, &cols[c1]); 1934 cairo_stroke(cr); 1935 cairo_new_path(cr); 1936 cairo_rectangle(cr, x + 0.5, y + 0.5, width - 2, height - 2); 1937 Cairo::setColor(cr, &cols[c2]); 1938 cairo_stroke(cr); 1939 break; 1940 case GTK_SHADOW_ETCHED_OUT: 1941 cairo_new_path(cr); 1942 cairo_rectangle(cr, x + 1.5, y + 1.5, width - 2, height - 2); 1943 Cairo::setColor(cr, &cols[c2]); 1944 cairo_stroke(cr); 1945 cairo_new_path(cr); 1946 cairo_rectangle(cr, x + 0.5, y + 0.5, width - 2, height - 2); 1947 Cairo::setColor(cr, &cols[c1]); 1948 cairo_stroke(cr); 1949 break; 1950 } 1951 } 1952 } 1953 cairo_destroy(cr); 1954 } 1955 1956 // static gboolean isHoveredCell(GtkWidget *widget, int x, int y, int width, int height) 1957 // { 1958 // gboolean hovered=false; 1959 // 1960 // if(widget && GTK_IS_TREE_VIEW(widget)) 1961 // { 1962 // GtkTreePath *path=nullptr; 1963 // GtkTreeViewColumn *column=nullptr; 1964 // 1965 // qtcTreeViewSetup(widget); 1966 // qtcTreeViewGetCell(GTK_TREE_VIEW(widget), &path, &column, x, y, width, height); 1967 // hovered=path && qtcTreeViewIsCellHovered(widget, path, column); 1968 // } 1969 // 1970 // return hovered; 1971 // } 1972 1973 static void 1974 gtkDrawCheck(GtkStyle *style, GdkWindow *window, GtkStateType state, 1975 GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, 1976 const char *_detail, int x, int y, int width, int height) 1977 { 1978 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 1979 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 1980 const char *detail = _detail ? _detail : ""; 1981 QtcRect *area = (QtcRect*)_area; 1982 cairo_t *cr = Cairo::gdkCreateClip(window, area); 1983 drawCheckBox(cr, state, shadow, style, widget, detail, area, 1984 x, y, width, height); 1985 cairo_destroy(cr); 1986 } 1987 1988 static void 1989 gtkDrawOption(GtkStyle *style, GdkWindow *window, GtkStateType state, 1990 GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, 1991 const char *_detail, int x, int y, int width, int height) 1992 { 1993 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 1994 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 1995 const char *detail = _detail ? _detail : ""; 1996 QtcRect *area = (QtcRect*)_area; 1997 cairo_t *cr = Cairo::gdkCreateClip(window, area); 1998 drawRadioButton(cr, state, shadow, style, widget, detail, area, 1999 x, y, width, height); 2000 cairo_destroy(cr); 2001 } 2002 2003 #define NUM_GCS 5 2004 2005 static void 2006 drawLayout(cairo_t *cr, GtkStyle *style, GtkStateType state, 2007 bool use_text, const QtcRect *area, int x, int y, 2008 PangoLayout *layout) 2009 { 2010 Cairo::layout(cr, area, x, y, layout, 2011 use_text || state == GTK_STATE_INSENSITIVE ? 2012 &style->text[state] : &style->fg[state]); 2013 } 2014 2015 static void 2016 gtkDrawLayout(GtkStyle *style, GdkWindow *window, GtkStateType state, 2017 gboolean use_text, GdkRectangle *_area, GtkWidget *widget, 2018 const char *_detail, int x, int y, PangoLayout *layout) 2019 { 2020 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 2021 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2022 const char *detail = _detail ? _detail : ""; 2023 const QtcRect *area = (QtcRect*)_area; 2024 cairo_t *cr = gdk_cairo_create(window); 2025 if (GTK_IS_PROGRESS(widget) || oneOf(detail, "progressbar")) { 2026 drawLayout(cr, style, state, use_text, area, x, y, layout); 2027 } else { 2028 Style *qtc_style = (Style*)style; 2029 bool isMenuItem = isMenuitem(widget); 2030 GtkMenuBar *mb = isMenuItem ? isMenubar(widget, 0) : nullptr; 2031 bool activeMb = mb ? GTK_MENU_SHELL(mb)->active : false; 2032 bool selectedText = ((opts.useHighlightForMenu || 2033 opts.customMenuTextColor) && isMenuItem && 2034 (opts.colorMenubarMouseOver ? 2035 state == GTK_STATE_PRELIGHT : 2036 ((!mb || activeMb) && 2037 state == GTK_STATE_PRELIGHT))); 2038 bool def_but = false; 2039 bool but = isOnButton(widget, 0, &def_but); 2040 bool swapColors = false; 2041 QtcRect area2; 2042 GtkWidget *parent = widget ? gtk_widget_get_parent(widget) : nullptr; 2043 2044 if (!opts.colorMenubarMouseOver && mb && !activeMb && 2045 state == GTK_STATE_PRELIGHT) 2046 state = GTK_STATE_NORMAL; 2047 2048 GdkColor prevColors[NUM_GCS]; 2049 2050 if (qtSettings.debug == DEBUG_ALL) { 2051 printf(DEBUG_PREFIX "%s %s %d %d %d %d %d %s ", __FUNCTION__, 2052 pango_layout_get_text(layout), x, y, state, use_text, 2053 isMenuitem(widget), _detail); 2054 debugDisplayWidget(widget, 10); 2055 } 2056 2057 if (oneOf(detail, "cellrenderertext") && widget && 2058 gtk_widget_get_state(widget) == GTK_STATE_INSENSITIVE) 2059 state = GTK_STATE_INSENSITIVE; 2060 2061 #ifndef READ_INACTIVE_PAL 2062 /* If we reead the inactive palette, then there is no need for the 2063 following... The following fixes the text in list views... 2064 if not used, when an item is selected it gets the selected text 2065 color - but when the window changes focus it gets the normal 2066 text color! */ 2067 if (oneOf(detail, "cellrenderertext") && state == GTK_STATE_ACTIVE) 2068 state = GTK_STATE_SELECTED; 2069 #endif 2070 2071 if (!isMenuItem && state == GTK_STATE_PRELIGHT) 2072 state = GTK_STATE_NORMAL; 2073 2074 if (!use_text && parent && GTK_IS_LABEL(widget) && 2075 (isOnOptionMenu(parent, 0) || 2076 (GTK_IS_BUTTON(parent) && isOnMenuItem(parent, 0)))) { 2077 use_text = true; 2078 } 2079 2080 /* 2081 This check of 'requisition' size (and not 'allocation') seems to 2082 match better with Qt4's text positioning. For example, 10pt verdana 2083 - no shift is required 9pt DejaVu Sans requires the shift 2084 */ 2085 if (but && widget) { 2086 GtkRequisition req = Widget::getRequisition(widget); 2087 if (req.height < Widget::getAllocation(widget).height && 2088 req.height % 2) { 2089 y++; 2090 } 2091 } 2092 2093 but = but || isOnComboBox(widget, 0); 2094 2095 if (isOnListViewHeader(widget, 0)) 2096 y--; 2097 2098 if (but && ((qtSettings.qt4 && state == GTK_STATE_INSENSITIVE) || 2099 (!qtSettings.qt4 && state != GTK_STATE_INSENSITIVE))) { 2100 use_text = true; 2101 swapColors = true; 2102 for (int i = 0;i < NUM_GCS;++i) { 2103 prevColors[i] = style->text[i]; 2104 style->text[i] = 2105 *qtc_style->button_text[state == GTK_STATE_INSENSITIVE ? 2106 PAL_DISABLED : PAL_ACTIVE]; 2107 } 2108 if (state == GTK_STATE_INSENSITIVE) { 2109 state = GTK_STATE_NORMAL; 2110 } 2111 } else if (isMenuItem) { 2112 bool activeWindow = 2113 (mb && opts.shadeMenubarOnlyWhenActive && widget ? 2114 Window::isActive(gtk_widget_get_toplevel(widget)) : true); 2115 2116 if ((opts.shadePopupMenu && state == GTK_STATE_PRELIGHT) || 2117 (mb && (activeWindow || 2118 opts.shadeMenubars == SHADE_WINDOW_BORDER))) { 2119 if (opts.shadeMenubars == SHADE_WINDOW_BORDER) { 2120 for (int i = 0;i < NUM_GCS;i++) { 2121 prevColors[i] = style->text[i]; 2122 } 2123 swapColors = true; 2124 style->text[GTK_STATE_NORMAL] = 2125 *qtc_style->menutext[activeWindow ? 1 : 0]; 2126 use_text = true; 2127 } else if (opts.customMenuTextColor && 2128 qtc_style->menutext[0]) { 2129 for (int i = 0;i < NUM_GCS;i++) { 2130 prevColors[i] = style->text[i]; 2131 } 2132 swapColors = true; 2133 style->text[GTK_STATE_NORMAL] = *qtc_style->menutext[0]; 2134 style->text[GTK_STATE_ACTIVE] = *qtc_style->menutext[1]; 2135 style->text[GTK_STATE_PRELIGHT] = *qtc_style->menutext[0]; 2136 style->text[GTK_STATE_SELECTED] = *qtc_style->menutext[1]; 2137 style->text[GTK_STATE_INSENSITIVE] = 2138 *qtc_style->menutext[0]; 2139 use_text = true; 2140 } else if (oneOf(opts.shadeMenubars, SHADE_BLEND_SELECTED, 2141 SHADE_SELECTED) || 2142 (opts.shadeMenubars == SHADE_CUSTOM && 2143 TOO_DARK(qtcPalette.menubar[ORIGINAL_SHADE]))) { 2144 selectedText = true; 2145 } 2146 } 2147 } 2148 2149 if (parent && GTK_IS_LABEL(widget) && GTK_IS_FRAME(parent) && 2150 !isOnStatusBar(widget, 0)) { 2151 int diff = (Widget::getAllocation(widget).x - 2152 Widget::getAllocation(parent).x); 2153 2154 if (qtcNoFrame(opts.groupBox)) { 2155 x -= qtcBound(0, diff, 8); 2156 } else if (opts.gbLabel&GB_LBL_OUTSIDE) { 2157 x -= qtcBound(0, diff, 4); 2158 } else if(opts.gbLabel&GB_LBL_INSIDE) { 2159 x -= qtcBound(0, diff, 2); 2160 } else { 2161 x += 5; 2162 } 2163 #if GTK_CHECK_VERSION(2, 90, 0) 2164 cairo_reset_clip(cr); 2165 #else 2166 if (area) { 2167 area2 = *area; 2168 if (qtcNoFrame(opts.groupBox)) { 2169 area2.x -= qtcBound(0, diff, 8); 2170 } else if (opts.gbLabel & GB_LBL_OUTSIDE) { 2171 area2.x -= qtcBound(0, diff, 4); 2172 } else if(opts.gbLabel&GB_LBL_INSIDE) { 2173 area2.x -= qtcBound(0, diff, 2); 2174 } else { 2175 area2.x += 5; 2176 } 2177 area = &area2; 2178 } 2179 #endif 2180 } 2181 2182 if (!opts.useHighlightForMenu && (isMenuItem || mb) && 2183 state != GTK_STATE_INSENSITIVE) 2184 state = GTK_STATE_NORMAL; 2185 2186 drawLayout(cr, style, selectedText ? GTK_STATE_SELECTED : state, 2187 use_text || selectedText, area, x, y, layout); 2188 2189 if (opts.embolden && def_but) { 2190 drawLayout(cr, style, selectedText ? GTK_STATE_SELECTED : state, 2191 use_text || selectedText, area, x + 1, y, layout); 2192 } 2193 2194 if (swapColors) { 2195 for (int i = 0;i < 5;++i) { 2196 style->text[i] = prevColors[i]; 2197 } 2198 } 2199 } 2200 cairo_destroy(cr); 2201 } 2202 2203 static GdkPixbuf* 2204 gtkRenderIcon(GtkStyle *style, const GtkIconSource *source, 2205 GtkTextDirection, GtkStateType state, GtkIconSize size, 2206 GtkWidget *widget, const char*) 2207 { 2208 return renderIcon(style, source, state, size, widget); 2209 } 2210 2211 static void 2212 gtkDrawTab(GtkStyle*, GdkWindow *window, GtkStateType state, 2213 GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, 2214 const char *_detail, int x, int y, int width, int height) 2215 { 2216 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2217 if (qtSettings.debug == DEBUG_ALL) { 2218 printf(DEBUG_PREFIX "%s %d %d %s ", __FUNCTION__, state, shadow, 2219 _detail); 2220 debugDisplayWidget(widget, 10); 2221 } 2222 const QtcRect *area = (QtcRect*)_area; 2223 cairo_t *cr = gdk_cairo_create(window); 2224 const GdkColor *arrowColor = 2225 MO_ARROW(false, &qtSettings.colors[state == GTK_STATE_INSENSITIVE ? 2226 PAL_DISABLED : 2227 PAL_ACTIVE][COLOR_BUTTON_TEXT]); 2228 if (isActiveOptionMenu(widget)) { 2229 x++; 2230 y++; 2231 } 2232 x = (reverseLayout(widget) || 2233 ((widget = gtk_widget_get_parent(widget)) && reverseLayout(widget)) ? 2234 x + 1 : x + width / 2); 2235 if (opts.doubleGtkComboArrow) { 2236 int pad = opts.vArrows ? 0 : 1; 2237 Cairo::arrow(cr, arrowColor, area, GTK_ARROW_UP, 2238 x, y + height / 2 - (LARGE_ARR_HEIGHT - pad), 2239 false, true, opts.vArrows); 2240 Cairo::arrow(cr, arrowColor, area, GTK_ARROW_DOWN, 2241 x, y + height / 2 + (LARGE_ARR_HEIGHT - pad), 2242 false, true, opts.vArrows); 2243 } else { 2244 Cairo::arrow(cr, arrowColor, area, GTK_ARROW_DOWN, 2245 x, y + height / 2, false, true, opts.vArrows); 2246 } 2247 cairo_destroy(cr); 2248 } 2249 2250 static void 2251 gtkDrawBoxGap(GtkStyle *style, GdkWindow *window, GtkStateType state, 2252 GtkShadowType, GdkRectangle *area, GtkWidget *widget, 2253 const char *_detail, int x, int y, int width, int height, 2254 GtkPositionType gapSide, int gapX, int gapWidth) 2255 { 2256 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 2257 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2258 const char *detail = _detail ? _detail : ""; 2259 cairo_t *cr = Cairo::gdkCreateClip(window, area); 2260 2261 if ((opts.thin & THIN_FRAMES) && gapX == 0) { 2262 gapX--; 2263 gapWidth += 2; 2264 } 2265 2266 sanitizeSize(window, &width, &height); 2267 drawBoxGap(cr, style, GTK_SHADOW_OUT, state, widget, (QtcRect*)area, x, y, 2268 width, height, gapSide, gapX, gapWidth, 2269 opts.borderTab ? BORDER_LIGHT : BORDER_RAISED, true); 2270 2271 if (opts.windowDrag > WM_DRAG_MENU_AND_TOOLBAR && oneOf(detail, "notebook")) { 2272 WMMove::setup(widget); 2273 } 2274 2275 if (!isMozilla()) 2276 drawBoxGapFixes(cr, widget, x, y, width, height, 2277 gapSide, gapX, gapWidth); 2278 cairo_destroy(cr); 2279 } 2280 2281 static void 2282 gtkDrawExtension(GtkStyle *style, GdkWindow *window, GtkStateType state, 2283 GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, 2284 const char *_detail, int x, int y, int width, int height, 2285 GtkPositionType gapSide) 2286 { 2287 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 2288 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2289 const char *detail = _detail ? _detail : ""; 2290 if (qtSettings.debug == DEBUG_ALL) { 2291 printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %d %s ", __FUNCTION__, state, 2292 shadow, gapSide, x, y, width, height, _detail); 2293 debugDisplayWidget(widget, 10); 2294 } 2295 sanitizeSize(window, &width, &height); 2296 2297 if (oneOf(detail, "tab")) { 2298 QtcRect *area = (QtcRect*)_area; 2299 cairo_t *cr = Cairo::gdkCreateClip(window, area); 2300 drawTab(cr, state, style, widget, area, x, y, width, height, gapSide); 2301 cairo_destroy(cr); 2302 } else { 2303 parent_class->draw_extension(style, window, state, shadow, _area, 2304 widget, _detail, x, y, width, height, 2305 gapSide); 2306 } 2307 } 2308 2309 static void 2310 gtkDrawSlider(GtkStyle *style, GdkWindow *window, GtkStateType state, 2311 GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, 2312 const char *_detail, int x, int y, int width, int height, 2313 GtkOrientation orientation) 2314 { 2315 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 2316 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2317 const char *detail = _detail ? _detail : ""; 2318 bool scrollbar = oneOf(detail, "slider"); 2319 bool scale = oneOf(detail, "hscale", "vscale"); 2320 2321 if (qtSettings.debug == DEBUG_ALL) { 2322 printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %s ", __FUNCTION__, state, 2323 shadow, x, y, width, height, _detail); 2324 debugDisplayWidget(widget, 10); 2325 } 2326 2327 cairo_t *cr = Cairo::gdkCreateClip(window, area); 2328 sanitizeSize(window, &width, &height); 2329 2330 if (scrollbar || SLIDER_TRIANGULAR!=opts.sliderStyle) { 2331 GdkColor newColors[TOTAL_SHADES + 1]; 2332 GdkColor *btnColors = qtcPalette.background; 2333 int min = MIN_SLIDER_SIZE(opts.sliderThumbs); 2334 2335 #ifdef INCREASE_SB_SLIDER 2336 if (scrollbar) 2337 lastSlider.widget = nullptr; 2338 #endif 2339 /* Fix Java swing sliders looking pressed */ 2340 if(!scrollbar && GTK_STATE_ACTIVE==state) 2341 state=GTK_STATE_PRELIGHT; 2342 2343 // FIXME, need to update useButtonColor if the logic below changes 2344 if (useButtonColor(detail)) { 2345 if(scrollbar|scale && GTK_STATE_INSENSITIVE==state) 2346 btnColors=qtcPalette.background; 2347 else if(QT_CUSTOM_COLOR_BUTTON(style)) 2348 { 2349 shadeColors(&style->bg[state], newColors); 2350 btnColors=newColors; 2351 } 2352 else 2353 SET_BTN_COLS(scrollbar, scale, false, state) 2354 } 2355 2356 #ifdef INCREASE_SB_SLIDER 2357 if(scrollbar && !opts.flatSbarButtons && SHADE_NONE!=opts.shadeSliders && SCROLLBAR_NONE!=opts.scrollbarType && !isMozilla()) 2358 { 2359 lastSlider.style=style; 2360 #if GTK_CHECK_VERSION(2, 90, 0) 2361 lastSlider.cr=cr; 2362 #else 2363 lastSlider.window=window; 2364 #endif 2365 lastSlider.state=state; 2366 lastSlider.shadow=shadow; 2367 lastSlider.widget=widget; 2368 lastSlider.detail=detail; 2369 lastSlider.x=x; 2370 lastSlider.y=y; 2371 lastSlider.width=width; 2372 lastSlider.height=height; 2373 lastSlider.orientation=orientation; 2374 } 2375 #endif 2376 2377 #if GTK_CHECK_VERSION(2, 90, 0) 2378 if(scrollbar && GTK_STATE_ACTIVE==state) 2379 state=GTK_STATE_PRELIGHT; 2380 #endif 2381 2382 drawBox(style, window, state, shadow, area, widget, 2383 !scrollbar ? "qtc-slider" : "slider", 2384 x, y, width, height, false); 2385 2386 /* Orientation is always vertical with Mozilla, why? Anyway this hack 2387 should be OK - as we only draw dashes when slider is larger than 2388 'min' pixels... */ 2389 orientation = (width < height ? GTK_ORIENTATION_VERTICAL : 2390 GTK_ORIENTATION_HORIZONTAL); 2391 if (opts.sliderThumbs != LINE_NONE && 2392 (scrollbar || opts.sliderStyle != SLIDER_CIRCULAR) && 2393 (scale || ((orientation == GTK_ORIENTATION_HORIZONTAL && 2394 width >= min) || height >= min))) { 2395 GdkColor *markers=/*opts.coloredMouseOver && GTK_STATE_PRELIGHT==state 2396 ? qtcPalette.mouseover 2397 : */btnColors; 2398 bool horiz = orientation == GTK_ORIENTATION_HORIZONTAL; 2399 2400 if (opts.sliderThumbs == LINE_SUNKEN) { 2401 if (horiz) { 2402 y--; 2403 height++; 2404 } else { 2405 x--; 2406 width++; 2407 } 2408 } else if (horiz) { 2409 x++; 2410 } else { 2411 y++; 2412 } 2413 2414 switch (opts.sliderThumbs) { 2415 case LINE_1DOT: 2416 Cairo::dot(cr, x, y, width, height, 2417 &markers[QTC_STD_BORDER]); 2418 break; 2419 case LINE_FLAT: 2420 drawLines(cr, x, y, width, height, !horiz, 3, 5, markers, 2421 (QtcRect*)area, 5, opts.sliderThumbs); 2422 break; 2423 case LINE_SUNKEN: 2424 drawLines(cr, x, y, width, height, !horiz, 4, 3, markers, 2425 (QtcRect*)area, 3, opts.sliderThumbs); 2426 break; 2427 default: 2428 case LINE_DOTS: 2429 Cairo::dots(cr, x, y, width, height, !horiz, 2430 scale ? 3 : 5, scale ? 4 : 2, (QtcRect*)area, 2431 0, &markers[5], markers); 2432 } 2433 } 2434 } else { 2435 drawTriangularSlider(cr, style, state, detail, x, y, width, height); 2436 } 2437 cairo_destroy(cr); 2438 } 2439 2440 static void 2441 gtkDrawShadowGap(GtkStyle *style, GdkWindow *window, GtkStateType state, 2442 GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, 2443 const char*, int x, int y, int width, int height, 2444 GtkPositionType gapSide, int gapX, int gapWidth) 2445 { 2446 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 2447 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2448 QtcRect *area = (QtcRect*)_area; 2449 cairo_t *cr = Cairo::gdkCreateClip(window, area); 2450 sanitizeSize(window, &width, &height); 2451 drawShadowGap(cr, style, shadow, state, widget, area, x, y, 2452 width, height, gapSide, gapX, gapWidth); 2453 cairo_destroy(cr); 2454 } 2455 2456 static void 2457 gtkDrawHLine(GtkStyle *style, GdkWindow *window, GtkStateType state, 2458 GdkRectangle *area, GtkWidget *widget, const char *_detail, 2459 int x1, int x2, int y) 2460 { 2461 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 2462 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2463 const char *detail = _detail ? _detail : ""; 2464 bool tbar = strcmp(detail, "toolbar"); 2465 int light = 0; 2466 int dark = tbar ? (opts.toolbarSeparators == LINE_FLAT ? 4 : 3) : 5; 2467 2468 if (qtSettings.debug == DEBUG_ALL) { 2469 printf(DEBUG_PREFIX "%s %d %d %d %d %s ", __FUNCTION__, state, x1, x2, 2470 y, _detail); 2471 debugDisplayWidget(widget, 10); 2472 } 2473 2474 cairo_t *cr = Cairo::gdkCreateClip(window, area); 2475 2476 if (tbar) { 2477 switch (opts.toolbarSeparators) { 2478 default: 2479 case LINE_DOTS: 2480 Cairo::dots(cr, x1, y, x2 - x1, 2, false, 2481 (x2 - x1) / 3.0 + 0.5, 0, (QtcRect*)area, 0, 2482 &qtcPalette.background[5], qtcPalette.background); 2483 break; 2484 case LINE_NONE: 2485 break; 2486 case LINE_FLAT: 2487 case LINE_SUNKEN: 2488 { 2489 drawFadedLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), 1, 2490 &qtcPalette.background[dark], (QtcRect*)area, 2491 nullptr, true, true, true); 2492 /* Cairo::hLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), */ 2493 /* &qtcPalette.background[dark]); */ 2494 if(LINE_SUNKEN==opts.toolbarSeparators) 2495 { 2496 cairo_new_path(cr); 2497 /* Cairo::hLine(cr, x1 < x2 ? x1 : x2, y + 1, abs(x2 - x1), */ 2498 /* &qtcPalette.background[light]); */ 2499 drawFadedLine(cr, x1 < x2 ? x1 : x2, y + 1, abs(x2 - x1), 1, 2500 &qtcPalette.background[light], (QtcRect*)area, 2501 nullptr, true, true, true); 2502 } 2503 } 2504 } 2505 } else if (oneOf(detail, "label")) { 2506 if (state == GTK_STATE_INSENSITIVE) { 2507 /* Cairo::hLine(cr, (x1 < x2 ? x1 : x2) + 1, y + 1, abs(x2 - x1), */ 2508 /* &qtcPalette.background[light]); */ 2509 drawFadedLine(cr, x1 < x2 ? x1 : x2, y + 1, abs(x2 - x1), 1, 2510 &qtcPalette.background[light], (QtcRect*)area, nullptr, 2511 true, true, true); 2512 } 2513 /* Cairo::hLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), */ 2514 /* &style->text[state]); */ 2515 drawFadedLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), 1, 2516 &qtcPalette.background[dark], (QtcRect*)area, nullptr, 2517 true, true, true); 2518 } else if (oneOf(detail, "menuitem") || 2519 (widget && oneOf(detail, "hseparator") && isMenuitem(widget))) { 2520 int offset=opts.menuStripe && (isMozilla() || (widget && GTK_IS_MENU_ITEM(widget))) ? 20 : 0; 2521 GdkColor *cols=qtcPalette.background; 2522 2523 if(offset && isFakeGtk()) 2524 offset+=2; 2525 2526 if (opts.lighterPopupMenuBgnd || opts.shadePopupMenu) { 2527 cols = qtcPalette.menu; 2528 } 2529 if (offset && isFakeGtk()) { 2530 offset += 2; 2531 } 2532 2533 /* Cairo::hLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), */ 2534 /* &qtcPalette.background[MENU_SEP_SHADE]); */ 2535 drawFadedLine(cr, offset + (x1 < x2 ? x1 : x2), y + 1, 2536 abs(x2 - x1) - offset, 1, &cols[MENU_SEP_SHADE], 2537 (QtcRect*)area, nullptr, true, true, true); 2538 } else { 2539 /* Cairo::hLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), */ 2540 /* qtcPalette.background[dark]); */ 2541 drawFadedLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), 1, 2542 &qtcPalette.background[dark], (QtcRect*)area, nullptr, 2543 true, true, true); 2544 } 2545 2546 cairo_destroy(cr); 2547 } 2548 2549 static void 2550 gtkDrawVLine(GtkStyle *style, GdkWindow *window, GtkStateType state, 2551 GdkRectangle *area, GtkWidget *widget, const char *_detail, 2552 int y1, int y2, int x) 2553 { 2554 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 2555 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2556 const char *detail = _detail ? _detail : ""; 2557 2558 if (qtSettings.debug == DEBUG_ALL) { 2559 printf(DEBUG_PREFIX "%s %d %d %d %d %s ", __FUNCTION__, state, x, y1, 2560 y2, _detail); 2561 debugDisplayWidget(widget, 10); 2562 } 2563 2564 cairo_t *cr = Cairo::gdkCreateClip(window, area); 2565 2566 if (!(oneOf(detail, "vseparator") && isOnComboBox(widget, 0))) { 2567 /* CPD: Combo handled in drawBox */ 2568 bool tbar = oneOf(detail, "toolbar"); 2569 int dark = tbar ? 3 : 5; 2570 int light = 0; 2571 2572 if (tbar) { 2573 switch (opts.toolbarSeparators) { 2574 default: 2575 case LINE_DOTS: 2576 Cairo::dots(cr, x, y1, 2, y2 - y1, true, 2577 (y2 - y1) / 3.0 + 0.5, 0, (QtcRect*)area, 0, 2578 &qtcPalette.background[5], 2579 qtcPalette.background); 2580 break; 2581 case LINE_NONE: 2582 break; 2583 case LINE_FLAT: 2584 case LINE_SUNKEN: 2585 /* Cairo::vLine(cr, x, y1 < y2 ? y1 : y2, abs(y2 - y1), */ 2586 /* &qtcPalette.background[dark]); */ 2587 drawFadedLine(cr, x, y1 < y2 ? y1 : y2, 1, abs(y2 - y1), 2588 &qtcPalette.background[dark], 2589 (QtcRect*)area, nullptr, true, true, false); 2590 if (opts.toolbarSeparators == LINE_SUNKEN) 2591 /* Cairo::vLine(cr, x + 1, y1 < y2 ? y1 : y2, */ 2592 /* abs(y2 - y1), */ 2593 /* &qtcPalette.background[light]); */ 2594 drawFadedLine(cr, x + 1, y1 < y2 ? y1 : y2, 1, 2595 abs(y2 - y1), &qtcPalette.background[light], 2596 (QtcRect*)area, nullptr, true, true, false); 2597 } 2598 } else { 2599 /* Cairo::vLine(cr, x, y1 < y2 ? y1 : y2, abs(y2 - y1), */ 2600 /* &qtcPalette.background[dark]); */ 2601 drawFadedLine(cr, x, y1 < y2 ? y1 : y2, 1, abs(y2 - y1), 2602 &qtcPalette.background[dark], (QtcRect*)area, 2603 nullptr, true, true, false); 2604 } 2605 } 2606 cairo_destroy(cr); 2607 } 2608 2609 static void 2610 gtkDrawFocus(GtkStyle *style, GdkWindow *window, GtkStateType state, 2611 GdkRectangle *area, GtkWidget *widget, const char *_detail, 2612 int x, int y, int width, int height) 2613 { 2614 if (opts.focus == FOCUS_NONE) { 2615 return; 2616 } 2617 if (GTK_IS_EDITABLE(widget)) 2618 return; 2619 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2620 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 2621 2622 sanitizeSize(window, &width, &height); 2623 2624 if (qtSettings.debug == DEBUG_ALL) { 2625 printf(DEBUG_PREFIX "%s %d %d %d %d %d %s ", __FUNCTION__, state, x, y, 2626 width, height, _detail); 2627 debugDisplayWidget(widget, 10); 2628 } 2629 GtkWidget *parent = widget ? gtk_widget_get_parent(widget) : nullptr; 2630 bool doEtch = opts.buttonEffect != EFFECT_NONE; 2631 bool btn = false; 2632 bool comboButton = false; 2633 bool rev = parent && reverseLayout(parent); 2634 bool view = isList(widget); 2635 bool listViewHeader = isListViewHeader(widget); 2636 bool toolbarBtn = (!listViewHeader && !view && 2637 isButtonOnToolbar(widget, nullptr)); 2638 2639 if (opts.comboSplitter && 2640 noneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED) && isComboBox(widget)) { 2641 /* x++; */ 2642 /* y++; */ 2643 /* height -= 2; */ 2644 width += 2; /* Remove if re-add the above */ 2645 2646 if (widget && rev) { 2647 x += 20; 2648 } 2649 width -= 22; 2650 2651 if (isGimpCombo(widget)) { 2652 x += 2; 2653 y += 2; 2654 width -= 4; 2655 height -= 4; 2656 } 2657 btn = true; 2658 } 2659 #if !GTK_CHECK_VERSION(2, 90, 0) 2660 else if (GTK_IS_OPTION_MENU(widget)) { 2661 if ((!opts.comboSplitter || 2662 oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)) && widget) { 2663 QtcRect alloc = Widget::getAllocation(widget); 2664 if (alloc.width > width) { 2665 width = alloc.width - (doEtch ? 8 : 4); 2666 } 2667 } 2668 x++; 2669 y++; 2670 width -= 2; 2671 height -= 2; 2672 btn = true; 2673 } 2674 #endif 2675 if (isComboBoxEntryButton(widget)) { 2676 #if GTK_CHECK_VERSION(2, 90, 0) 2677 if (doEtch) { 2678 x -= 2; 2679 y++; 2680 width += 3; 2681 height -= 2; 2682 } else { 2683 x -= 2; 2684 width += 4; 2685 } 2686 #else 2687 if (doEtch) { 2688 x++; 2689 y += 2; 2690 width -= 3; 2691 height -= 4; 2692 } else { 2693 x++; 2694 y++; 2695 width -= 2; 2696 height -= 2; 2697 } 2698 #endif 2699 comboButton = true; 2700 btn = true; 2701 } else if (isGimpCombo(widget)) { 2702 if (opts.focus == FOCUS_GLOW) { 2703 return; 2704 } 2705 x -= 2; 2706 width += 4; 2707 if (!doEtch) { 2708 x--; 2709 y--; 2710 width += 2; 2711 height += 2; 2712 } 2713 } else if (GTK_IS_BUTTON(widget)) { 2714 if (GTK_IS_RADIO_BUTTON(widget) || GTK_IS_CHECK_BUTTON(widget)) { 2715 // Gimps buttons in its toolbox are 2716 const char *text = nullptr; 2717 toolbarBtn = (qtSettings.app == GTK_APP_GIMP && 2718 ((text = 2719 gtk_button_get_label(GTK_BUTTON(widget))) == nullptr || 2720 text[0] == '\0')); 2721 2722 if (!toolbarBtn && opts.focus == FOCUS_GLOW && !isMozilla()) { 2723 return; 2724 } 2725 2726 if (toolbarBtn) { 2727 if (qtSettings.app == GTK_APP_GIMP && 2728 opts.focus == FOCUS_GLOW && toolbarBtn) { 2729 x -= 2; 2730 width += 4; 2731 y -= 1; 2732 height += 2; 2733 } 2734 } 2735 #if 0 /* Removed in 1.7.2 */ 2736 else { 2737 if (opts.focus == FOCUS_LINE) { 2738 height--; 2739 } else if (oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)) { 2740 y--; 2741 x -= 3; 2742 width += 6; 2743 height += 2; 2744 if (!doEtch) { 2745 y--; 2746 x--; 2747 width += 2; 2748 height += 2; 2749 } 2750 } 2751 } 2752 #endif 2753 } else if (opts.focus == FOCUS_GLOW && toolbarBtn) { 2754 x -= 2; 2755 width += 4; 2756 y -= 2; 2757 height += 4; 2758 } else { 2759 if (doEtch) { 2760 x--; 2761 width += 2; 2762 } else { 2763 x -= 2; 2764 width += 4; 2765 } 2766 if (doEtch && (opts.thin & THIN_BUTTONS)) { 2767 y++; 2768 height -= 2; 2769 } 2770 btn = true; 2771 } 2772 } 2773 if (state == GTK_STATE_PRELIGHT && opts.coloredMouseOver != MO_NONE && 2774 oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED) && !listViewHeader && 2775 (btn || comboButton)) { 2776 return; 2777 } 2778 if (opts.focus == FOCUS_GLOW && !comboButton && !listViewHeader && 2779 !toolbarBtn && (btn || GTK_IS_SCALE(widget))) { 2780 return; 2781 } 2782 if (opts.focus == FOCUS_GLOW && toolbarBtn && state != GTK_STATE_NORMAL) { 2783 return; 2784 } 2785 if (opts.focus == FOCUS_STANDARD) { 2786 parent_class->draw_focus(style, window, state, area, widget, _detail, 2787 x, y, width, height); 2788 } else { 2789 bool drawRounded = (opts.round != ROUND_NONE); 2790 GdkColor *col = 2791 (view && state == GTK_STATE_SELECTED ? &style->text[state] : 2792 &qtcPalette.focus[FOCUS_SHADE(state == GTK_STATE_SELECTED)]); 2793 2794 cairo_t *cr = Cairo::gdkCreateClip(window, area); 2795 2796 if (qtSettings.app == GTK_APP_JAVA_SWT && view && widget && 2797 GTK_IS_TREE_VIEW(widget)) { 2798 GtkTreeView *treeView = GTK_TREE_VIEW(widget); 2799 GtkTreePath *path = nullptr; 2800 GtkTreeViewColumn *column = nullptr; 2801 GtkTreeViewColumn *expanderColumn = 2802 gtk_tree_view_get_expander_column(treeView); 2803 2804 TreeView::getCell(treeView, &path, &column, x, y, width, height); 2805 if (column == expanderColumn) { 2806 int expanderSize = 0; 2807 gtk_widget_style_get(widget, "expander-size", 2808 &expanderSize, nullptr); 2809 if (expanderSize > 0) { 2810 int depth = path ? (int)gtk_tree_path_get_depth(path) : 0; 2811 int offset = 2812 (3 + expanderSize * depth + 2813 (4 + gtk_tree_view_get_level_indentation(treeView)) * 2814 (depth - 1)); 2815 x += offset; 2816 width -= offset; 2817 } 2818 } 2819 2820 if (path) { 2821 gtk_tree_path_free(path); 2822 } 2823 } 2824 2825 if (oneOf(opts.focus, FOCUS_LINE, FOCUS_GLOW)) { 2826 if (view || listViewHeader) { 2827 height -= 2; 2828 } 2829 drawFadedLine(cr, x, y + height - 1, width, 1, col, 2830 (QtcRect*)area, nullptr, true, true, true); 2831 } else { 2832 /* double alpha = (opts.focus == FOCUS_GLOW ? */ 2833 /* FOCUS_GLOW_LINE_ALPHA : 1.0); */ 2834 2835 if (width < 3 || height < 3) { 2836 drawRounded = false; 2837 } 2838 cairo_new_path(cr); 2839 2840 if (isListViewHeader(widget)) { 2841 btn = false; 2842 y++; 2843 x++; 2844 width -= 2; 2845 height -= 3; 2846 } 2847 if (oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)) { 2848 if (btn) { 2849 if (toolbarBtn) { 2850 x -= 2; 2851 y -= 2; 2852 width += 4; 2853 height += 4; 2854 if (!doEtch) { 2855 x -= 2; 2856 width += 4; 2857 y--; 2858 height += 2; 2859 } 2860 } else if (!widget || !(GTK_IS_RADIO_BUTTON(widget) || 2861 GTK_IS_CHECK_BUTTON(widget))) { 2862 /* 1.7.2 - dont asjust fot check/radio */ 2863 x -= 3; 2864 y -= 3; 2865 width += 6; 2866 height += 6; 2867 } 2868 } 2869 2870 if (opts.focus == FOCUS_FILLED) { 2871 if (drawRounded) { 2872 Cairo::pathWhole(cr, x + 0.5, y + 0.5, width - 1, 2873 height - 1, 2874 qtcGetRadius(&opts, width, height, 2875 WIDGET_OTHER, 2876 RADIUS_EXTERNAL), 2877 comboButton ? 2878 (rev ? ROUNDED_LEFT : ROUNDED_RIGHT) : 2879 ROUNDED_ALL); 2880 } else { 2881 cairo_rectangle(cr, x + 0.5, y + 0.5, 2882 width - 1, height - 1); 2883 } 2884 Cairo::setColor(cr, col, FOCUS_ALPHA); 2885 cairo_fill(cr); 2886 cairo_new_path(cr); 2887 } 2888 } 2889 if (drawRounded) { 2890 Cairo::pathWhole(cr, x + 0.5, y + 0.5, width - 1, height - 1, 2891 (view && 2892 opts.square & SQUARE_LISTVIEW_SELECTION) && 2893 opts.round != ROUND_NONE ? SLIGHT_INNER_RADIUS : 2894 qtcGetRadius(&opts, width, height, WIDGET_OTHER, 2895 oneOf(opts.focus, FOCUS_FULL, 2896 FOCUS_FILLED) ? 2897 RADIUS_EXTERNAL : 2898 RADIUS_SELECTION), 2899 oneOf(opts.focus, FOCUS_FULL, 2900 FOCUS_FILLED) && comboButton ? 2901 (rev ? ROUNDED_LEFT : ROUNDED_RIGHT) : 2902 ROUNDED_ALL); 2903 } else { 2904 cairo_rectangle(cr, x+0.5, y+0.5, width-1, height-1); 2905 } 2906 /* Cairo::setColor(cr, col, alpha); */ 2907 Cairo::setColor(cr, col); 2908 cairo_stroke(cr); 2909 } 2910 cairo_destroy(cr); 2911 } 2912 } 2913 2914 static void 2915 gtkDrawResizeGrip(GtkStyle *style, GdkWindow *window, GtkStateType state, 2916 GdkRectangle *_area, GtkWidget *widget, const char *_detail, 2917 GdkWindowEdge edge, int x, int y, int width, int height) 2918 { 2919 QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); 2920 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2921 QtcRect *area = (QtcRect*)_area; 2922 cairo_t *cr = Cairo::gdkCreateClip(window, area); 2923 int size = SIZE_GRIP_SIZE - 2; 2924 2925 /* Clear background */ 2926 if (qtcIsFlatBgnd(opts.bgndAppearance) || 2927 !(widget && drawWindowBgnd(cr, style, area, window, widget, 2928 x, y, width, height))) { 2929 if (widget && opts.bgndImage.type != IMG_NONE) { 2930 drawWindowBgnd(cr, style, area, window, widget, 2931 x, y, width, height); 2932 } 2933 } 2934 2935 switch (edge) { 2936 case GDK_WINDOW_EDGE_SOUTH_EAST: { 2937 // Adjust Firefox's resize grip so that it can be completely covered 2938 // by QtCurve's KWin resize grip. 2939 if (isMozilla()) { 2940 x++; 2941 y++; 2942 } 2943 const GdkPoint a[] = {{x + width, y + height - size}, 2944 {x + width, y + height}, 2945 {x + width - size, y + height}}; 2946 Cairo::polygon(cr, &qtcPalette.background[2], area, a, 3, true); 2947 break; 2948 } 2949 case GDK_WINDOW_EDGE_SOUTH_WEST: { 2950 const GdkPoint a[] = {{x + width - size, y + height - size}, 2951 {x + width, y + height}, 2952 {x + width - size, y + height}}; 2953 Cairo::polygon(cr, &qtcPalette.background[2], area, a, 3, true); 2954 break; 2955 } 2956 case GDK_WINDOW_EDGE_NORTH_EAST: 2957 // TODO!! 2958 case GDK_WINDOW_EDGE_NORTH_WEST: 2959 // TODO!! 2960 default: 2961 parent_class->draw_resize_grip(style, window, state, _area, widget, 2962 _detail, edge, x, y, width, height); 2963 } 2964 cairo_destroy(cr); 2965 } 2966 2967 static void 2968 gtkDrawExpander(GtkStyle *style, GdkWindow *window, GtkStateType state, 2969 GdkRectangle *_area, GtkWidget *widget, const char *_detail, 2970 int x, int y, GtkExpanderStyle expander_style) 2971 { 2972 QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); 2973 if (qtSettings.debug == DEBUG_ALL) { 2974 printf(DEBUG_PREFIX "%s %d %s ", __FUNCTION__, state, _detail); 2975 debugDisplayWidget(widget, 10); 2976 } 2977 QtcRect *area = (QtcRect*)_area; 2978 cairo_t *cr = gdk_cairo_create(window); 2979 bool isExpander = widget && (GTK_IS_EXPANDER(widget) || 2980 GTK_IS_TREE_VIEW(widget)); 2981 bool fill = (!isExpander || opts.coloredMouseOver || 2982 state != GTK_STATE_PRELIGHT); 2983 const GdkColor *col = (isExpander && opts.coloredMouseOver && 2984 state == GTK_STATE_PRELIGHT ? 2985 &qtcPalette.mouseover[ARROW_MO_SHADE] : 2986 &style->text[ARROW_STATE(state)]); 2987 2988 x -= LV_SIZE / 2.0 + 0.5; 2989 x += 2; 2990 y -= LV_SIZE / 2.0 + 0.5; 2991 2992 if (expander_style == GTK_EXPANDER_COLLAPSED) { 2993 Cairo::arrow(cr, col, area, 2994 reverseLayout(widget) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT, 2995 x + LARGE_ARR_WIDTH / 2, y + LARGE_ARR_HEIGHT, 2996 false, fill, opts.vArrows); 2997 } else { 2998 Cairo::arrow(cr, col, area, GTK_ARROW_DOWN, x + LARGE_ARR_WIDTH / 2, 2999 y + LARGE_ARR_HEIGHT, false, fill, opts.vArrows); 3000 } 3001 cairo_destroy(cr); 3002 } 3003 3004 static void 3005 styleRealize(GtkStyle *style) 3006 { 3007 Style *qtc_style = (Style*)style; 3008 3009 parent_class->realize(style); 3010 3011 qtc_style->button_text[PAL_ACTIVE] = 3012 &qtSettings.colors[PAL_ACTIVE][COLOR_BUTTON_TEXT]; 3013 qtc_style->button_text[PAL_DISABLED] = 3014 (qtSettings.qt4 ? &qtSettings.colors[PAL_DISABLED][COLOR_BUTTON_TEXT] : 3015 &style->text[GTK_STATE_INSENSITIVE]); 3016 3017 if (opts.shadeMenubars == SHADE_WINDOW_BORDER) { 3018 qtc_style->menutext[0] = 3019 &qtSettings.colors[PAL_INACTIVE][COLOR_WINDOW_BORDER_TEXT]; 3020 qtc_style->menutext[1] = 3021 &qtSettings.colors[PAL_ACTIVE][COLOR_WINDOW_BORDER_TEXT]; 3022 } else if (opts.customMenuTextColor) { 3023 qtc_style->menutext[0] = &opts.customMenuNormTextColor; 3024 qtc_style->menutext[1] = &opts.customMenuSelTextColor; 3025 } else { 3026 qtc_style->menutext[0] = nullptr; 3027 } 3028 } 3029 3030 static void 3031 styleUnrealize(GtkStyle *style) 3032 { 3033 parent_class->unrealize(style); 3034 } 3035 3036 static void 3037 style_init_from_rc(GtkStyle *style, GtkRcStyle *rc_style) 3038 { 3039 parent_class->init_from_rc(style, rc_style); 3040 } 3041 3042 static void style_class_init(void *_klass, void*) 3043 { 3044 StyleClass *klass = (StyleClass*)_klass; 3045 GtkStyleClass *style_class = GTK_STYLE_CLASS(klass); 3046 3047 parent_class = (GtkStyleClass*)g_type_class_peek_parent(klass); 3048 3049 style_class->realize = styleRealize; 3050 style_class->unrealize = styleUnrealize; 3051 style_class->init_from_rc = style_init_from_rc; 3052 style_class->draw_resize_grip = gtkDrawResizeGrip; 3053 style_class->draw_expander = gtkDrawExpander; 3054 style_class->draw_arrow = gtkDrawArrow; 3055 style_class->draw_tab = gtkDrawTab; 3056 style_class->draw_shadow = gtkDrawShadow; 3057 style_class->draw_box_gap = gtkDrawBoxGap; 3058 style_class->draw_extension = gtkDrawExtension; 3059 style_class->draw_handle = gtkDrawHandle; 3060 style_class->draw_box = gtkDrawBox; 3061 style_class->draw_flat_box = gtkDrawFlatBox; 3062 style_class->draw_check = gtkDrawCheck; 3063 style_class->draw_slider = gtkDrawSlider; 3064 style_class->draw_option = gtkDrawOption; 3065 style_class->draw_shadow_gap = gtkDrawShadowGap; 3066 style_class->draw_hline = gtkDrawHLine; 3067 style_class->draw_vline = gtkDrawVLine; 3068 style_class->draw_focus = gtkDrawFocus; 3069 style_class->draw_layout = gtkDrawLayout; 3070 style_class->render_icon = gtkRenderIcon; 3071 } 3072 3073 static GtkRcStyleClass *parent_rc_class; 3074 3075 static unsigned 3076 rc_style_parse(GtkRcStyle*, GtkSettings*, GScanner *scanner) 3077 { 3078 unsigned old_scope; 3079 unsigned token; 3080 3081 /* Set up a new scope in this scanner. */ 3082 static GQuark scope_id = g_quark_from_string("qtcurve_theme_engine"); 3083 3084 /* If we bail out due to errors, we *don't* reset the scope, so the error 3085 messaging code can make sense of our tokens. */ 3086 old_scope = g_scanner_set_scope(scanner, scope_id); 3087 3088 token = g_scanner_peek_next_token(scanner); 3089 while (token != G_TOKEN_RIGHT_CURLY) { 3090 switch (token) { 3091 default: 3092 g_scanner_get_next_token(scanner); 3093 token = G_TOKEN_RIGHT_CURLY; 3094 } 3095 if (token != G_TOKEN_NONE) 3096 return token; 3097 token = g_scanner_peek_next_token(scanner); 3098 } 3099 3100 g_scanner_get_next_token(scanner); 3101 g_scanner_set_scope(scanner, old_scope); 3102 return G_TOKEN_NONE; 3103 } 3104 3105 static void 3106 rc_style_merge(GtkRcStyle *dest, GtkRcStyle *src) 3107 { 3108 3109 GtkRcStyle copy; 3110 bool destIsQtc = isRcStyle(dest); 3111 bool srcIsQtc = (!src->name || Str::startsWith(src->name, RC_SETTING) || 3112 Str::startsWith(src->name, getProgName())); 3113 bool isQtCNoteBook = (opts.tabBgnd != 0 && src->name && 3114 oneOf(src->name, "qtcurve-notebook_bg")); 3115 bool dontChangeColors = destIsQtc && !srcIsQtc && !isQtCNoteBook && 3116 // Only allow GtkRcStyle and QtCurve::RcStyle to change colours 3117 // ...this should catch most cases whre another themes gtkrc is in the 3118 // GTK2_RC_FILES path 3119 (noneOf(gTypeName(src), "GtkRcStyle", "QtCurveRcStyle") || 3120 // If run as root (probably via kdesu/kdesudo) then dont allow KDE 3121 // settings to take effect - as these are sometimes from the user's 3122 // settings, not roots! 3123 (getuid() == 0 && src && src->name && 3124 oneOf(src->name, "ToolTip", "default"))); 3125 3126 if (isQtCNoteBook) { 3127 qtcShade(&qtcPalette.background[ORIGINAL_SHADE], 3128 &src->bg[GTK_STATE_NORMAL], TO_FACTOR(opts.tabBgnd), 3129 opts.shading); 3130 } 3131 3132 if(dontChangeColors) 3133 { 3134 memcpy(copy.color_flags, dest->color_flags, sizeof(GtkRcFlags)*5); 3135 memcpy(copy.fg, dest->fg, sizeof(GdkColor)*5); 3136 memcpy(copy.bg, dest->bg, sizeof(GdkColor)*5); 3137 memcpy(copy.text, dest->text, sizeof(GdkColor)*5); 3138 memcpy(copy.base, dest->base, sizeof(GdkColor)*5); 3139 } 3140 3141 parent_rc_class->merge(dest, src); 3142 3143 if(dontChangeColors) 3144 { 3145 memcpy(dest->color_flags, copy.color_flags, sizeof(GtkRcFlags)*5); 3146 memcpy(dest->fg, copy.fg, sizeof(GdkColor)*5); 3147 memcpy(dest->bg, copy.bg, sizeof(GdkColor)*5); 3148 memcpy(dest->text, copy.text, sizeof(GdkColor)*5); 3149 memcpy(dest->base, copy.base, sizeof(GdkColor)*5); 3150 } 3151 } 3152 3153 /* Create an empty style suitable to this RC style */ 3154 static GtkStyle* 3155 rc_style_create_style(GtkRcStyle *rc_style) 3156 { 3157 GtkStyle *style = (GtkStyle*)g_object_new(style_type, nullptr); 3158 3159 qtSettingsSetColors(style, rc_style); 3160 return style; 3161 } 3162 3163 static void style_init(void*, void*) 3164 { 3165 Shadow::initialize(); 3166 } 3167 3168 static void 3169 style_register_type(GTypeModule *module) 3170 { 3171 static const GTypeInfo object_info = { 3172 sizeof(StyleClass), 3173 (GBaseInitFunc)nullptr, 3174 (GBaseFinalizeFunc)nullptr, 3175 (GClassInitFunc)style_class_init, 3176 nullptr, /* class_finalize */ 3177 nullptr, /* class_data */ 3178 sizeof(Style), 3179 0, /* n_preallocs */ 3180 (GInstanceInitFunc)style_init, 3181 nullptr 3182 }; 3183 3184 style_type = g_type_module_register_type(module, GTK_TYPE_STYLE, 3185 "QtCurveStyle", &object_info, 3186 GTypeFlags(0)); 3187 } 3188 3189 static gboolean 3190 style_set_hook(GSignalInvocationHint*, unsigned, const GValue *argv, void*) 3191 { 3192 GtkWidget *widget = GTK_WIDGET(g_value_get_object(argv)); 3193 GdkScreen *screen = gtk_widget_get_screen(widget); 3194 if (!screen) { 3195 return true; 3196 } 3197 #if GTK_CHECK_VERSION(3, 0, 0) 3198 GdkVisual *visual = nullptr; 3199 if (gtk_widget_is_toplevel(widget)) { 3200 visual = gdk_screen_get_rgba_visual(screen); 3201 } else if (GTK_IS_DRAWING_AREA(widget)) { 3202 visual = gdk_screen_get_system_visual(screen); 3203 } 3204 if (visual) { 3205 gtk_widget_set_visual(widget, visual); 3206 } 3207 #else 3208 GdkColormap *colormap = nullptr; 3209 if (gtk_widget_is_toplevel(widget)) { 3210 colormap = gdk_screen_get_rgba_colormap(screen); 3211 } else if (GTK_IS_DRAWING_AREA(widget)) { 3212 // For inkscape and flash (and probably others). 3213 // Inkscape's (at least the Gtk2 version) EekPreview widget 3214 // uses system default colormap instead of the one for the widget. 3215 // Not sure what's wrong with flash... 3216 colormap = gdk_screen_get_default_colormap(screen); 3217 } 3218 if (colormap) { 3219 gtk_widget_set_colormap(widget, colormap); 3220 } 3221 #endif 3222 return true; 3223 } 3224 3225 static void 3226 rc_style_init(void*, void*s) 3227 { 3228 #ifdef INCREASE_SB_SLIDER 3229 lastSlider.widget = nullptr; 3230 #endif 3231 if (qtSettingsInit()) { 3232 generateColors(); 3233 if (qtSettings.useAlpha) { 3234 // Somehow GtkWidget is not loaded yet 3235 // when this function is called. 3236 g_type_class_ref(GTK_TYPE_WIDGET); 3237 g_signal_add_emission_hook( 3238 g_signal_lookup("style-set", GTK_TYPE_WIDGET), 3239 0, style_set_hook, nullptr, nullptr); 3240 } 3241 } 3242 } 3243 3244 static void 3245 rc_style_finalize(GObject *object) 3246 { 3247 Animation::cleanup(); 3248 qtcCall(G_OBJECT_CLASS(parent_rc_class)->finalize, object); 3249 } 3250 3251 static void 3252 rc_style_class_init(void *_klass, void*) 3253 { 3254 RcStyleClass *klass = (RcStyleClass*)_klass; 3255 GtkRcStyleClass *rc_style_class = GTK_RC_STYLE_CLASS(klass); 3256 GObjectClass *object_class = G_OBJECT_CLASS(klass); 3257 3258 parent_rc_class = (GtkRcStyleClass*)g_type_class_peek_parent(klass); 3259 3260 rc_style_class->parse = rc_style_parse; 3261 rc_style_class->create_style = rc_style_create_style; 3262 rc_style_class->merge = rc_style_merge; 3263 3264 object_class->finalize = rc_style_finalize; 3265 } 3266 3267 static void 3268 rc_style_register_type(GTypeModule *module) 3269 { 3270 static const GTypeInfo object_info = { 3271 sizeof(RcStyleClass), 3272 nullptr, 3273 nullptr, 3274 (GClassInitFunc)rc_style_class_init, 3275 nullptr, /* class_finalize */ 3276 nullptr, /* class_data */ 3277 sizeof(RcStyle), 3278 0, /* n_preallocs */ 3279 (GInstanceInitFunc)rc_style_init, 3280 nullptr 3281 }; 3282 3283 rc_style_type = g_type_module_register_type(module, GTK_TYPE_RC_STYLE, 3284 "QtCurveRcStyle", &object_info, 3285 GTypeFlags(0)); 3286 } 3287 } 3288 3289 QTC_BEGIN_DECLS 3290 3291 QTC_EXPORT void 3292 theme_init(GTypeModule *module) 3293 { 3294 qtcX11InitXlib(GDK_DISPLAY_XDISPLAY(gdk_display_get_default())); 3295 QtCurve::rc_style_register_type(module); 3296 QtCurve::style_register_type(module); 3297 } 3298 3299 QTC_EXPORT void 3300 theme_exit() 3301 { 3302 } 3303 3304 QTC_EXPORT GtkRcStyle* 3305 theme_create_rc_style() 3306 { 3307 return GTK_RC_STYLE(g_object_new(QtCurve::rc_style_type, nullptr)); 3308 } 3309 3310 /* The following function will be called by GTK+ when the module is loaded and 3311 * checks to see if we are compatible with the version of GTK+ that loads us. 3312 */ 3313 QTC_EXPORT const char* 3314 g_module_check_init(GModule*) 3315 { 3316 return gtk_check_version(GTK_MAJOR_VERSION, GTK_MINOR_VERSION, 3317 GTK_MICRO_VERSION - GTK_INTERFACE_AGE); 3318 } 3319 3320 QTC_END_DECLS