diff --git a/gtk2/style/qtcurve.cpp b/gtk2/style/qtcurve.cpp index 0b479ef1..55e2b736 100644 --- a/gtk2/style/qtcurve.cpp +++ b/gtk2/style/qtcurve.cpp @@ -1,3320 +1,3320 @@ /***************************************************************************** * Copyright 2003 - 2010 Craig Drummond * * Copyright 2013 - 2015 Yichao Yu * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation; either version 2.1 of the * * License, or (at your option) version 3, or any later version accepted * * by the membership of KDE e.V. (or its successor approved by the * * membership of KDE e.V.), which shall act as a proxy defined in * * Section 6 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library. If not, * * see . * *****************************************************************************/ #include "config.h" #include #include #include #include #include #include #include #include #include #include "compatability.h" #include #define MO_ARROW(MENU, COL) \ (!MENU && MO_NONE != opts.coloredMouseOver && \ GTK_STATE_PRELIGHT == state ? \ &qtcPalette.mouseover[ARROW_MO_SHADE] : (COL)) #include "qt_settings.h" #include "animation.h" #include "menu.h" #include "tab.h" #include "widgetmap.h" #include "window.h" #include "entry.h" #include "treeview.h" #include "combobox.h" #include "scrolledwindow.h" #include "scrollbar.h" #include "wmmove.h" #include "helpers.h" #include "drawing.h" #include "pixcache.h" #include "shadowhelper.h" #include "config.h" namespace QtCurve { static GType style_type = 0; static GType rc_style_type = 0; struct StyleClass { GtkStyleClass parent_class; }; struct Style { GtkStyle parent_instance; GdkColor *button_text[2]; GdkColor *menutext[2]; }; struct RcStyleClass { GtkRcStyleClass parent_class; }; struct RcStyle { GtkRcStyle parent_instance; }; template static inline bool isRcStyle(T *object) { return G_TYPE_CHECK_INSTANCE_TYPE(object, rc_style_type); } static GtkStyleClass *parent_class = nullptr; #ifdef INCREASE_SB_SLIDER typedef struct { GtkStyle *style; #if GTK_CHECK_VERSION(2, 90, 0) cairo_t *cr; #else GdkWindow *window; #endif GtkStateType state; GtkShadowType shadow; GtkWidget *widget; const char *detail; int x; int y; int width; int height; GtkOrientation orientation; } QtCSlider; static QtCSlider lastSlider; #endif template static inline bool widgetIsType(Widget *widget, const char *name) { return oneOf(gTypeName(widget), name); } static void gtkDrawBox(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, const char *detail, int x, int y, int width, int height); static void gtkDrawSlider(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, const char *detail, int x, int y, int width, int height, GtkOrientation orientation); static void gtkLogHandler(const char*, GLogLevelFlags, const char*, void*) { } static void gtkDrawFlatBox(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; cairo_t *cr = Cairo::gdkCreateClip(window, area); bool isMenuOrToolTipWindow = (widget && GTK_IS_WINDOW(widget) && ((gtk_widget_get_name(widget) && strcmp(gtk_widget_get_name(widget), "gtk-tooltip") == 0) || isMenuWindow(widget))); if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %s ", __FUNCTION__, state, shadow, x, y, width, height, _detail); debugDisplayWidget(widget, 10); } sanitizeSize(window, &width, &height); if (!opts.gtkButtonOrder && opts.reorderGtkButtons && GTK_IS_WINDOW(widget) && oneOf(detail, "base")) { GtkWidget *topLevel = gtk_widget_get_toplevel(widget); GtkWidgetProps topProps(topLevel); if (topLevel && GTK_IS_DIALOG(topLevel) && !topProps->buttonOrderHacked) { // gtk_dialog_set_alternative_button_order will cause errors to be // logged, but dont want these so register our own error handler, // and then unregister afterwards... unsigned id = g_log_set_handler("Gtk", G_LOG_LEVEL_CRITICAL, gtkLogHandler, nullptr); topProps->buttonOrderHacked = true; gtk_dialog_set_alternative_button_order( GTK_DIALOG(topLevel), GTK_RESPONSE_HELP, GTK_RESPONSE_OK, GTK_RESPONSE_YES, GTK_RESPONSE_ACCEPT, GTK_RESPONSE_APPLY, GTK_RESPONSE_REJECT, GTK_RESPONSE_CLOSE, GTK_RESPONSE_NO, GTK_RESPONSE_CANCEL, -1); g_log_remove_handler("Gtk", id); } } if (opts.windowDrag > WM_DRAG_MENU_AND_TOOLBAR && oneOf(detail, "base", "eventbox", "viewportbin")) { WMMove::setup(widget); } if (widget && ((100!=opts.bgndOpacity && GTK_IS_WINDOW(widget)) || (100!=opts.dlgOpacity && GTK_IS_DIALOG(widget))) && !isFixedWidget(widget) && isRgbaWidget(widget)) { enableBlurBehind(widget, true); } if ((opts.menubarHiding || opts.statusbarHiding || BLEND_TITLEBAR || opts.windowBorder & WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR) && widget && GTK_IS_WINDOW(widget) && !isFixedWidget(widget) && !isGimpDockable(widget) && !isMenuOrToolTipWindow) { if (Window::setup(widget, GTK_IS_DIALOG(widget) ? opts.dlgOpacity : opts.bgndOpacity)) { GtkWidget *menuBar = Window::getMenuBar(widget, 0); GtkWidget *statusBar = (opts.statusbarHiding ? Window::getStatusBar(widget, 0) : nullptr); if (menuBar) { bool hiddenMenubar = (opts.menubarHiding ? qtcMenuBarHidden(qtSettings.appName) : false); QtcRect alloc = Widget::getAllocation(menuBar); if (hiddenMenubar) gtk_widget_hide(menuBar); if (BLEND_TITLEBAR || opts.menubarHiding & HIDE_KWIN || opts.windowBorder & WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR) { Menu::emitSize(menuBar, hiddenMenubar ? 0 : alloc.height); } if (opts.menubarHiding&HIDE_KWIN) { Window::menuBarDBus(widget, hiddenMenubar ? 0 : alloc.height); } } #if GTK_CHECK_VERSION(2, 90, 0) if(gtk_window_get_has_resize_grip(GTK_WINDOW(widget))) gtk_window_set_has_resize_grip(GTK_WINDOW(widget), false); #else if(statusBar && gtk_statusbar_get_has_resize_grip(GTK_STATUSBAR(statusBar))) gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(statusBar), false); #endif if (opts.statusbarHiding && statusBar) { bool hiddenStatusBar = qtcStatusBarHidden(qtSettings.appName); if (hiddenStatusBar) { gtk_widget_hide(statusBar); } if (opts.statusbarHiding & HIDE_KWIN) { Window::statusBarDBus(widget, !hiddenStatusBar); Window::setStatusBarProp(widget); } } } } if (widget && qtcIsCustomBgnd(opts) && oneOf(detail, "base", "eventbox")) { Scrollbar::setup(widget); } if (qtcIsCustomBgnd(opts) && oneOf(detail, "viewportbin")) { GtkRcStyle *st = widget ? gtk_widget_get_modifier_style(widget) : nullptr; // if the app hasn't modified bg, draw background gradient if (st && !(st->color_flags[state]>K_RC_BG)) { drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, x, y, width, height); Scrollbar::setup(widget); } else { parent_class->draw_flat_box(style, window, state, shadow, area, widget, _detail, x, y, width, height); } } else if (qtcIsCustomBgnd(opts) && widget && GTK_IS_WINDOW(widget) && !isMenuOrToolTipWindow && drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, x, y, width, height)) { Window::setup(widget, GTK_IS_DIALOG(widget) ? opts.dlgOpacity : opts.bgndOpacity); } else if (widget && GTK_IS_TREE_VIEW(widget)) { bool isCombo = isComboBoxPopupWindow(widget, 0); GtkTreeView *treeView = GTK_TREE_VIEW(widget); bool checkRules = (opts.forceAlternateLvCols || gtk_tree_view_get_rules_hint(treeView)); bool isEven = checkRules && strstr(detail, "cell_even"); if (qtSettings.app == GTK_APP_JAVA_SWT) area = nullptr; /* SWT seems to draw a 'cell_even', and then 'cell_odd' at the same position. This causes the view painting * to be messed up. Try and hack around this... */ if (qtSettings.app == GTK_APP_JAVA_SWT && state == GTK_STATE_SELECTED && checkRules && !isCombo && widget) { static GtkWidget *lastWidget = nullptr; static int lastEven = -1; if (strstr(detail, "cell_even")) { lastWidget = widget; lastEven = y; } else if (strstr(detail, "cell_odd")) { if (lastWidget == widget) { if (y == lastEven) { isEven = true; } } lastWidget = nullptr; lastEven = -1; } } if (!isCombo || state != GTK_STATE_SELECTED) { Cairo::rect(cr, (QtcRect*)area, x, y, width, height, getCellCol(haveAlternateListViewCol() && checkRules && !isEven ? &qtSettings.colors[PAL_ACTIVE][COLOR_LV] : &style->base[GTK_STATE_NORMAL], detail)); } if (isCombo) { if (state == GTK_STATE_SELECTED) { Cairo::rect(cr, (QtcRect*)area, x, y, width, height, &style->base[widget && gtk_widget_has_focus(widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE]); } } else { double alpha = 1.0; int selX = x; int selW = width; int factor = 0; bool forceCellStart = false; bool forceCellEnd = false; if (!isFixedWidget(widget)) { GtkTreePath *path = nullptr; GtkTreeViewColumn *column = nullptr; GtkTreeViewColumn *expanderColumn = gtk_tree_view_get_expander_column(treeView); int levelIndent = 0; int expanderSize = 0; int depth = 0; TreeView::getCell(treeView, &path, &column, x, y, width, height); TreeView::setup(widget); if (path && TreeView::isCellHovered(widget, path, column)) { if (state == GTK_STATE_SELECTED) { factor = 10; } else { alpha = 0.2; } } if (column == expanderColumn) { gtk_widget_style_get(widget, "expander-size", &expanderSize, nullptr); levelIndent = gtk_tree_view_get_level_indentation(treeView), depth = path ? (int)gtk_tree_path_get_depth(path) : 0; forceCellStart = true; if (opts.lvLines) { drawTreeViewLines(cr, &style->mid[GTK_STATE_ACTIVE], x, y, height, depth, levelIndent, expanderSize, treeView, path); } } else if (column && TreeView::cellIsLeftOfExpanderColumn(treeView, column)) { forceCellEnd = true; } if ((state == GTK_STATE_SELECTED || alpha < 1.0) && column == expanderColumn) { int offset = (3 + expanderSize * depth + (4 + levelIndent) * (depth - 1)); selX += offset; selW -= offset; } if(path) gtk_tree_path_free(path); } if (state == GTK_STATE_SELECTED || alpha < 1.0) { auto round = ROUNDED_NONE; if (opts.round != ROUND_NONE) { if (forceCellStart && forceCellEnd) { round = ROUNDED_ALL; } else if (forceCellStart || strstr(detail, "_start")) { round = ROUNDED_LEFT; } else if (forceCellEnd || strstr(detail, "_end")) { round = ROUNDED_RIGHT; } else if (!strstr(detail, "_middle")) { round = ROUNDED_ALL; } } drawSelection(cr, style, state, (QtcRect*)area, widget, selX, y, selW, height, round, true, alpha, factor); } } } else if (oneOf(detail, "checkbutton")) { if (state == GTK_STATE_PRELIGHT && opts.crHighlight && width > opts.crSize * 2) { GdkColor col=shadeColor(&style->bg[state], TO_FACTOR(opts.crHighlight)); drawSelectionGradient(cr, (QtcRect*)area, x, y, width, height, ROUNDED_ALL, false, 1.0, &col, true); } } else if (oneOf(detail, "expander")) { if (state == GTK_STATE_PRELIGHT && opts.expanderHighlight) { GdkColor col = shadeColor(&style->bg[state], TO_FACTOR(opts.expanderHighlight)); drawSelectionGradient(cr, (QtcRect*)area, x, y, width, height, ROUNDED_ALL, false, 1.0, &col, true); } } else if (oneOf(detail, "tooltip")) { drawToolTip(cr, widget, (QtcRect*)area, x, y, width, height); } else if (oneOf(detail, "icon_view_item")) { drawSelection(cr, style, state, (QtcRect*)area, widget, x, y, width, height, ROUNDED_ALL, false, 1.0, 0); } else if (state != GTK_STATE_SELECTED && qtcIsCustomBgnd(opts) && oneOf(detail, "eventbox")) { drawWindowBgnd(cr, style, nullptr, window, widget, x, y, width, height); } else if (!(qtSettings.app == GTK_APP_JAVA && widget && GTK_IS_LABEL(widget))) { if (state != GTK_STATE_PRELIGHT || opts.crHighlight || noneOf(detail, "checkbutton")) { parent_class->draw_flat_box(style, window, state, shadow, area, widget, _detail, x, y, width, height); } /* For SWT (e.g. eclipse) apps. For some reason these only seem to allow a ythickness of at max 2 - but for etching we need 3. So we fake this by drawing the 3rd lines here...*/ /* if(DO_EFFECT && GTK_STATE_INSENSITIVE!=state && oneOf(detail, "entry_bg") && isSwtComboBoxEntry(widget) && gtk_widget_has_focus(widget)) { Cairo::hLine(cr, x, y, width, &qtcPalette.highlight[FRAME_DARK_SHADOW]); Cairo::hLine(cr, x, y + height - 1, width, &qtcPalette.highlight[0]); } */ } cairo_destroy(cr); } static void gtkDrawHandle(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height, GtkOrientation) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_WINDOW(window)); const char *detail = _detail ? _detail : ""; QtcRect *area = (QtcRect*)_area; bool paf = widgetIsType(widget, "PanelAppletFrame"); cairo_t *cr = Cairo::gdkCreateClip(window, area); if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %d %d %s ", __FUNCTION__, state, shadow, width, height, _detail); debugDisplayWidget(widget, 10); } sanitizeSize(window, &width, &height); if (qtcIsFlatBgnd(opts.bgndAppearance) || !(widget && drawWindowBgnd(cr, style, area, window, widget, x, y, width, height))) { if (widget && opts.bgndImage.type != IMG_NONE) { drawWindowBgnd(cr, style, area, window, widget, x, y, width, height); } } if (oneOf(detail, "paned") || oneOf(detail + 1, "paned")) { drawSplitter(cr, state, style, area, x, y, width, height); } else if ((oneOf(detail, "handlebox") && (qtSettings.app == GTK_APP_JAVA || (widget && GTK_IS_HANDLE_BOX(widget)))) || oneOf(detail, "dockitem") || paf) { /* Note: I'm not sure why the 'widget && GTK_IS_HANDLE_BOX(widget)' is in * the following 'if' - its been there for a while. But this breaks the * toolbar handles for Java Swing apps. I'm leaving it in for non Java * apps, as there must've been a reason for it.... */ if (widget && state != GTK_STATE_INSENSITIVE) { state = gtk_widget_get_state(widget); } if (paf) { /* The paf here is expected to be on the gnome panel */ if (height < width) { y++; } else { x++; } } else { gtkDrawBox(style, window, state, shadow, (GdkRectangle*)area, widget, "handlebox", x, y, width, height); } switch (opts.handles) { case LINE_1DOT: Cairo::dot(cr, x, y, width, height, &qtcPalette.background[QTC_STD_BORDER]); break; case LINE_NONE: break; case LINE_DOTS: Cairo::dots(cr, x, y, width, height, height < width, 2, 5, area, 2, &qtcPalette.background[5], qtcPalette.background); break; case LINE_DASHES: if (height > width) { drawLines(cr, x + 3, y, 3, height, true, (height - 8) / 2, 0, qtcPalette.background, area, 5, opts.handles); } else { drawLines(cr, x, y + 3, width, 3, false, (width - 8) / 2, 0, qtcPalette.background, area, 5, opts.handles); } break; case LINE_FLAT: drawLines(cr, x, y, width, height, height < width, 2, 4, qtcPalette.background, area, 4, opts.handles); break; default: drawLines(cr, x, y, width, height, height < width, 2, 4, qtcPalette.background, area, 3, opts.handles); } } cairo_destroy(cr); } static void drawArrow(GdkWindow *window, const GdkColor *col, const QtcRect *area, GtkArrowType arrow_type, int x, int y, bool small, bool fill) { cairo_t *cr = gdk_cairo_create(window); Cairo::arrow(cr, col, area, arrow_type, x, y, small, fill, opts.vArrows); cairo_destroy(cr); } static void gtkDrawArrow(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, const char *_detail, GtkArrowType arrow_type, gboolean, int x, int y, int width, int height) { QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %d %s ", __FUNCTION__, state, shadow, arrow_type, x, y, width, height, _detail); debugDisplayWidget(widget, 10); } QtcRect *area = (QtcRect*)_area; cairo_t *cr = gdk_cairo_create(window); if (oneOf(detail, "arrow")) { bool onComboEntry = isOnComboEntry(widget, 0); if (isOnComboBox(widget, 0) && !onComboEntry) { if (state == GTK_STATE_ACTIVE) state = GTK_STATE_PRELIGHT; const GdkColor *arrowColor = MO_ARROW(false, &qtSettings.colors[state == GTK_STATE_INSENSITIVE ? PAL_DISABLED : PAL_ACTIVE] [COLOR_BUTTON_TEXT]); x++; // NOTE: Dont do this for moz - as looks odd fir widgets in // HTML pages - arrow is shifted too much :-( if (!(opts.buttonEffect != EFFECT_NONE)) x += 2; if (opts.doubleGtkComboArrow) { int pad = opts.vArrows ? 0 : 1; Cairo::arrow(cr, arrowColor, area, GTK_ARROW_UP, x + width / 2, y + height / 2 - (LARGE_ARR_HEIGHT - pad), false, true, opts.vArrows); Cairo::arrow(cr, arrowColor, area, GTK_ARROW_DOWN, x + width / 2, y + height / 2 + (LARGE_ARR_HEIGHT - pad), false, true, opts.vArrows); } else { GtkWidget *parent = nullptr; if (!opts.gtkComboMenus && !((parent = gtk_widget_get_parent(widget)) && (parent = gtk_widget_get_parent(parent)) && !ComboBox::hasFrame(parent))) { x += 2; } Cairo::arrow(cr, arrowColor, area, GTK_ARROW_DOWN, x + width / 2, y + height / 2, false, true, opts.vArrows); } } else { bool combo = onComboEntry || isOnCombo(widget, 0); int origState = state; if (combo && state == GTK_STATE_ACTIVE) state = GTK_STATE_PRELIGHT; const GdkColor *col = (combo || isOnListViewHeader(widget, 0) || isOnButton(widget, 0, nullptr) ? &qtSettings.colors[state == GTK_STATE_INSENSITIVE ? PAL_DISABLED : PAL_ACTIVE][COLOR_BUTTON_TEXT] : &style->text[ARROW_STATE(state)]); if (onComboEntry && origState == GTK_STATE_ACTIVE && opts.unifyCombo) { x--; y--; } Cairo::arrow(cr, MO_ARROW(false, col), area, arrow_type, x + width / 2, y + height / 2, false, true, opts.vArrows); } } else { int isSpinButton = oneOf(detail, "spinbutton"); bool isMenuItem = oneOf(detail, "menuitem"); /* int a_width = LARGE_ARR_WIDTH; */ /* int a_height = LARGE_ARR_HEIGHT; */ bool sbar = isSbarDetail(detail); bool smallArrows = isSpinButton && !opts.unifySpin; int stepper = (sbar ? getStepper(widget, x, y, opts.sliderWidth, opts.sliderWidth) : STEPPER_NONE); sanitizeSize(window, &width, &height); if (isSpinButton) { /* if (GTK_ARROW_UP == arrow_type) */ /* y++; */ /* a_height = SMALL_ARR_HEIGHT; */ /* a_width = SMALL_ARR_WIDTH; */ } else if (oneOf(arrow_type, GTK_ARROW_LEFT, GTK_ARROW_RIGHT) || isMenuItem) { /* a_width = LARGE_ARR_HEIGHT; */ /* a_height = LARGE_ARR_WIDTH; */ if (isMozilla() && opts.vArrows /* && a_height */ && height < LARGE_ARR_WIDTH) { smallArrows = true; } } x += width / 2; y += height / 2; if (state == GTK_STATE_ACTIVE && ((sbar && !opts.flatSbarButtons) || (isSpinButton && !opts.unifySpin))) { x++; y++; } if (sbar) { switch (stepper) { case STEPPER_B: if (opts.flatSbarButtons || !opts.vArrows) { if (GTK_ARROW_RIGHT == arrow_type) { x--; } else { y--; } } break; case STEPPER_C: if (opts.flatSbarButtons || !opts.vArrows) { if (GTK_ARROW_LEFT == arrow_type) { x++; } else { y++; } } default: break; } } if (isSpinButton && isFixedWidget(widget) && isFakeGtk()) { x--; } if (isSpinButton && !(opts.buttonEffect != EFFECT_NONE)) { y += arrow_type == GTK_ARROW_UP ? -1 : 1; } if (opts.unifySpin && isSpinButton && !opts.vArrows && arrow_type == GTK_ARROW_DOWN) { y--; } if (state == GTK_STATE_ACTIVE && (sbar || isSpinButton) && opts.coloredMouseOver == MO_GLOW) { state = GTK_STATE_PRELIGHT; } if (isMenuItem && arrow_type == GTK_ARROW_RIGHT && !isFakeGtk()) { x -= 2; } const GdkColor *col = (isSpinButton || sbar ? &qtSettings.colors[state == GTK_STATE_INSENSITIVE ? PAL_DISABLED : PAL_ACTIVE][COLOR_BUTTON_TEXT] : &style->text[isMenuItem && state == GTK_STATE_PRELIGHT ? GTK_STATE_SELECTED : ARROW_STATE(state)]); if (isMenuItem && state != GTK_STATE_PRELIGHT && opts.shadePopupMenu) { if (opts.shadeMenubars == SHADE_WINDOW_BORDER) { col = &qtSettings.colors[PAL_ACTIVE][COLOR_WINDOW_BORDER_TEXT]; } else if (opts.customMenuTextColor) { col = &opts.customMenuNormTextColor; } else if (oneOf(opts.shadeMenubars, SHADE_BLEND_SELECTED, SHADE_SELECTED) || (opts.shadeMenubars == SHADE_CUSTOM && TOO_DARK(qtcPalette.menubar[ORIGINAL_SHADE]))) { col = &style->text[GTK_STATE_SELECTED]; } } Cairo::arrow(cr, MO_ARROW(isMenuItem, col), area, arrow_type, x, y, smallArrows, true, opts.vArrows); } cairo_destroy(cr); } static void drawBox(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height, bool btnDown) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; bool sbar = isSbarDetail(detail); bool pbar = oneOf(detail, "bar"); // && GTK_IS_PROGRESS_BAR(widget); bool qtcSlider = !pbar && oneOf(detail, "qtc-slider"); bool slider = qtcSlider || (!pbar && oneOf(detail, "slider")); bool hscale = !slider && oneOf(detail, "hscale"); bool vscale = !hscale && oneOf(detail, "vscale"); bool menubar = !vscale && oneOf(detail, "menubar"); bool button = !menubar && oneOf(detail, "button"); bool togglebutton = !button && oneOf(detail, "togglebutton"); bool optionmenu = !togglebutton && oneOf(detail, "optionmenu"); bool stepper = !optionmenu && oneOf(detail, "stepper"); bool vscrollbar = (!optionmenu && Str::startsWith(detail, "vscrollbar")); bool hscrollbar = (!vscrollbar && Str::startsWith(detail, "hscrollbar")); bool spinUp = !hscrollbar && oneOf(detail, "spinbutton_up"); bool spinDown = !spinUp && oneOf(detail, "spinbutton_down"); bool menuScroll = strstr(detail, "menu_scroll_arrow_"); bool rev = (reverseLayout(widget) || (widget && reverseLayout(gtk_widget_get_parent(widget)))); bool activeWindow = true; GdkColor new_cols[TOTAL_SHADES + 1]; const GdkColor *btnColors = qtcPalette.background; int bgnd = getFill(state, btnDown); auto round = getRound(detail, widget, rev); bool lvh = (isListViewHeader(widget) || isEvolutionListViewHeader(widget, detail)); bool sunken = (btnDown || shadow == GTK_SHADOW_IN || state == GTK_STATE_ACTIVE || bgnd == 2 || bgnd == 3); GtkWidget *parent = nullptr; if (button && GTK_IS_TOGGLE_BUTTON(widget)) { button = false; togglebutton = true; } if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %d %s ", __FUNCTION__, btnDown, state, shadow, x, y, width, height, _detail); debugDisplayWidget(widget, 10); } // FIXME, need to update useButtonColor if the logic below changes right now if (useButtonColor(detail)) { if (slider | hscale | vscale | sbar && state == GTK_STATE_INSENSITIVE) { btnColors = qtcPalette.background; } else if (QT_CUSTOM_COLOR_BUTTON(style)) { shadeColors(&style->bg[state], new_cols); btnColors = new_cols; } else { SET_BTN_COLS(slider, hscale | vscale, lvh, state); } } if (menubar && !isFakeGtk() && opts.shadeMenubarOnlyWhenActive) { GtkWindow *topLevel = GTK_WINDOW(gtk_widget_get_toplevel(widget)); if (topLevel && GTK_IS_WINDOW(topLevel)) { GtkWidgetProps topProps(topLevel); if (!topProps->shadeActiveMBHacked) { topProps->shadeActiveMBHacked = true; g_signal_connect(G_OBJECT(topLevel), "event", G_CALLBACK(windowEvent), widget); } activeWindow = Window::isActive(GTK_WIDGET(topLevel)); } } if (opts.menubarMouseOver && GTK_IS_MENU_SHELL(widget) && !isFakeGtk()) { Menu::shellSetup(widget); } cairo_t *cr = Cairo::gdkCreateClip(window, area); if (spinUp || spinDown) { if (!opts.unifySpin && (!opts.unifySpinBtns || sunken)) { EWidget wid = spinUp ? WIDGET_SPIN_UP : WIDGET_SPIN_DOWN; QtcRect *a = (QtcRect*)area; QtcRect b; QtcRect unified; bool ooOrMoz = isFakeGtk(); if (!a && isFixedWidget(widget) && ooOrMoz) { b = qtcRect(x, y, width, height); a = &b; } if (wid == WIDGET_SPIN_UP) { if (opts.buttonEffect != EFFECT_NONE && opts.etchEntry) { if (!opts.unifySpinBtns) drawEtch(cr, a, widget, x - 2, y, width + 2, height * 2, false, ROUNDED_RIGHT, WIDGET_SPIN_UP); y++; width--; } height++; if (opts.unifySpinBtns) { unified = qtcRect(x, y, width, height - (state == GTK_STATE_PRELIGHT ? 2 : 1)); height *= 2; area = (GdkRectangle*)&unified; } else if (!opts.etchEntry) { height++; } } else if (opts.buttonEffect != EFFECT_NONE && opts.etchEntry) { QtcRect clip = {x - 2, y, width + 2, height}; if (!opts.unifySpinBtns) { drawEtch(cr, ooOrMoz ? a : &clip, widget, x - 2, y - 2, width + 2, height + 2, false, ROUNDED_RIGHT, WIDGET_SPIN_DOWN); } height--; width--; if (opts.unifySpinBtns) { unified = qtcRect( x, y + (state == GTK_STATE_PRELIGHT ? 1 : 0), width, height - (state == GTK_STATE_PRELIGHT ? 1 : 0)); y -= height; height *= 2; area = (GdkRectangle*)&unified; } } drawBgnd(cr, &btnColors[bgnd], widget, (QtcRect*)area, x + 1, y + 1, width - 2, height - 2); drawLightBevel(cr, style, state, (QtcRect*)area, x, y, width, height - (WIDGET_SPIN_UP == wid && opts.buttonEffect != EFFECT_NONE ? 1 : 0), &btnColors[bgnd], btnColors, round, wid, BORDER_FLAT, DF_DO_BORDER | (sunken ? DF_SUNKEN : 0), widget); } } else if (oneOf(detail, "spinbutton")) { if (qtcIsFlatBgnd(opts.bgndAppearance) || !(widget && drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, x, y, width, height))) { gtk_style_apply_default_background( style, window, widget && gtk_widget_get_has_window(widget), state == GTK_STATE_INSENSITIVE ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL, area, x, y, width, height); if (widget && opts.bgndImage.type != IMG_NONE) { drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, x, y, width, height); } } if (opts.unifySpin) { bool rev = (reverseLayout(widget) || (widget && reverseLayout(gtk_widget_get_parent(widget)))); bool moz = isMozillaWidget(widget); if (!rev) { x -= 4; } width += 4; Cairo::Saver saver(cr); if (moz) { QtcRect a = {x + 2, y, width - 2, height}; Cairo::clipRect(cr, &a); } drawEntryField(cr, style, state, window, widget, (QtcRect*)area, x, y, width, height, rev ? ROUNDED_LEFT : ROUNDED_RIGHT, WIDGET_SPIN); } else if (opts.unifySpinBtns) { int offset = (opts.buttonEffect != EFFECT_NONE && opts.etchEntry ? 1 : 0); if (offset) { drawEtch(cr, (QtcRect*)area, widget, x, y, width, height, false, ROUNDED_RIGHT, WIDGET_SPIN); } #if GTK_CHECK_VERSION(2, 90, 0) bgnd = getFill(state == GTK_STATE_ACTIVE ? GTK_STATE_NORMAL : state, false); #endif drawLightBevel(cr, style, state, (QtcRect*)area, x, y + offset, width - offset, height - 2 * offset, &btnColors[bgnd], btnColors, ROUNDED_RIGHT, WIDGET_SPIN, BORDER_FLAT, DF_DO_BORDER | (sunken ? DF_SUNKEN : 0), widget); drawFadedLine(cr, x + 2, y + height / 2, width - (offset + 4), 1, &btnColors[QTC_STD_BORDER], (QtcRect*)area, nullptr, true, true, true); } } else if (!opts.stdSidebarButtons && (button || togglebutton) && isSideBarBtn(widget)) { drawSidebarButton(cr, state, style, (QtcRect*)area, x, y, width, height); } else if (lvh) { if (opts.highlightScrollViews && widget) { GtkWidget *parent = gtk_widget_get_parent(widget); if (parent && GTK_IS_TREE_VIEW(parent)) { ScrolledWindow::registerChild(parent); } } drawListViewHeader(cr, state, btnColors, bgnd, (QtcRect*)area, x, y, width, height); } else if (isPathButton(widget)) { if (state == GTK_STATE_PRELIGHT) { drawSelection(cr, style, state, (QtcRect*)area, widget, x, y, width, height, ROUNDED_ALL, false, 1.0, 0); } if (opts.windowDrag > WM_DRAG_MENU_AND_TOOLBAR) { WMMove::setup(widget); } if (GTK_IS_TOGGLE_BUTTON(widget)) { drawArrow(window, &qtcPalette.background[5], (QtcRect*)area, GTK_ARROW_RIGHT, x + width - (LARGE_ARR_WIDTH / 2 + 4), y + (height - LARGE_ARR_HEIGHT / 2) / 2 + 1, false, true); } } else if (button || togglebutton || optionmenu || sbar || hscale || vscale || stepper || slider) { bool combo = oneOf(detail, "optionmenu") || isOnComboBox(widget, 0); bool combo_entry = combo && isOnComboEntry(widget, 0); bool horiz_tbar; bool tbar_button = isButtonOnToolbar(widget, &horiz_tbar); bool handle_button = (!tbar_button && isButtonOnHandlebox(widget, &horiz_tbar)); int xAdjust = 0; int yAdjust = 0; int wAdjust = 0; int hAdjust = 0; bool horiz = ((tbar_button || handle_button) && IS_GLASS(opts.appearance) && IS_GLASS(opts.toolbarAppearance) ? horiz_tbar : (slider && width < height) || vscrollbar || vscale || (stepper && widget && GTK_IS_VSCROLLBAR(widget)) ? false : true); bool defBtn = (state != GTK_STATE_INSENSITIVE && (button || togglebutton) && widget && gtk_widget_has_default(widget)); if (combo && !sunken && isActiveOptionMenu(widget)) { sunken = true; bgnd = 4; } if (tbar_button && opts.tbarBtns == TBTN_JOINED) { adjustToolbarButtons(widget, &xAdjust, &yAdjust, &wAdjust, &hAdjust, &round, horiz_tbar); x += xAdjust; y += yAdjust; width += wAdjust; height += hAdjust; } { /* Yuck this is a horrible mess!!!!! */ bool glowFocus = (widget && gtk_widget_has_focus(widget) && opts.coloredMouseOver == MO_GLOW && oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)); EWidget widgetType=isComboBoxButton(widget) ? WIDGET_COMBO_BUTTON : slider ? qtcSlider ? WIDGET_SLIDER : WIDGET_SB_SLIDER : hscale||vscale ? WIDGET_SLIDER : combo || optionmenu ? WIDGET_COMBO : tbar_button ? (opts.coloredTbarMo ? WIDGET_TOOLBAR_BUTTON : WIDGET_UNCOLOURED_MO_BUTTON) : togglebutton ? (glowFocus && !sunken ? WIDGET_DEF_BUTTON : WIDGET_TOGGLE_BUTTON) : button ? defBtn || glowFocus ? WIDGET_DEF_BUTTON : WIDGET_STD_BUTTON : stepper || sbar ? WIDGET_SB_BUTTON : WIDGET_OTHER; int xo=x, yo=y, wo=width, ho=height, stepper=STEPPER_NONE; /* Try and guess if this button is a toolbar button... */ if (oneOf(widgetType, WIDGET_STD_BUTTON, WIDGET_TOGGLE_BUTTON) && isMozillaWidget(widget) && GTK_IS_BUTTON(widget) && oneOf(detail, "button") && ((width > 22 && width < 56 && height > 30) || height >= 32 || ((width == 30 || width == 45) && height == 30))) widgetType = (opts.coloredTbarMo ? WIDGET_TOOLBAR_BUTTON : WIDGET_UNCOLOURED_MO_BUTTON); if (ROUND_MAX==opts.round && ((WIDGET_TOGGLE_BUTTON==widgetType && height>(opts.crSize+8) && width<(height+10)) || (GTK_APP_GIMP==qtSettings.app && WIDGET_STD_BUTTON==widgetType && widgetIsType(widget, "GimpViewableButton")) || (opts.stdSidebarButtons && WIDGET_STD_BUTTON==widgetType && widget && isSideBarBtn(widget)) || (WIDGET_STD_BUTTON==widgetType && GTK_APP_OPEN_OFFICE==qtSettings.app && isFixedWidget(widget) && height>30 && height<40 && width>16 && width<50) ) ) widgetType=WIDGET_TOOLBAR_BUTTON; /* For some reason SWT combo's dont un-prelight when activated! So dont pre-light at all! */ /* if(GTK_APP_JAVA_SWT==qtSettings.app && WIDGET_STD_BUTTON==widgetType && GTK_STATE_PRELIGHT==state && WIDGET_COMBO==widgetType) { state=GTK_STATE_NORMAL; bgnd=getFill(state, btnDown); } else */ if(WIDGET_SB_BUTTON==widgetType && GTK_APP_MOZILLA!=qtSettings.app) { stepper = getStepper(widget, x, y, width, height); switch (stepper) { case STEPPER_B: if (horiz) { x--; width++; } else { y--; height++; } break; case STEPPER_C: if (horiz) { width++; } else { height++; } default: break; } } if(/*GTK_APP_JAVA_SWT==qtSettings.app && */ widget && !isFixedWidget(widget) && /* Don't do for Firefox, etc. */ WIDGET_SB_SLIDER==widgetType && GTK_STATE_INSENSITIVE!=state && GTK_IS_RANGE(widget)) { QtcRect alloc = Widget::getAllocation(widget); bool horizontal = !Widget::isHorizontal(widget); int sbarTroughLen = (horizontal ? alloc.height : alloc.width) - ((qtcRangeHasStepperA(widget) ? opts.sliderWidth : 0) + (qtcRangeHasStepperB(widget) ? opts.sliderWidth : 0) + (qtcRangeHasStepperC(widget) ? opts.sliderWidth : 0) + (qtcRangeHasStepperD(widget) ? opts.sliderWidth : 0)); int sliderLen = horizontal ? height : width; if(sbarTroughLen==sliderLen) { state=GTK_STATE_INSENSITIVE; btnColors=qtcPalette.background; bgnd=getFill(state, false); } } #ifdef INCREASE_SB_SLIDER if(slider && widget && GTK_IS_RANGE(widget) && !opts.flatSbarButtons && SCROLLBAR_NONE!=opts.scrollbarType /*&& !(GTK_STATE_PRELIGHT==state && MO_GLOW==opts.coloredMouseOver)*/) { GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); bool horizontal = Widget::isHorizontal(widget); #if GTK_CHECK_VERSION(2, 90, 0) bool hasStartStepper = SCROLLBAR_PLATINUM!=opts.scrollbarType; bool hasEndStepper = SCROLLBAR_NEXT!=opts.scrollbarType; #else bool hasStartStepper = (qtcRangeHasStepperA(widget) || qtcRangeHasStepperB(widget)); bool hasEndStepper = (qtcRangeHasStepperC(widget) || qtcRangeHasStepperD(widget)); #endif bool atEnd = false; double value = gtk_adjustment_get_value(adj); if (hasStartStepper && value <= gtk_adjustment_get_lower(adj)) { if (horizontal) { x--; width++; } else { y--; height++; } atEnd = true; } if (hasEndStepper && value >= (gtk_adjustment_get_upper(adj) - gtk_adjustment_get_page_size(adj))) { if (horizontal) { width++; } else { height++; } atEnd = true; } if (!isMozilla() && widget && lastSlider.widget == widget && !atEnd) { lastSlider.widget = nullptr; } } #endif #if !GTK_CHECK_VERSION(2, 90, 0) /* Gtk3:TODO !!! */ if(GTK_APP_OPEN_OFFICE==qtSettings.app && opts.flatSbarButtons && slider && (SCROLLBAR_KDE==opts.scrollbarType || SCROLLBAR_WINDOWS==opts.scrollbarType) && widget && GTK_IS_RANGE(widget) && isFixedWidget(widget)) { if (!Widget::isHorizontal(widget)) { y++; height--; } else { x += 2; width -= 2; } } #endif if(WIDGET_COMBO==widgetType && !opts.gtkComboMenus && !isMozilla() && ((parent=gtk_widget_get_parent(widget)) && GTK_IS_COMBO_BOX(parent) && !QTC_COMBO_ENTRY(parent))) { GtkWidget *mapped = nullptr; bool changedFocus = false; bool draw = true; int mod = 7; if (!opts.gtkComboMenus && !ComboBox::hasFrame(parent)) { mod = 0; draw = oneOf(state, GTK_STATE_ACTIVE, GTK_STATE_PRELIGHT); ComboBox::setup(nullptr, parent); } else { changedFocus = ComboBox::isFocusChanged(widget); mapped = WidgetMap::getWidget(parent, 1); WidgetMap::setup(parent, widget, 0); if (parent && ComboBox::isHovered(parent)) { state = GTK_STATE_PRELIGHT; } } if (draw) drawLightBevel(cr, style, state, (QtcRect*)area, x - mod, y, width + mod, height, &btnColors[bgnd], btnColors, round, WIDGET_TOOLBAR_BUTTON, BORDER_FLAT, (state == GTK_STATE_ACTIVE ? DF_SUNKEN : 0) | DF_DO_BORDER, widget); if(mapped) { if(changedFocus) gtk_widget_queue_draw(mapped); else { GtkStateType mappedState=gtk_widget_get_state(mapped); if(GTK_STATE_INSENSITIVE==state && GTK_STATE_INSENSITIVE!=mappedState) state=mappedState; if(mappedState!=gtk_widget_get_state(widget) && GTK_STATE_INSENSITIVE!=mappedState && GTK_STATE_INSENSITIVE!=state) gtk_widget_set_state(mapped, state); } } } else if(opts.unifyCombo && WIDGET_COMBO_BUTTON==widgetType) { GtkWidget *parent=widget ? gtk_widget_get_parent(widget) : nullptr; GtkWidget *entry=parent ? getComboEntry(parent) : nullptr; GtkStateType entryState=entry ? gtk_widget_get_state(entry) : GTK_STATE_NORMAL; bool rev = false; bool mozToolbar = (isMozilla() && parent && GTK_IS_TOGGLE_BUTTON(widget) && QTC_COMBO_ENTRY(parent) && (parent = gtk_widget_get_parent(parent)) && GTK_IS_FIXED(parent) && (parent = gtk_widget_get_parent(parent)) && GTK_IS_WINDOW(parent) && strcmp(gtk_widget_get_name(parent), "MozillaGtkWidget") == 0); if (!entry && widget && gtk_widget_get_parent(widget)) { entry = WidgetMap::getWidget( gtk_widget_get_parent(widget), 1); } if(entry) rev=reverseLayout(entry); if(!rev) x-=4; width+=4; if((mozToolbar && state==GTK_STATE_PRELIGHT) || state==GTK_STATE_ACTIVE) state=GTK_STATE_NORMAL; // When we draw the entry, if its highlighted we want to highlight this button as well. // Unfortunately, when the entry of a GtkComboBoxEntry draws itself, there is no way to // determine the button associated with it. So, we store the mapping here... if(!mozToolbar && parent && QTC_COMBO_ENTRY(parent)) WidgetMap::setup(parent, widget, 0); // If the button is disabled, but the entry field is not - then use entry field's state // for the button. This fixes an issue with LinuxDC++ and Gtk 2.18 if(GTK_STATE_INSENSITIVE==state && entry && GTK_STATE_INSENSITIVE!=entryState) state=entryState; drawEntryField(cr, style, state, window, entry, (QtcRect*)area, x, y, width, height, rev ? ROUNDED_LEFT : ROUNDED_RIGHT, WIDGET_COMBO_BUTTON); // Get entry to redraw by setting its state... // ...cant do a queue redraw, as then entry does for the button, else we get stuck in a loop! if(!mozToolbar && widget && entry && entryState!=gtk_widget_get_state(widget) && GTK_STATE_INSENSITIVE!=entryState && GTK_STATE_INSENSITIVE!=state) gtk_widget_set_state(entry, state); } else if (opts.flatSbarButtons && WIDGET_SB_BUTTON==widgetType) { #if !GTK_CHECK_VERSION(2, 90, 0) if (isMozilla()) { /* This section messes up Gtk3 scrollbars with custom background - and doesnt seem to be required for Gtk2 either. remove at 1.7.1 */ /* Re-added in 1.7.2 as needed by Mozilla! */ if(opts.gtkScrollViews && qtcIsFlat(opts.sbarBgndAppearance) && 0!=opts.tabBgnd && widget && gtk_widget_get_parent(widget) && gtk_widget_get_parent(widget)->parent && GTK_IS_SCROLLED_WINDOW(gtk_widget_get_parent(widget)) && GTK_IS_NOTEBOOK(gtk_widget_get_parent(widget)->parent)) drawAreaModColor(cr, (QtcRect*)area, &qtcPalette.background[ORIGINAL_SHADE], TO_FACTOR(opts.tabBgnd), xo, yo, wo, ho); else if(qtcIsFlatBgnd(opts.bgndAppearance) || !(opts.gtkScrollViews && qtcIsFlat(opts.sbarBgndAppearance) && widget && drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, xo, yo, wo, ho))) { if (!qtcIsFlat(opts.sbarBgndAppearance) && opts.scrollbarType != SCROLLBAR_NONE) { drawBevelGradient( cr, (QtcRect*)area, xo, yo, wo, ho, &qtcPalette.background[ORIGINAL_SHADE], horiz, false, opts.sbarBgndAppearance, WIDGET_SB_BGND); } else { drawBgnd( cr, &qtcPalette.background[ORIGINAL_SHADE], widget, (QtcRect*)area, xo, yo, wo, ho); } } } #endif } else { const GdkColor *cols = (defBtn && oneOf(opts.defBtnIndicator, IND_TINT, IND_COLORED, IND_SELECTED) ? qtcPalette.defbtn : widgetType == WIDGET_COMBO_BUTTON && qtcPalette.combobtn && state != GTK_STATE_INSENSITIVE ? qtcPalette.combobtn : btnColors); int bg = (WIDGET_COMBO_BUTTON==widgetType && (SHADE_DARKEN==opts.comboBtn || (SHADE_NONE != opts.comboBtn && GTK_STATE_INSENSITIVE==state))) || (WIDGET_SB_SLIDER==widgetType && SHADE_DARKEN==opts.shadeSliders) || (defBtn && IND_DARKEN==opts.defBtnIndicator) ? getFill(state, btnDown, true) : bgnd; drawLightBevel(cr, style, state, (QtcRect*)area, x, y, width, height, &cols[bg], cols, round, widgetType, BORDER_FLAT, (sunken ? DF_SUNKEN : 0) | DF_DO_BORDER | (horiz ? 0 : DF_VERT), widget); if(tbar_button && TBTN_JOINED==opts.tbarBtns) { const int constSpace=4; int xo=x-xAdjust, yo=y-yAdjust, wo=width-wAdjust, ho=height-hAdjust; if(xAdjust) drawFadedLine(cr, xo, yo + constSpace, 1, ho - 2 * constSpace, &btnColors[0], (QtcRect*)area, nullptr, true, true, false); if (yAdjust) drawFadedLine(cr, xo + constSpace, yo, wo - 2 * constSpace, 1, &btnColors[0], (QtcRect*)area, nullptr, true, true, true); if(wAdjust && ROUNDED_RIGHT!=round) drawFadedLine(cr, xo + wo - 1, yo + constSpace, 1, ho - 2 * constSpace, &btnColors[QTC_STD_BORDER], (QtcRect*)area, nullptr, true, true, false); if (hAdjust && ROUNDED_BOTTOM!=round) drawFadedLine(cr, xo + constSpace, yo + ho - 1, wo - 2 * constSpace, 1, &btnColors[QTC_STD_BORDER], (QtcRect*)area, nullptr, true, true, true); } } #ifdef INCREASE_SB_SLIDER /* Gtk draws slider first, and then the buttons. But if we have a shaded slider, and extend this so that it overlaps (by 1 pixel) the buttons, then the top/bottom is vut off if this is shaded... So, work-around this by re-drawing the slider here! */ if(!opts.flatSbarButtons && SHADE_NONE!=opts.shadeSliders && SCROLLBAR_NONE!=opts.scrollbarType && WIDGET_SB_BUTTON==widgetType && widget && widget==lastSlider.widget && !isMozilla() && ( (SCROLLBAR_NEXT==opts.scrollbarType && STEPPER_B==stepper) || STEPPER_D==stepper)) { #if GTK_CHECK_VERSION(2, 90, 0) gtkDrawSlider(lastSlider.style, lastSlider.cr, lastSlider.state, lastSlider.shadow, lastSlider.widget, lastSlider.detail, lastSlider.x, lastSlider.y, lastSlider.width, lastSlider.height, lastSlider.orientation); #else gtkDrawSlider(lastSlider.style, lastSlider.window, lastSlider.state, lastSlider.shadow, nullptr, lastSlider.widget, lastSlider.detail, lastSlider.x, lastSlider.y, lastSlider.width, lastSlider.height, lastSlider.orientation); #endif lastSlider.widget=nullptr; } #endif } if (defBtn) { drawDefBtnIndicator(cr, state, btnColors, bgnd, sunken, (QtcRect*)area, x, y, width, height); } if (opts.comboSplitter || opts.comboBtn != SHADE_NONE) { if (optionmenu) { GtkRequisition indicator_size; GtkBorder indicator_spacing; int cx=x, cy=y, cheight=height, cwidth=width, ind_width=0, darkLine=BORDER_VAL(GTK_STATE_INSENSITIVE!=state); optionMenuGetProps(widget, &indicator_size, &indicator_spacing); ind_width=indicator_size.width+indicator_spacing.left+indicator_spacing.right; if (opts.buttonEffect != EFFECT_NONE) cx--; cy+=3; cheight-=6; if (opts.comboBtn != SHADE_NONE) { const GdkColor *cols = (qtcPalette.combobtn && state != GTK_STATE_INSENSITIVE ? qtcPalette.combobtn : btnColors); int bg = SHADE_DARKEN==opts.comboBtn || (GTK_STATE_INSENSITIVE==state && SHADE_NONE!=opts.comboBtn) ? getFill(state, btnDown, true) : bgnd; QtcRect btn = { cx + (rev ? ind_width + style->xthickness : (cwidth - ind_width - style->xthickness) + 1), y, ind_width + 3, height }; Cairo::Saver saver(cr); if (!opts.comboSplitter) { Cairo::clipRect(cr, &btn); } if (rev) { btn.width += 3; } else { btn.x -= 3; if (opts.buttonEffect != EFFECT_NONE) { btn.width += 3; } else { btn.width += 1; } } drawLightBevel(cr, style, state, (QtcRect*)area, btn.x, btn.y, btn.width, btn.height, &cols[bg], cols, rev ? ROUNDED_LEFT : ROUNDED_RIGHT, WIDGET_COMBO, BORDER_FLAT, (sunken ? DF_SUNKEN : 0) | DF_DO_BORDER | DF_HIDE_EFFECT, widget); } else if (opts.comboSplitter) { if(sunken) cx++, cy++, cheight--; drawFadedLine( cr, cx + (rev ? ind_width + style->xthickness : cwidth - ind_width - style->xthickness), cy + style->ythickness - 1, 1, cheight - 3, &btnColors[darkLine], (QtcRect*)area, nullptr, true, true, false); if (!sunken) { drawFadedLine( cr, cx + 1 + (rev ? ind_width + style->xthickness : cwidth - ind_width - style->xthickness), cy + style->ythickness-1, 1, cheight - 3, &btnColors[0], (QtcRect*)area, nullptr, true, true, false); } } } else if((button || togglebutton) && (combo || combo_entry)) { int vx = x + (width - (1 + (combo_entry ? 24 : 20))); /* int vwidth = width - (vx - x); */ int darkLine = BORDER_VAL(GTK_STATE_INSENSITIVE != state); if (rev) { vx = x + LARGE_ARR_WIDTH; if (combo_entry) { vx += 2; } } if (opts.buttonEffect != EFFECT_NONE) vx -= 2; if (!combo_entry) { if (opts.comboBtn != SHADE_NONE) { const GdkColor *cols = (qtcPalette.combobtn && state != GTK_STATE_INSENSITIVE ? qtcPalette.combobtn : btnColors); int bg = SHADE_DARKEN==opts.comboBtn || (GTK_STATE_INSENSITIVE==state && SHADE_NONE!=opts.comboBtn) ? getFill(state, btnDown, true) : bgnd; QtcRect btn = { vx + (rev ? LARGE_ARR_WIDTH + 4 : 0), y, 20 + 3, height }; Cairo::Saver saver(cr); if (!opts.comboSplitter) { Cairo::clipRect(cr, &btn); } if (rev) { btn.width += 3; } else { btn.x -= 3; if (opts.buttonEffect != EFFECT_NONE) { btn.width += 3; } } drawLightBevel(cr, style, state, (QtcRect*)area, btn.x, btn.y, btn.width, btn.height, &cols[bg], cols, rev ? ROUNDED_LEFT : ROUNDED_RIGHT, WIDGET_COMBO, BORDER_FLAT, (sunken ? DF_SUNKEN : 0) | DF_DO_BORDER | DF_HIDE_EFFECT, widget); } else if (opts.comboSplitter) { drawFadedLine(cr, vx + (rev ? LARGE_ARR_WIDTH + 4 : 0), y + 4, 1, height - 8, &btnColors[darkLine], (QtcRect*)area, nullptr, true, true, false); if(!sunken) drawFadedLine(cr, vx + 1 + (rev ? LARGE_ARR_WIDTH + 4 : 0), y + 4, 1, height - 8, &btnColors[0], (QtcRect*)area, nullptr, true, true, false); } } } } } else if (oneOf(detail, "buttondefault", "togglebuttondefault")) { } else if (widget && (oneOf(detail, "trough") || Str::startsWith(detail, "trough-"))) { bool list = isList(widget); bool pbar = list || GTK_IS_PROGRESS_BAR(widget); bool scale = !pbar && GTK_IS_SCALE(widget); /* int border = BORDER_VAL(GTK_STATE_INSENSITIVE != state || !scale); */ bool horiz = (GTK_IS_RANGE(widget) ? Widget::isHorizontal(widget) : width > height); if (scale) { drawSliderGroove(cr, style, state, widget, detail, (QtcRect*)area, x, y, width, height, horiz); } else if (pbar) { drawProgressGroove(cr, style, state, window, widget, (QtcRect*)area, x, y, width, height, list, horiz); } else { drawScrollbarGroove(cr, style, state, widget, (QtcRect*)area, x, y, width, height, horiz); } } else if (oneOf(detail, "entry-progress")) { int adjust = (opts.fillProgress ? 4 : 3) - (opts.etchEntry ? 1 : 0); drawProgress(cr, style, state, widget, (QtcRect*)area, x - adjust, y - adjust, width + adjust, height + 2 * adjust, rev, true); } else if (oneOf(detail, "dockitem", "dockitem_bin")) { if (qtcIsCustomBgnd(opts) && widget) { drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, x, y, width, height); } } else if (widget && ((menubar || oneOf(detail, "toolbar", "handlebox", "handlebox_bin")) || widgetIsType(widget, "PanelAppletFrame"))) { //if(GTK_SHADOW_NONE!=shadow) { const GdkColor *col = menubar && (GTK_STATE_INSENSITIVE!=state || SHADE_NONE!=opts.shadeMenubars) ? &menuColors(activeWindow)[ORIGINAL_SHADE] : &style->bg[state]; EAppearance app=menubar ? opts.menubarAppearance : opts.toolbarAppearance; int menuBarAdjust=0, opacity=getOpacity(widget); double alpha=opacity!=100 ? (opacity/100.00) : 1.0; bool drawGradient = shadow != GTK_SHADOW_NONE && !qtcIsFlat(app); bool fillBackground = menubar && opts.shadeMenubars != SHADE_NONE; if ((menubar && opts.windowDrag) || opts.windowDrag > WM_DRAG_MENUBAR) { WMMove::setup(widget); } if (menubar && BLEND_TITLEBAR) { menuBarAdjust = qtcGetWindowBorderSize(false).titleHeight; if (widget && Menu::emitSize(widget, height) && (opts.menubarHiding || opts.windowBorder & WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR)) { Window::menuBarDBus(widget, height); } } if (widget && (opacity!=100 || qtcIsCustomBgnd(opts))) { drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, x, y, width, height); } if (drawGradient) { drawBevelGradient(cr, (QtcRect*)area, x, y - menuBarAdjust, width, height + menuBarAdjust, col, (menubar ? true : oneOf(detail, "handlebox") ? width < height : width > height), false, MODIFY_AGUA(app), WIDGET_OTHER, alpha); } else if (fillBackground) { Cairo::rect(cr, (QtcRect*)area, x, y, width, height, col, alpha); } if (shadow != GTK_SHADOW_NONE && opts.toolbarBorders != TB_NONE) { drawToolbarBorders(cr, state, x, y, width, height, menubar && activeWindow, detail); } } } else if (widget && pbar) { drawProgress(cr, style, state, widget, (QtcRect*)area, x, y, width, height, rev, false); } else if (oneOf(detail, "menuitem")) { drawMenuItem(cr, state, style, widget, (QtcRect*)area, x, y, width, height); } else if (oneOf(detail, "menu")) { drawMenu(cr, widget, (QtcRect*)area, x, y, width, height); } else if ((!strcmp(detail, "paned") || !strcmp(detail + 1, "paned"))) { gtkDrawHandle(style, window, state, shadow, area, widget, detail, x, y, width, height, *detail == 'h' ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL); } else if (strcmp(detail + 1, "ruler") == 0) { drawBevelGradient(cr, (QtcRect*)area, x, y, width, height, &qtcPalette.background[ORIGINAL_SHADE], detail[0] == 'h', false, opts.lvAppearance, WIDGET_LISTVIEW_HEADER); // if(qtcIsFlatBgnd(opts.bgndAppearance) || !widget || !drawWindowBgnd(cr, style, area, widget, x, y, width, height)) // { // drawAreaColor(cr, area, &style->bg[state], x, y, width, height); // if(widget && IMG_NONE!=opts.bgndImage.type) // drawWindowBgnd(cr, style, area, widget, x, y, width, height); // } } else if (oneOf(detail, "hseparator")) { bool isMenuItem = widget && GTK_IS_MENU_ITEM(widget); const GdkColor *cols=qtcPalette.background; int offset=opts.menuStripe && (isMozilla() || isMenuItem) ? 20 : 0; if(offset && isFakeGtk()) offset+=2; if (isMenuItem && (opts.lighterPopupMenuBgnd || opts.shadePopupMenu)) { cols = qtcPalette.menu; } drawFadedLine(cr, x + 1 + offset, y + height / 2, width - (1 + offset), 1, &cols[isMenuItem ? MENU_SEP_SHADE : QTC_STD_BORDER], (QtcRect*)area, nullptr, true, true, true); } else if (oneOf(detail, "vseparator")) { drawFadedLine(cr, x + width / 2, y, 1, height, &qtcPalette.background[QTC_STD_BORDER], (QtcRect*)area, nullptr, true, true, false); } else { EWidget wt = (!_detail && GTK_IS_TREE_VIEW(widget) ? WIDGET_PBAR_TROUGH : WIDGET_FRAME); Cairo::Saver saver(cr); qtcClipPath(cr, x + 1, y + 1, width - 2, height - 2, WIDGET_OTHER, RADIUS_INTERNAL, round); if (qtcIsFlatBgnd(opts.bgndAppearance) || !widget || !drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, x + 1, y + 1, width - 2, height - 2)) { Cairo::rect(cr, (QtcRect*)area, x + 1, y + 1, width - 2, height - 2, &style->bg[state]); if (widget && opts.bgndImage.type != IMG_NONE) { drawWindowBgnd(cr, style, (QtcRect*)area, window, widget, x, y, width, height); } } saver.restore(); if (wt == WIDGET_PBAR_TROUGH) { drawProgressGroove(cr, style, state, window, widget, (QtcRect*)area, x, y, width, height, true, true); } else { drawBorder(cr, style, state, (QtcRect*)area, x, y, width, height, nullptr, (menuScroll || opts.square & SQUARE_FRAME ? ROUNDED_NONE : ROUNDED_ALL), shadowToBorder(shadow), wt, QTC_STD_BORDER); } } cairo_destroy(cr); } static void gtkDrawBox(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, const char *detail, int x, int y, int width, int height) { sanitizeSize(window, &width, &height); drawBox(style, window, state, shadow, area, widget, detail, x, y, width, height, state == GTK_STATE_ACTIVE || shadow == GTK_SHADOW_IN); } static void gtkDrawShadow(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; sanitizeSize(window, &width, &height); cairo_t *cr = Cairo::gdkCreateClip(window, area); bool comboBoxList = isComboBoxList(widget); bool comboList = !comboBoxList && isComboList(widget); if (comboBoxList || comboList) { bool square = opts.square & SQUARE_POPUP_MENUS; if ((!square || opts.popupBorder) && (!comboList || noneOf(detail, "viewport"))) { bool nonGtk = square || isFakeGtk(); bool composActive = !nonGtk && compositingActive(widget); bool isAlphaWidget = (!nonGtk && composActive && isRgbaWidget(widget)); bool useAlpha = !nonGtk && qtSettings.useAlpha && isAlphaWidget; if (opts.popupBorder && square) { Cairo::rect(cr, (QtcRect*)area, x, y, width, height, &style->base[state]); cairo_new_path(cr); cairo_rectangle(cr, x + 0.5, y + 0.5, width - 1, height - 1); Cairo::setColor(cr, &qtcPalette.background[QTC_STD_BORDER]); cairo_stroke(cr); } else /* if (!opts.popupBorder || */ /* !(opts.square & SQUARE_POPUP_MENUS)) */ { if (useAlpha) { cairo_rectangle(cr, x, y, width, height); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_set_source_rgba(cr, 0, 0, 0, 1); cairo_fill(cr); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); clearRoundedMask(widget, false); } else { createRoundedMask(widget, x, y, width, height, opts.round >= ROUND_FULL ? 5.0 : 2.5, false); } Cairo::clipWhole(cr, x, y, width, height, opts.round >= ROUND_FULL ? 5.0 : 2.5, ROUNDED_ALL); Cairo::rect(cr, (QtcRect*)area, x, y, width, height, &style->base[state]); if(useAlpha) cairo_set_operator(cr, CAIRO_OPERATOR_OVER); if (opts.popupBorder) { Cairo::pathWhole(cr, x + 0.5, y + 0.5, width - 1, height - 1, (opts.round >= ROUND_FULL ? 5.0 : 2.5) - 1, ROUNDED_ALL); Cairo::setColor(cr, &qtcPalette.background[QTC_STD_BORDER]); cairo_stroke(cr); } } } else { Cairo::rect(cr, (QtcRect*)area, x, y, width, height, &style->base[state]); } } else if(!opts.gtkComboMenus && !isMozilla() && isComboFrame(widget)) { GdkColor newColors[TOTAL_SHADES + 1]; GdkColor *btnColors; int bgnd = getFill(state, false); // TODO!!! btnDown??? bool sunken = //btnDown || (GTK_IS_BUTTON(widget) && qtcButtonIsDepressed(widget)) || state == GTK_STATE_ACTIVE || oneOf(bgnd, 2, 3); GtkWidget *parent = gtk_widget_get_parent(widget); GtkWidget *mapped = parent ? WidgetMap::getWidget(parent, 0) : nullptr; if(parent && ComboBox::isHovered(parent)) state=GTK_STATE_PRELIGHT; if(QT_CUSTOM_COLOR_BUTTON(style)) { shadeColors(&style->bg[state], newColors); btnColors=newColors; } else btnColors=qtcPalette.button[GTK_STATE_INSENSITIVE==state ? PAL_DISABLED : PAL_ACTIVE]; drawLightBevel(cr, style, state, (QtcRect*)area, x, y, width + 4, height, &btnColors[bgnd], btnColors, ROUNDED_LEFT, WIDGET_TOOLBAR_BUTTON, BORDER_FLAT, (sunken ? DF_SUNKEN : 0) | DF_DO_BORDER | (ComboBox::hasFocus(widget, mapped) ? DF_HAS_FOCUS : 0), widget); if(GTK_STATE_PRELIGHT!=state) { if(mapped && GTK_STATE_PRELIGHT==gtk_widget_get_state(mapped)) state=GTK_STATE_PRELIGHT, gtk_widget_set_state(widget, GTK_STATE_PRELIGHT); } if(mapped && GTK_STATE_INSENSITIVE!=gtk_widget_get_state(widget)) gtk_widget_queue_draw(mapped); WidgetMap::setup(parent, widget, 1); ComboBox::setup(widget, parent); } else if (oneOf(detail, "entry", "text")) { GtkWidget *parent=widget ? gtk_widget_get_parent(widget) : nullptr; if (parent && isList(parent)) { // Dont draw shadow for entries in listviews... // Fixes RealPlayer's in-line editing of its favourites. } else { bool combo = isComboBoxEntry(widget); bool isSpin = !combo && isSpinButton(widget); bool rev = reverseLayout(widget) || (combo && parent && reverseLayout(parent)); GtkWidget *btn = nullptr; /* GtkStateType savedState = state; */ #if GTK_CHECK_VERSION(2, 16, 0) #if !GTK_CHECK_VERSION(2, 90, 0) /* Gtk3:TODO !!! */ if (isSpin && widget && width == Widget::getAllocation(widget).width) { int btnWidth, dummy; gdk_drawable_get_size(GTK_SPIN_BUTTON(widget)->panel, &btnWidth, &dummy); width-=btnWidth; if(rev) x+=btnWidth; } #endif #endif if((opts.unifySpin && isSpin) || (combo && opts.unifyCombo)) width+=(combo ? 4 : 2); // If we're a combo entry, and not prelight, check to see if the button is // prelighted, if so so are we! if(GTK_STATE_PRELIGHT!=state && combo && opts.unifyCombo && parent) { btn=getComboButton(parent); if (!btn && parent) { btn = WidgetMap::getWidget(parent, 0); } if(btn && GTK_STATE_PRELIGHT==gtk_widget_get_state(btn)) state=GTK_STATE_PRELIGHT, gtk_widget_set_state(widget, GTK_STATE_PRELIGHT); } #if GTK_CHECK_VERSION(2, 90, 0) if(!opts.unifySpin && isSpin) width-=16; #endif drawEntryField(cr, style, state, window, widget, (QtcRect*)area, x, y, width, height, combo || isSpin ? rev ? ROUNDED_RIGHT : ROUNDED_LEFT : ROUNDED_ALL, WIDGET_ENTRY); if(combo && opts.unifyCombo && parent) { if(btn && GTK_STATE_INSENSITIVE!=gtk_widget_get_state(widget)) gtk_widget_queue_draw(btn); if (QTC_COMBO_ENTRY(parent)) { WidgetMap::setup(parent, widget, 1); } } } } else { bool frame = !_detail || strcmp(detail, "frame") == 0; bool scrolledWindow = oneOf(detail, "scrolled_window"); bool viewport = !scrolledWindow && strstr(detail, "viewport"); bool drawSquare = ((frame && opts.square & SQUARE_FRAME) || (!viewport && !scrolledWindow && !_detail && !widget)); bool statusBar = (isFakeGtk() ? frame : isStatusBarFrame(widget)); bool checkScrollViewState = (opts.highlightScrollViews && widget && GTK_IS_SCROLLED_WINDOW(widget)); bool isHovered = false; bool hasFocus = false; GdkColor *cols = nullptr; if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %s ", __FUNCTION__, state, shadow, x, y, width, height, _detail); debugDisplayWidget(widget, 10); } if(scrolledWindow && GTK_SHADOW_IN!=shadow && widget && GTK_IS_SCROLLED_WINDOW(widget) && GTK_IS_TREE_VIEW(gtk_bin_get_child(GTK_BIN(widget)))) gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(widget), GTK_SHADOW_IN), shadow=GTK_SHADOW_IN; else if(frame && !statusBar && GTK_IS_FRAME(widget)) { /* check for scrolled windows embedded in frames, that contain a treeview. if found, change the shadowtypes for consistency with normal -sunken- scrolled windows. this should improve rendering of most mandriva drake tools */ GtkWidget *child=gtk_bin_get_child(GTK_BIN(widget)); if(GTK_IS_SCROLLED_WINDOW(child) && GTK_IS_TREE_VIEW(gtk_bin_get_child(GTK_BIN(child)))) { gtk_frame_set_shadow_type(GTK_FRAME(widget), GTK_SHADOW_NONE); shadow=GTK_SHADOW_NONE; // also change scrolled window shadow if needed GtkScrolledWindow *sw=GTK_SCROLLED_WINDOW(child); if(GTK_SHADOW_IN!=gtk_scrolled_window_get_shadow_type(sw)) gtk_scrolled_window_set_shadow_type(sw, GTK_SHADOW_IN); } } if (checkScrollViewState) { ScrolledWindow::setup(widget); isHovered = ScrolledWindow::hovered(widget); hasFocus = !isHovered && ScrolledWindow::hasFocus(widget); } cols=isHovered ? qtcPalette.mouseover : hasFocus ? qtcPalette.focus : qtcPalette.background; if(!statusBar && !drawSquare && (frame || scrolledWindow || viewport/* || drawSquare*/)) // && ROUNDED) { if (shadow != GTK_SHADOW_NONE && (!frame || opts.drawStatusBarFrames || !isFakeGtk())) { GtkWidget *parent = (widget ? gtk_widget_get_parent(widget) : nullptr); bool doBorder = !viewport && !drawSquare; bool windowFrame = (parent && !isFixedWidget(widget) && GTK_IS_FRAME(widget) && GTK_IS_WINDOW(parent)); if (windowFrame) { QtcRect wAlloc = Widget::getAllocation(widget); QtcRect pAlloc = Widget::getAllocation(parent); windowFrame = Rect::equal(wAlloc, pAlloc); } // if(!drawSquare && widget && gtk_widget_get_parent(widget) && !isFixedWidget(widget) && // GTK_IS_FRAME(widget) && GTK_IS_WINDOW(gtk_widget_get_parent(widget))) // drawSquare=true; if(scrolledWindow) { /* See code in qt_settings.c as to isMozill part */ if((opts.square&SQUARE_SCROLLVIEW && !opts.highlightScrollViews) || isMozillaWidget(widget)) { /* Flat style... drawBorder(cr, style, state, area, x, y, width, height, nullptr, ROUNDED_NONE, BORDER_FLAT, WIDGET_SCROLLVIEW, 0); */ /* 3d... */ Cairo::setColor(cr, &cols[QTC_STD_BORDER]); Cairo::pathTopLeft(cr, x + 0.5, y + 0.5, width - 1, height - 1, 0.0, ROUNDED_NONE); cairo_stroke(cr); if(!opts.gtkScrollViews) Cairo::setColor(cr, &cols[QTC_STD_BORDER], LOWER_BORDER_ALPHA); /* Cairo::setColor(cr, &qtcPalette.background[ */ /* STD_BORDER_BR]); */ Cairo::pathBottomRight(cr, x + 0.5, y + 0.5, width - 1, height - 1, 0, ROUNDED_NONE); cairo_stroke(cr); doBorder=false; } else if (opts.etchEntry) { drawEtch(cr, (QtcRect*)area, widget, x, y, width, height, false, ROUNDED_ALL, WIDGET_SCROLLVIEW); x++; y++; width -= 2; height -= 2; } } if (viewport || windowFrame/* || drawSquare*/) { cairo_new_path(cr); cairo_rectangle(cr, x + 0.5, y + 0.5, width - 1, height - 1); if (windowFrame) { Cairo::setColor(cr, &cols[QTC_STD_BORDER]); } else { Cairo::setColor(cr, &cols[ORIGINAL_SHADE]); } cairo_stroke(cr); } else if(doBorder) drawBorder(cr, style, state, (QtcRect*)area, x, y, width, height, cols, ROUNDED_ALL, scrolledWindow ? BORDER_SUNKEN : BORDER_FLAT, scrolledWindow ? WIDGET_SCROLLVIEW : WIDGET_FRAME, DF_BLEND); } } else if (!statusBar || opts.drawStatusBarFrames) { int c1 = 0; int c2 = 0; switch(shadow) { case GTK_SHADOW_NONE: - if (statusBar) { - shadow = GTK_SHADOW_IN; - } else { + if (!statusBar) break; - } + shadow = GTK_SHADOW_IN; + /* FALLTHROUGH */ case GTK_SHADOW_IN: case GTK_SHADOW_ETCHED_IN: c1 = 0; c2 = QTC_STD_BORDER; break; case GTK_SHADOW_OUT: case GTK_SHADOW_ETCHED_OUT: c1 = QTC_STD_BORDER; c2 = 0; break; } switch(shadow) { case GTK_SHADOW_NONE: if (!frame) { cairo_new_path(cr); cairo_rectangle(cr, x + 0.5, y + 0.5, width - 1, height - 1); Cairo::setColor(cr, &cols[QTC_STD_BORDER]); cairo_stroke(cr); } break; case GTK_SHADOW_IN: case GTK_SHADOW_OUT: // if(drawSquare || frame || !ROUNDED) { double c2Alpha = shadow == GTK_SHADOW_IN ? 1.0 : LOWER_BORDER_ALPHA; double c1Alpha = shadow == GTK_SHADOW_OUT ? 1.0 : LOWER_BORDER_ALPHA; Cairo::hLine(cr, x, y, width, &cols[QTC_STD_BORDER], c2Alpha); Cairo::vLine(cr, x, y, height, &cols[QTC_STD_BORDER], c2Alpha); if (opts.appearance != APPEARANCE_FLAT) { Cairo::hLine(cr, x, y + height - 1, width, &cols[QTC_STD_BORDER], c1Alpha); Cairo::vLine(cr, x + width - 1, y, height, &cols[QTC_STD_BORDER], c1Alpha); } break; } case GTK_SHADOW_ETCHED_IN: cairo_new_path(cr); cairo_rectangle(cr, x + 1.5, y + 1.5, width - 2, height - 2); Cairo::setColor(cr, &cols[c1]); cairo_stroke(cr); cairo_new_path(cr); cairo_rectangle(cr, x + 0.5, y + 0.5, width - 2, height - 2); Cairo::setColor(cr, &cols[c2]); cairo_stroke(cr); break; case GTK_SHADOW_ETCHED_OUT: cairo_new_path(cr); cairo_rectangle(cr, x + 1.5, y + 1.5, width - 2, height - 2); Cairo::setColor(cr, &cols[c2]); cairo_stroke(cr); cairo_new_path(cr); cairo_rectangle(cr, x + 0.5, y + 0.5, width - 2, height - 2); Cairo::setColor(cr, &cols[c1]); cairo_stroke(cr); break; } } } cairo_destroy(cr); } // static gboolean isHoveredCell(GtkWidget *widget, int x, int y, int width, int height) // { // gboolean hovered=false; // // if(widget && GTK_IS_TREE_VIEW(widget)) // { // GtkTreePath *path=nullptr; // GtkTreeViewColumn *column=nullptr; // // qtcTreeViewSetup(widget); // qtcTreeViewGetCell(GTK_TREE_VIEW(widget), &path, &column, x, y, width, height); // hovered=path && qtcTreeViewIsCellHovered(widget, path, column); // } // // return hovered; // } static void gtkDrawCheck(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; QtcRect *area = (QtcRect*)_area; cairo_t *cr = Cairo::gdkCreateClip(window, area); drawCheckBox(cr, state, shadow, style, widget, detail, area, x, y, width, height); cairo_destroy(cr); } static void gtkDrawOption(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; QtcRect *area = (QtcRect*)_area; cairo_t *cr = Cairo::gdkCreateClip(window, area); drawRadioButton(cr, state, shadow, style, widget, detail, area, x, y, width, height); cairo_destroy(cr); } #define NUM_GCS 5 static void drawLayout(cairo_t *cr, GtkStyle *style, GtkStateType state, bool use_text, const QtcRect *area, int x, int y, PangoLayout *layout) { Cairo::layout(cr, area, x, y, layout, use_text || state == GTK_STATE_INSENSITIVE ? &style->text[state] : &style->fg[state]); } static void gtkDrawLayout(GtkStyle *style, GdkWindow *window, GtkStateType state, gboolean use_text, GdkRectangle *_area, GtkWidget *widget, const char *_detail, int x, int y, PangoLayout *layout) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; const QtcRect *area = (QtcRect*)_area; cairo_t *cr = gdk_cairo_create(window); if (GTK_IS_PROGRESS(widget) || oneOf(detail, "progressbar")) { drawLayout(cr, style, state, use_text, area, x, y, layout); } else { Style *qtc_style = (Style*)style; bool isMenuItem = isMenuitem(widget); GtkMenuBar *mb = isMenuItem ? isMenubar(widget, 0) : nullptr; bool activeMb = mb ? GTK_MENU_SHELL(mb)->active : false; bool selectedText = ((opts.useHighlightForMenu || opts.customMenuTextColor) && isMenuItem && (opts.colorMenubarMouseOver ? state == GTK_STATE_PRELIGHT : ((!mb || activeMb) && state == GTK_STATE_PRELIGHT))); bool def_but = false; bool but = isOnButton(widget, 0, &def_but); bool swapColors = false; QtcRect area2; GtkWidget *parent = widget ? gtk_widget_get_parent(widget) : nullptr; if (!opts.colorMenubarMouseOver && mb && !activeMb && state == GTK_STATE_PRELIGHT) state = GTK_STATE_NORMAL; GdkColor prevColors[NUM_GCS]; if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %s %d %d %d %d %d %s ", __FUNCTION__, pango_layout_get_text(layout), x, y, state, use_text, isMenuitem(widget), _detail); debugDisplayWidget(widget, 10); } if (oneOf(detail, "cellrenderertext") && widget && gtk_widget_get_state(widget) == GTK_STATE_INSENSITIVE) state = GTK_STATE_INSENSITIVE; #ifndef READ_INACTIVE_PAL /* If we reead the inactive palette, then there is no need for the following... The following fixes the text in list views... if not used, when an item is selected it gets the selected text color - but when the window changes focus it gets the normal text color! */ if (oneOf(detail, "cellrenderertext") && state == GTK_STATE_ACTIVE) state = GTK_STATE_SELECTED; #endif if (!isMenuItem && state == GTK_STATE_PRELIGHT) state = GTK_STATE_NORMAL; if (!use_text && parent && GTK_IS_LABEL(widget) && (isOnOptionMenu(parent, 0) || (GTK_IS_BUTTON(parent) && isOnMenuItem(parent, 0)))) { use_text = true; } /* This check of 'requisition' size (and not 'allocation') seems to match better with Qt4's text positioning. For example, 10pt verdana - no shift is required 9pt DejaVu Sans requires the shift */ if (but && widget) { GtkRequisition req = Widget::getRequisition(widget); if (req.height < Widget::getAllocation(widget).height && req.height % 2) { y++; } } but = but || isOnComboBox(widget, 0); if (isOnListViewHeader(widget, 0)) y--; if (but && ((qtSettings.qt4 && state == GTK_STATE_INSENSITIVE) || (!qtSettings.qt4 && state != GTK_STATE_INSENSITIVE))) { use_text = true; swapColors = true; for (int i = 0;i < NUM_GCS;++i) { prevColors[i] = style->text[i]; style->text[i] = *qtc_style->button_text[state == GTK_STATE_INSENSITIVE ? PAL_DISABLED : PAL_ACTIVE]; } if (state == GTK_STATE_INSENSITIVE) { state = GTK_STATE_NORMAL; } } else if (isMenuItem) { bool activeWindow = (mb && opts.shadeMenubarOnlyWhenActive && widget ? Window::isActive(gtk_widget_get_toplevel(widget)) : true); if ((opts.shadePopupMenu && state == GTK_STATE_PRELIGHT) || (mb && (activeWindow || opts.shadeMenubars == SHADE_WINDOW_BORDER))) { if (opts.shadeMenubars == SHADE_WINDOW_BORDER) { for (int i = 0;i < NUM_GCS;i++) { prevColors[i] = style->text[i]; } swapColors = true; style->text[GTK_STATE_NORMAL] = *qtc_style->menutext[activeWindow ? 1 : 0]; use_text = true; } else if (opts.customMenuTextColor && qtc_style->menutext[0]) { for (int i = 0;i < NUM_GCS;i++) { prevColors[i] = style->text[i]; } swapColors = true; style->text[GTK_STATE_NORMAL] = *qtc_style->menutext[0]; style->text[GTK_STATE_ACTIVE] = *qtc_style->menutext[1]; style->text[GTK_STATE_PRELIGHT] = *qtc_style->menutext[0]; style->text[GTK_STATE_SELECTED] = *qtc_style->menutext[1]; style->text[GTK_STATE_INSENSITIVE] = *qtc_style->menutext[0]; use_text = true; } else if (oneOf(opts.shadeMenubars, SHADE_BLEND_SELECTED, SHADE_SELECTED) || (opts.shadeMenubars == SHADE_CUSTOM && TOO_DARK(qtcPalette.menubar[ORIGINAL_SHADE]))) { selectedText = true; } } } if (parent && GTK_IS_LABEL(widget) && GTK_IS_FRAME(parent) && !isOnStatusBar(widget, 0)) { int diff = (Widget::getAllocation(widget).x - Widget::getAllocation(parent).x); if (qtcNoFrame(opts.groupBox)) { x -= qtcBound(0, diff, 8); } else if (opts.gbLabel&GB_LBL_OUTSIDE) { x -= qtcBound(0, diff, 4); } else if(opts.gbLabel&GB_LBL_INSIDE) { x -= qtcBound(0, diff, 2); } else { x += 5; } #if GTK_CHECK_VERSION(2, 90, 0) cairo_reset_clip(cr); #else if (area) { area2 = *area; if (qtcNoFrame(opts.groupBox)) { area2.x -= qtcBound(0, diff, 8); } else if (opts.gbLabel & GB_LBL_OUTSIDE) { area2.x -= qtcBound(0, diff, 4); } else if(opts.gbLabel&GB_LBL_INSIDE) { area2.x -= qtcBound(0, diff, 2); } else { area2.x += 5; } area = &area2; } #endif } if (!opts.useHighlightForMenu && (isMenuItem || mb) && state != GTK_STATE_INSENSITIVE) state = GTK_STATE_NORMAL; drawLayout(cr, style, selectedText ? GTK_STATE_SELECTED : state, use_text || selectedText, area, x, y, layout); if (opts.embolden && def_but) { drawLayout(cr, style, selectedText ? GTK_STATE_SELECTED : state, use_text || selectedText, area, x + 1, y, layout); } if (swapColors) { for (int i = 0;i < 5;++i) { style->text[i] = prevColors[i]; } } } cairo_destroy(cr); } static GdkPixbuf* gtkRenderIcon(GtkStyle *style, const GtkIconSource *source, GtkTextDirection, GtkStateType state, GtkIconSize size, GtkWidget *widget, const char*) { return renderIcon(style, source, state, size, widget); } static void gtkDrawTab(GtkStyle*, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height) { QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %s ", __FUNCTION__, state, shadow, _detail); debugDisplayWidget(widget, 10); } const QtcRect *area = (QtcRect*)_area; cairo_t *cr = gdk_cairo_create(window); const GdkColor *arrowColor = MO_ARROW(false, &qtSettings.colors[state == GTK_STATE_INSENSITIVE ? PAL_DISABLED : PAL_ACTIVE][COLOR_BUTTON_TEXT]); if (isActiveOptionMenu(widget)) { x++; y++; } x = (reverseLayout(widget) || ((widget = gtk_widget_get_parent(widget)) && reverseLayout(widget)) ? x + 1 : x + width / 2); if (opts.doubleGtkComboArrow) { int pad = opts.vArrows ? 0 : 1; Cairo::arrow(cr, arrowColor, area, GTK_ARROW_UP, x, y + height / 2 - (LARGE_ARR_HEIGHT - pad), false, true, opts.vArrows); Cairo::arrow(cr, arrowColor, area, GTK_ARROW_DOWN, x, y + height / 2 + (LARGE_ARR_HEIGHT - pad), false, true, opts.vArrows); } else { Cairo::arrow(cr, arrowColor, area, GTK_ARROW_DOWN, x, y + height / 2, false, true, opts.vArrows); } cairo_destroy(cr); } static void gtkDrawBoxGap(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType, GdkRectangle *area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height, GtkPositionType gapSide, int gapX, int gapWidth) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; cairo_t *cr = Cairo::gdkCreateClip(window, area); if ((opts.thin & THIN_FRAMES) && gapX == 0) { gapX--; gapWidth += 2; } sanitizeSize(window, &width, &height); drawBoxGap(cr, style, GTK_SHADOW_OUT, state, widget, (QtcRect*)area, x, y, width, height, gapSide, gapX, gapWidth, opts.borderTab ? BORDER_LIGHT : BORDER_RAISED, true); if (opts.windowDrag > WM_DRAG_MENU_AND_TOOLBAR && oneOf(detail, "notebook")) { WMMove::setup(widget); } if (!isMozilla()) drawBoxGapFixes(cr, widget, x, y, width, height, gapSide, gapX, gapWidth); cairo_destroy(cr); } static void gtkDrawExtension(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height, GtkPositionType gapSide) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %d %s ", __FUNCTION__, state, shadow, gapSide, x, y, width, height, _detail); debugDisplayWidget(widget, 10); } sanitizeSize(window, &width, &height); if (oneOf(detail, "tab")) { QtcRect *area = (QtcRect*)_area; cairo_t *cr = Cairo::gdkCreateClip(window, area); drawTab(cr, state, style, widget, area, x, y, width, height, gapSide); cairo_destroy(cr); } else { parent_class->draw_extension(style, window, state, shadow, _area, widget, _detail, x, y, width, height, gapSide); } } static void gtkDrawSlider(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height, GtkOrientation orientation) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; bool scrollbar = oneOf(detail, "slider"); bool scale = oneOf(detail, "hscale", "vscale"); if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %d %d %d %d %s ", __FUNCTION__, state, shadow, x, y, width, height, _detail); debugDisplayWidget(widget, 10); } cairo_t *cr = Cairo::gdkCreateClip(window, area); sanitizeSize(window, &width, &height); if (scrollbar || SLIDER_TRIANGULAR!=opts.sliderStyle) { GdkColor newColors[TOTAL_SHADES + 1]; GdkColor *btnColors = qtcPalette.background; int min = MIN_SLIDER_SIZE(opts.sliderThumbs); #ifdef INCREASE_SB_SLIDER if (scrollbar) lastSlider.widget = nullptr; #endif /* Fix Java swing sliders looking pressed */ if(!scrollbar && GTK_STATE_ACTIVE==state) state=GTK_STATE_PRELIGHT; // FIXME, need to update useButtonColor if the logic below changes if (useButtonColor(detail)) { if(scrollbar|scale && GTK_STATE_INSENSITIVE==state) btnColors=qtcPalette.background; else if(QT_CUSTOM_COLOR_BUTTON(style)) { shadeColors(&style->bg[state], newColors); btnColors=newColors; } else SET_BTN_COLS(scrollbar, scale, false, state) } #ifdef INCREASE_SB_SLIDER if(scrollbar && !opts.flatSbarButtons && SHADE_NONE!=opts.shadeSliders && SCROLLBAR_NONE!=opts.scrollbarType && !isMozilla()) { lastSlider.style=style; #if GTK_CHECK_VERSION(2, 90, 0) lastSlider.cr=cr; #else lastSlider.window=window; #endif lastSlider.state=state; lastSlider.shadow=shadow; lastSlider.widget=widget; lastSlider.detail=detail; lastSlider.x=x; lastSlider.y=y; lastSlider.width=width; lastSlider.height=height; lastSlider.orientation=orientation; } #endif #if GTK_CHECK_VERSION(2, 90, 0) if(scrollbar && GTK_STATE_ACTIVE==state) state=GTK_STATE_PRELIGHT; #endif drawBox(style, window, state, shadow, area, widget, !scrollbar ? "qtc-slider" : "slider", x, y, width, height, false); /* Orientation is always vertical with Mozilla, why? Anyway this hack should be OK - as we only draw dashes when slider is larger than 'min' pixels... */ orientation = (width < height ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL); if (opts.sliderThumbs != LINE_NONE && (scrollbar || opts.sliderStyle != SLIDER_CIRCULAR) && (scale || ((orientation == GTK_ORIENTATION_HORIZONTAL && width >= min) || height >= min))) { GdkColor *markers=/*opts.coloredMouseOver && GTK_STATE_PRELIGHT==state ? qtcPalette.mouseover : */btnColors; bool horiz = orientation == GTK_ORIENTATION_HORIZONTAL; if (opts.sliderThumbs == LINE_SUNKEN) { if (horiz) { y--; height++; } else { x--; width++; } } else if (horiz) { x++; } else { y++; } switch (opts.sliderThumbs) { case LINE_1DOT: Cairo::dot(cr, x, y, width, height, &markers[QTC_STD_BORDER]); break; case LINE_FLAT: drawLines(cr, x, y, width, height, !horiz, 3, 5, markers, (QtcRect*)area, 5, opts.sliderThumbs); break; case LINE_SUNKEN: drawLines(cr, x, y, width, height, !horiz, 4, 3, markers, (QtcRect*)area, 3, opts.sliderThumbs); break; default: case LINE_DOTS: Cairo::dots(cr, x, y, width, height, !horiz, scale ? 3 : 5, scale ? 4 : 2, (QtcRect*)area, 0, &markers[5], markers); } } } else { drawTriangularSlider(cr, style, state, detail, x, y, width, height); } cairo_destroy(cr); } static void gtkDrawShadowGap(GtkStyle *style, GdkWindow *window, GtkStateType state, GtkShadowType shadow, GdkRectangle *_area, GtkWidget *widget, const char*, int x, int y, int width, int height, GtkPositionType gapSide, int gapX, int gapWidth) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); QtcRect *area = (QtcRect*)_area; cairo_t *cr = Cairo::gdkCreateClip(window, area); sanitizeSize(window, &width, &height); drawShadowGap(cr, style, shadow, state, widget, area, x, y, width, height, gapSide, gapX, gapWidth); cairo_destroy(cr); } static void gtkDrawHLine(GtkStyle *style, GdkWindow *window, GtkStateType state, GdkRectangle *area, GtkWidget *widget, const char *_detail, int x1, int x2, int y) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; bool tbar = strcmp(detail, "toolbar"); int light = 0; int dark = tbar ? (opts.toolbarSeparators == LINE_FLAT ? 4 : 3) : 5; if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %d %d %s ", __FUNCTION__, state, x1, x2, y, _detail); debugDisplayWidget(widget, 10); } cairo_t *cr = Cairo::gdkCreateClip(window, area); if (tbar) { switch (opts.toolbarSeparators) { default: case LINE_DOTS: Cairo::dots(cr, x1, y, x2 - x1, 2, false, (x2 - x1) / 3.0 + 0.5, 0, (QtcRect*)area, 0, &qtcPalette.background[5], qtcPalette.background); break; case LINE_NONE: break; case LINE_FLAT: case LINE_SUNKEN: { drawFadedLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), 1, &qtcPalette.background[dark], (QtcRect*)area, nullptr, true, true, true); /* Cairo::hLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), */ /* &qtcPalette.background[dark]); */ if(LINE_SUNKEN==opts.toolbarSeparators) { cairo_new_path(cr); /* Cairo::hLine(cr, x1 < x2 ? x1 : x2, y + 1, abs(x2 - x1), */ /* &qtcPalette.background[light]); */ drawFadedLine(cr, x1 < x2 ? x1 : x2, y + 1, abs(x2 - x1), 1, &qtcPalette.background[light], (QtcRect*)area, nullptr, true, true, true); } } } } else if (oneOf(detail, "label")) { if (state == GTK_STATE_INSENSITIVE) { /* Cairo::hLine(cr, (x1 < x2 ? x1 : x2) + 1, y + 1, abs(x2 - x1), */ /* &qtcPalette.background[light]); */ drawFadedLine(cr, x1 < x2 ? x1 : x2, y + 1, abs(x2 - x1), 1, &qtcPalette.background[light], (QtcRect*)area, nullptr, true, true, true); } /* Cairo::hLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), */ /* &style->text[state]); */ drawFadedLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), 1, &qtcPalette.background[dark], (QtcRect*)area, nullptr, true, true, true); } else if (oneOf(detail, "menuitem") || (widget && oneOf(detail, "hseparator") && isMenuitem(widget))) { int offset=opts.menuStripe && (isMozilla() || (widget && GTK_IS_MENU_ITEM(widget))) ? 20 : 0; GdkColor *cols=qtcPalette.background; if(offset && isFakeGtk()) offset+=2; if (opts.lighterPopupMenuBgnd || opts.shadePopupMenu) { cols = qtcPalette.menu; } if (offset && isFakeGtk()) { offset += 2; } /* Cairo::hLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), */ /* &qtcPalette.background[MENU_SEP_SHADE]); */ drawFadedLine(cr, offset + (x1 < x2 ? x1 : x2), y + 1, abs(x2 - x1) - offset, 1, &cols[MENU_SEP_SHADE], (QtcRect*)area, nullptr, true, true, true); } else { /* Cairo::hLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), */ /* qtcPalette.background[dark]); */ drawFadedLine(cr, x1 < x2 ? x1 : x2, y, abs(x2 - x1), 1, &qtcPalette.background[dark], (QtcRect*)area, nullptr, true, true, true); } cairo_destroy(cr); } static void gtkDrawVLine(GtkStyle *style, GdkWindow *window, GtkStateType state, GdkRectangle *area, GtkWidget *widget, const char *_detail, int y1, int y2, int x) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); const char *detail = _detail ? _detail : ""; if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %d %d %s ", __FUNCTION__, state, x, y1, y2, _detail); debugDisplayWidget(widget, 10); } cairo_t *cr = Cairo::gdkCreateClip(window, area); if (!(oneOf(detail, "vseparator") && isOnComboBox(widget, 0))) { /* CPD: Combo handled in drawBox */ bool tbar = oneOf(detail, "toolbar"); int dark = tbar ? 3 : 5; int light = 0; if (tbar) { switch (opts.toolbarSeparators) { default: case LINE_DOTS: Cairo::dots(cr, x, y1, 2, y2 - y1, true, (y2 - y1) / 3.0 + 0.5, 0, (QtcRect*)area, 0, &qtcPalette.background[5], qtcPalette.background); break; case LINE_NONE: break; case LINE_FLAT: case LINE_SUNKEN: /* Cairo::vLine(cr, x, y1 < y2 ? y1 : y2, abs(y2 - y1), */ /* &qtcPalette.background[dark]); */ drawFadedLine(cr, x, y1 < y2 ? y1 : y2, 1, abs(y2 - y1), &qtcPalette.background[dark], (QtcRect*)area, nullptr, true, true, false); if (opts.toolbarSeparators == LINE_SUNKEN) /* Cairo::vLine(cr, x + 1, y1 < y2 ? y1 : y2, */ /* abs(y2 - y1), */ /* &qtcPalette.background[light]); */ drawFadedLine(cr, x + 1, y1 < y2 ? y1 : y2, 1, abs(y2 - y1), &qtcPalette.background[light], (QtcRect*)area, nullptr, true, true, false); } } else { /* Cairo::vLine(cr, x, y1 < y2 ? y1 : y2, abs(y2 - y1), */ /* &qtcPalette.background[dark]); */ drawFadedLine(cr, x, y1 < y2 ? y1 : y2, 1, abs(y2 - y1), &qtcPalette.background[dark], (QtcRect*)area, nullptr, true, true, false); } } cairo_destroy(cr); } static void gtkDrawFocus(GtkStyle *style, GdkWindow *window, GtkStateType state, GdkRectangle *area, GtkWidget *widget, const char *_detail, int x, int y, int width, int height) { if (opts.focus == FOCUS_NONE) { return; } if (GTK_IS_EDITABLE(widget)) return; QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); sanitizeSize(window, &width, &height); if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %d %d %d %d %s ", __FUNCTION__, state, x, y, width, height, _detail); debugDisplayWidget(widget, 10); } GtkWidget *parent = widget ? gtk_widget_get_parent(widget) : nullptr; bool doEtch = opts.buttonEffect != EFFECT_NONE; bool btn = false; bool comboButton = false; bool rev = parent && reverseLayout(parent); bool view = isList(widget); bool listViewHeader = isListViewHeader(widget); bool toolbarBtn = (!listViewHeader && !view && isButtonOnToolbar(widget, nullptr)); if (opts.comboSplitter && noneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED) && isComboBox(widget)) { /* x++; */ /* y++; */ /* height -= 2; */ width += 2; /* Remove if re-add the above */ if (widget && rev) { x += 20; } width -= 22; if (isGimpCombo(widget)) { x += 2; y += 2; width -= 4; height -= 4; } btn = true; } #if !GTK_CHECK_VERSION(2, 90, 0) else if (GTK_IS_OPTION_MENU(widget)) { if ((!opts.comboSplitter || oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)) && widget) { QtcRect alloc = Widget::getAllocation(widget); if (alloc.width > width) { width = alloc.width - (doEtch ? 8 : 4); } } x++; y++; width -= 2; height -= 2; btn = true; } #endif if (isComboBoxEntryButton(widget)) { #if GTK_CHECK_VERSION(2, 90, 0) if (doEtch) { x -= 2; y++; width += 3; height -= 2; } else { x -= 2; width += 4; } #else if (doEtch) { x++; y += 2; width -= 3; height -= 4; } else { x++; y++; width -= 2; height -= 2; } #endif comboButton = true; btn = true; } else if (isGimpCombo(widget)) { if (opts.focus == FOCUS_GLOW) { return; } x -= 2; width += 4; if (!doEtch) { x--; y--; width += 2; height += 2; } } else if (GTK_IS_BUTTON(widget)) { if (GTK_IS_RADIO_BUTTON(widget) || GTK_IS_CHECK_BUTTON(widget)) { // Gimps buttons in its toolbox are const char *text = nullptr; toolbarBtn = (qtSettings.app == GTK_APP_GIMP && ((text = gtk_button_get_label(GTK_BUTTON(widget))) == nullptr || text[0] == '\0')); if (!toolbarBtn && opts.focus == FOCUS_GLOW && !isMozilla()) { return; } if (toolbarBtn) { if (qtSettings.app == GTK_APP_GIMP && opts.focus == FOCUS_GLOW && toolbarBtn) { x -= 2; width += 4; y -= 1; height += 2; } } #if 0 /* Removed in 1.7.2 */ else { if (opts.focus == FOCUS_LINE) { height--; } else if (oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)) { y--; x -= 3; width += 6; height += 2; if (!doEtch) { y--; x--; width += 2; height += 2; } } } #endif } else if (opts.focus == FOCUS_GLOW && toolbarBtn) { x -= 2; width += 4; y -= 2; height += 4; } else { if (doEtch) { x--; width += 2; } else { x -= 2; width += 4; } if (doEtch && (opts.thin & THIN_BUTTONS)) { y++; height -= 2; } btn = true; } } if (state == GTK_STATE_PRELIGHT && opts.coloredMouseOver != MO_NONE && oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED) && !listViewHeader && (btn || comboButton)) { return; } if (opts.focus == FOCUS_GLOW && !comboButton && !listViewHeader && !toolbarBtn && (btn || GTK_IS_SCALE(widget))) { return; } if (opts.focus == FOCUS_GLOW && toolbarBtn && state != GTK_STATE_NORMAL) { return; } if (opts.focus == FOCUS_STANDARD) { parent_class->draw_focus(style, window, state, area, widget, _detail, x, y, width, height); } else { bool drawRounded = (opts.round != ROUND_NONE); GdkColor *col = (view && state == GTK_STATE_SELECTED ? &style->text[state] : &qtcPalette.focus[FOCUS_SHADE(state == GTK_STATE_SELECTED)]); cairo_t *cr = Cairo::gdkCreateClip(window, area); if (qtSettings.app == GTK_APP_JAVA_SWT && view && widget && GTK_IS_TREE_VIEW(widget)) { GtkTreeView *treeView = GTK_TREE_VIEW(widget); GtkTreePath *path = nullptr; GtkTreeViewColumn *column = nullptr; GtkTreeViewColumn *expanderColumn = gtk_tree_view_get_expander_column(treeView); TreeView::getCell(treeView, &path, &column, x, y, width, height); if (column == expanderColumn) { int expanderSize = 0; gtk_widget_style_get(widget, "expander-size", &expanderSize, nullptr); if (expanderSize > 0) { int depth = path ? (int)gtk_tree_path_get_depth(path) : 0; int offset = (3 + expanderSize * depth + (4 + gtk_tree_view_get_level_indentation(treeView)) * (depth - 1)); x += offset; width -= offset; } } if (path) { gtk_tree_path_free(path); } } if (oneOf(opts.focus, FOCUS_LINE, FOCUS_GLOW)) { if (view || listViewHeader) { height -= 2; } drawFadedLine(cr, x, y + height - 1, width, 1, col, (QtcRect*)area, nullptr, true, true, true); } else { /* double alpha = (opts.focus == FOCUS_GLOW ? */ /* FOCUS_GLOW_LINE_ALPHA : 1.0); */ if (width < 3 || height < 3) { drawRounded = false; } cairo_new_path(cr); if (isListViewHeader(widget)) { btn = false; y++; x++; width -= 2; height -= 3; } if (oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)) { if (btn) { if (toolbarBtn) { x -= 2; y -= 2; width += 4; height += 4; if (!doEtch) { x -= 2; width += 4; y--; height += 2; } } else if (!widget || !(GTK_IS_RADIO_BUTTON(widget) || GTK_IS_CHECK_BUTTON(widget))) { /* 1.7.2 - dont asjust fot check/radio */ x -= 3; y -= 3; width += 6; height += 6; } } if (opts.focus == FOCUS_FILLED) { if (drawRounded) { Cairo::pathWhole(cr, x + 0.5, y + 0.5, width - 1, height - 1, qtcGetRadius(&opts, width, height, WIDGET_OTHER, RADIUS_EXTERNAL), comboButton ? (rev ? ROUNDED_LEFT : ROUNDED_RIGHT) : ROUNDED_ALL); } else { cairo_rectangle(cr, x + 0.5, y + 0.5, width - 1, height - 1); } Cairo::setColor(cr, col, FOCUS_ALPHA); cairo_fill(cr); cairo_new_path(cr); } } if (drawRounded) { Cairo::pathWhole(cr, x + 0.5, y + 0.5, width - 1, height - 1, (view && opts.square & SQUARE_LISTVIEW_SELECTION) && opts.round != ROUND_NONE ? SLIGHT_INNER_RADIUS : qtcGetRadius(&opts, width, height, WIDGET_OTHER, oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED) ? RADIUS_EXTERNAL : RADIUS_SELECTION), oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED) && comboButton ? (rev ? ROUNDED_LEFT : ROUNDED_RIGHT) : ROUNDED_ALL); } else { cairo_rectangle(cr, x+0.5, y+0.5, width-1, height-1); } /* Cairo::setColor(cr, col, alpha); */ Cairo::setColor(cr, col); cairo_stroke(cr); } cairo_destroy(cr); } } static void gtkDrawResizeGrip(GtkStyle *style, GdkWindow *window, GtkStateType state, GdkRectangle *_area, GtkWidget *widget, const char *_detail, GdkWindowEdge edge, int x, int y, int width, int height) { QTC_RET_IF_FAIL(GTK_IS_STYLE(style)); QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); QtcRect *area = (QtcRect*)_area; cairo_t *cr = Cairo::gdkCreateClip(window, area); int size = SIZE_GRIP_SIZE - 2; /* Clear background */ if (qtcIsFlatBgnd(opts.bgndAppearance) || !(widget && drawWindowBgnd(cr, style, area, window, widget, x, y, width, height))) { if (widget && opts.bgndImage.type != IMG_NONE) { drawWindowBgnd(cr, style, area, window, widget, x, y, width, height); } } switch (edge) { case GDK_WINDOW_EDGE_SOUTH_EAST: { // Adjust Firefox's resize grip so that it can be completely covered // by QtCurve's KWin resize grip. if (isMozilla()) { x++; y++; } const GdkPoint a[] = {{x + width, y + height - size}, {x + width, y + height}, {x + width - size, y + height}}; Cairo::polygon(cr, &qtcPalette.background[2], area, a, 3, true); break; } case GDK_WINDOW_EDGE_SOUTH_WEST: { const GdkPoint a[] = {{x + width - size, y + height - size}, {x + width, y + height}, {x + width - size, y + height}}; Cairo::polygon(cr, &qtcPalette.background[2], area, a, 3, true); break; } case GDK_WINDOW_EDGE_NORTH_EAST: // TODO!! case GDK_WINDOW_EDGE_NORTH_WEST: // TODO!! default: parent_class->draw_resize_grip(style, window, state, _area, widget, _detail, edge, x, y, width, height); } cairo_destroy(cr); } static void gtkDrawExpander(GtkStyle *style, GdkWindow *window, GtkStateType state, GdkRectangle *_area, GtkWidget *widget, const char *_detail, int x, int y, GtkExpanderStyle expander_style) { QTC_RET_IF_FAIL(GDK_IS_DRAWABLE(window)); if (qtSettings.debug == DEBUG_ALL) { printf(DEBUG_PREFIX "%s %d %s ", __FUNCTION__, state, _detail); debugDisplayWidget(widget, 10); } QtcRect *area = (QtcRect*)_area; cairo_t *cr = gdk_cairo_create(window); bool isExpander = widget && (GTK_IS_EXPANDER(widget) || GTK_IS_TREE_VIEW(widget)); bool fill = (!isExpander || opts.coloredMouseOver || state != GTK_STATE_PRELIGHT); const GdkColor *col = (isExpander && opts.coloredMouseOver && state == GTK_STATE_PRELIGHT ? &qtcPalette.mouseover[ARROW_MO_SHADE] : &style->text[ARROW_STATE(state)]); x -= LV_SIZE / 2.0 + 0.5; x += 2; y -= LV_SIZE / 2.0 + 0.5; if (expander_style == GTK_EXPANDER_COLLAPSED) { Cairo::arrow(cr, col, area, reverseLayout(widget) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT, x + LARGE_ARR_WIDTH / 2, y + LARGE_ARR_HEIGHT, false, fill, opts.vArrows); } else { Cairo::arrow(cr, col, area, GTK_ARROW_DOWN, x + LARGE_ARR_WIDTH / 2, y + LARGE_ARR_HEIGHT, false, fill, opts.vArrows); } cairo_destroy(cr); } static void styleRealize(GtkStyle *style) { Style *qtc_style = (Style*)style; parent_class->realize(style); qtc_style->button_text[PAL_ACTIVE] = &qtSettings.colors[PAL_ACTIVE][COLOR_BUTTON_TEXT]; qtc_style->button_text[PAL_DISABLED] = (qtSettings.qt4 ? &qtSettings.colors[PAL_DISABLED][COLOR_BUTTON_TEXT] : &style->text[GTK_STATE_INSENSITIVE]); if (opts.shadeMenubars == SHADE_WINDOW_BORDER) { qtc_style->menutext[0] = &qtSettings.colors[PAL_INACTIVE][COLOR_WINDOW_BORDER_TEXT]; qtc_style->menutext[1] = &qtSettings.colors[PAL_ACTIVE][COLOR_WINDOW_BORDER_TEXT]; } else if (opts.customMenuTextColor) { qtc_style->menutext[0] = &opts.customMenuNormTextColor; qtc_style->menutext[1] = &opts.customMenuSelTextColor; } else { qtc_style->menutext[0] = nullptr; } } static void styleUnrealize(GtkStyle *style) { parent_class->unrealize(style); } static void style_init_from_rc(GtkStyle *style, GtkRcStyle *rc_style) { parent_class->init_from_rc(style, rc_style); } -static void -style_class_init(StyleClass *klass) +static void style_class_init(void *_klass, void*) { + StyleClass *klass = (StyleClass*)_klass; GtkStyleClass *style_class = GTK_STYLE_CLASS(klass); parent_class = (GtkStyleClass*)g_type_class_peek_parent(klass); style_class->realize = styleRealize; style_class->unrealize = styleUnrealize; style_class->init_from_rc = style_init_from_rc; style_class->draw_resize_grip = gtkDrawResizeGrip; style_class->draw_expander = gtkDrawExpander; style_class->draw_arrow = gtkDrawArrow; style_class->draw_tab = gtkDrawTab; style_class->draw_shadow = gtkDrawShadow; style_class->draw_box_gap = gtkDrawBoxGap; style_class->draw_extension = gtkDrawExtension; style_class->draw_handle = gtkDrawHandle; style_class->draw_box = gtkDrawBox; style_class->draw_flat_box = gtkDrawFlatBox; style_class->draw_check = gtkDrawCheck; style_class->draw_slider = gtkDrawSlider; style_class->draw_option = gtkDrawOption; style_class->draw_shadow_gap = gtkDrawShadowGap; style_class->draw_hline = gtkDrawHLine; style_class->draw_vline = gtkDrawVLine; style_class->draw_focus = gtkDrawFocus; style_class->draw_layout = gtkDrawLayout; style_class->render_icon = gtkRenderIcon; } static GtkRcStyleClass *parent_rc_class; static unsigned rc_style_parse(GtkRcStyle*, GtkSettings*, GScanner *scanner) { unsigned old_scope; unsigned token; /* Set up a new scope in this scanner. */ static GQuark scope_id = g_quark_from_string("qtcurve_theme_engine"); /* If we bail out due to errors, we *don't* reset the scope, so the error messaging code can make sense of our tokens. */ old_scope = g_scanner_set_scope(scanner, scope_id); token = g_scanner_peek_next_token(scanner); while (token != G_TOKEN_RIGHT_CURLY) { switch (token) { default: g_scanner_get_next_token(scanner); token = G_TOKEN_RIGHT_CURLY; } if (token != G_TOKEN_NONE) return token; token = g_scanner_peek_next_token(scanner); } g_scanner_get_next_token(scanner); g_scanner_set_scope(scanner, old_scope); return G_TOKEN_NONE; } static void rc_style_merge(GtkRcStyle *dest, GtkRcStyle *src) { GtkRcStyle copy; bool destIsQtc = isRcStyle(dest); bool srcIsQtc = (!src->name || Str::startsWith(src->name, RC_SETTING) || Str::startsWith(src->name, getProgName())); bool isQtCNoteBook = (opts.tabBgnd != 0 && src->name && oneOf(src->name, "qtcurve-notebook_bg")); bool dontChangeColors = destIsQtc && !srcIsQtc && !isQtCNoteBook && // Only allow GtkRcStyle and QtCurve::RcStyle to change colours // ...this should catch most cases whre another themes gtkrc is in the // GTK2_RC_FILES path (noneOf(gTypeName(src), "GtkRcStyle", "QtCurveRcStyle") || // If run as root (probably via kdesu/kdesudo) then dont allow KDE // settings to take effect - as these are sometimes from the user's // settings, not roots! (getuid() == 0 && src && src->name && oneOf(src->name, "ToolTip", "default"))); if (isQtCNoteBook) { qtcShade(&qtcPalette.background[ORIGINAL_SHADE], &src->bg[GTK_STATE_NORMAL], TO_FACTOR(opts.tabBgnd), opts.shading); } if(dontChangeColors) { memcpy(copy.color_flags, dest->color_flags, sizeof(GtkRcFlags)*5); memcpy(copy.fg, dest->fg, sizeof(GdkColor)*5); memcpy(copy.bg, dest->bg, sizeof(GdkColor)*5); memcpy(copy.text, dest->text, sizeof(GdkColor)*5); memcpy(copy.base, dest->base, sizeof(GdkColor)*5); } parent_rc_class->merge(dest, src); if(dontChangeColors) { memcpy(dest->color_flags, copy.color_flags, sizeof(GtkRcFlags)*5); memcpy(dest->fg, copy.fg, sizeof(GdkColor)*5); memcpy(dest->bg, copy.bg, sizeof(GdkColor)*5); memcpy(dest->text, copy.text, sizeof(GdkColor)*5); memcpy(dest->base, copy.base, sizeof(GdkColor)*5); } } /* Create an empty style suitable to this RC style */ static GtkStyle* rc_style_create_style(GtkRcStyle *rc_style) { GtkStyle *style = (GtkStyle*)g_object_new(style_type, nullptr); qtSettingsSetColors(style, rc_style); return style; } -static void style_init(Style*) +static void style_init(void*, void*) { Shadow::initialize(); } static void style_register_type(GTypeModule *module) { static const GTypeInfo object_info = { sizeof(StyleClass), (GBaseInitFunc)nullptr, (GBaseFinalizeFunc)nullptr, (GClassInitFunc)style_class_init, nullptr, /* class_finalize */ nullptr, /* class_data */ sizeof(Style), 0, /* n_preallocs */ (GInstanceInitFunc)style_init, nullptr }; style_type = g_type_module_register_type(module, GTK_TYPE_STYLE, "QtCurveStyle", &object_info, GTypeFlags(0)); } static gboolean style_set_hook(GSignalInvocationHint*, unsigned, const GValue *argv, void*) { GtkWidget *widget = GTK_WIDGET(g_value_get_object(argv)); GdkScreen *screen = gtk_widget_get_screen(widget); if (!screen) { return true; } #if GTK_CHECK_VERSION(3, 0, 0) GdkVisual *visual = nullptr; if (gtk_widget_is_toplevel(widget)) { visual = gdk_screen_get_rgba_visual(screen); } else if (GTK_IS_DRAWING_AREA(widget)) { visual = gdk_screen_get_system_visual(screen); } if (visual) { gtk_widget_set_visual(widget, visual); } #else GdkColormap *colormap = nullptr; if (gtk_widget_is_toplevel(widget)) { colormap = gdk_screen_get_rgba_colormap(screen); } else if (GTK_IS_DRAWING_AREA(widget)) { // For inkscape and flash (and probably others). // Inkscape's (at least the Gtk2 version) EekPreview widget // uses system default colormap instead of the one for the widget. // Not sure what's wrong with flash... colormap = gdk_screen_get_default_colormap(screen); } if (colormap) { gtk_widget_set_colormap(widget, colormap); } #endif return true; } static void -rc_style_init(RcStyle*) +rc_style_init(void*, void*s) { #ifdef INCREASE_SB_SLIDER lastSlider.widget = nullptr; #endif if (qtSettingsInit()) { generateColors(); if (qtSettings.useAlpha) { // Somehow GtkWidget is not loaded yet // when this function is called. g_type_class_ref(GTK_TYPE_WIDGET); g_signal_add_emission_hook( g_signal_lookup("style-set", GTK_TYPE_WIDGET), 0, style_set_hook, nullptr, nullptr); } } } static void rc_style_finalize(GObject *object) { Animation::cleanup(); qtcCall(G_OBJECT_CLASS(parent_rc_class)->finalize, object); } static void -rc_style_class_init(RcStyleClass *klass) +rc_style_class_init(void *_klass, void*) { + RcStyleClass *klass = (RcStyleClass*)_klass; GtkRcStyleClass *rc_style_class = GTK_RC_STYLE_CLASS(klass); GObjectClass *object_class = G_OBJECT_CLASS(klass); parent_rc_class = (GtkRcStyleClass*)g_type_class_peek_parent(klass); rc_style_class->parse = rc_style_parse; rc_style_class->create_style = rc_style_create_style; rc_style_class->merge = rc_style_merge; object_class->finalize = rc_style_finalize; } static void rc_style_register_type(GTypeModule *module) { static const GTypeInfo object_info = { sizeof(RcStyleClass), nullptr, nullptr, (GClassInitFunc)rc_style_class_init, nullptr, /* class_finalize */ nullptr, /* class_data */ sizeof(RcStyle), 0, /* n_preallocs */ (GInstanceInitFunc)rc_style_init, nullptr }; rc_style_type = g_type_module_register_type(module, GTK_TYPE_RC_STYLE, "QtCurveRcStyle", &object_info, GTypeFlags(0)); } } QTC_BEGIN_DECLS QTC_EXPORT void theme_init(GTypeModule *module) { qtcX11InitXlib(GDK_DISPLAY_XDISPLAY(gdk_display_get_default())); QtCurve::rc_style_register_type(module); QtCurve::style_register_type(module); } QTC_EXPORT void theme_exit() { } QTC_EXPORT GtkRcStyle* theme_create_rc_style() { return GTK_RC_STYLE(g_object_new(QtCurve::rc_style_type, nullptr)); } /* The following function will be called by GTK+ when the module is loaded and * checks to see if we are compatible with the version of GTK+ that loads us. */ QTC_EXPORT const char* g_module_check_init(GModule*) { return gtk_check_version(GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION - GTK_INTERFACE_AGE); } QTC_END_DECLS