+static void
+draw_box (GtkStyle *style,
+ cairo_t *cr,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GtkWidget *widget,
+ const gchar *detail, gint x, gint y, gint width, gint height)
+{
+ if (is_combo_box_child (widget) && detail && !strcmp (detail, "button"))
+ {
+ RECT rect;
+ XpDCInfo dc_info;
+ DWORD border;
+ HDC dc;
+ int cx;
+
+ border = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)) ? DFCS_PUSHED | DFCS_FLAT : 0);
+
+ dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
+ DrawFrameControl (dc, &rect, DFC_SCROLL, DFCS_SCROLLDOWN | border);
+ release_window_dc (&dc_info);
+
+ if (xp_theme_is_active ()
+ && xp_theme_draw (cr, XP_THEME_ELEMENT_COMBOBUTTON, style, x, y,
+ width, height, state_type))
+ {
+ cx = GetSystemMetrics(SM_CXVSCROLL);
+ x += width - cx;
+ width = cx;
+
+
+ dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width - cx, height, &rect);
+ FillRect (dc, &rect, GetSysColorBrush (COLOR_WINDOW));
+ release_window_dc (&dc_info);
+ return;
+ }
+ }
+
+ if (detail &&
+ (!strcmp (detail, "button") || !strcmp (detail, "buttondefault")))
+ {
+ if (GTK_IS_TREE_VIEW (gtk_widget_get_parent (widget)))
+ {
+ if (xp_theme_draw
+ (cr, XP_THEME_ELEMENT_LIST_HEADER, style, x, y,
+ width, height, state_type))
+ {
+ return;
+ }
+ else
+ {
+ HDC dc;
+ RECT rect;
+ XpDCInfo dc_info;
+ dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
+
+ DrawFrameControl (dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH |
+ (state_type ==
+ GTK_STATE_ACTIVE ? (DFCS_PUSHED | DFCS_FLAT)
+ : 0));
+ release_window_dc (&dc_info);
+ }
+ }
+ else if (is_toolbar_child (gtk_widget_get_parent (widget))
+ || (!GTK_IS_BUTTON (widget) ||
+ (GTK_RELIEF_NONE == gtk_button_get_relief (GTK_BUTTON (widget)))))
+ {
+ if (draw_tool_button (cr, widget, style, x, y,
+ width, height, state_type))
+ {
+ return;
+ }
+ }
+ else
+ {
+ gboolean is_default = gtk_widget_has_default (widget);
+ if (xp_theme_draw
+ (cr,
+ is_default ? XP_THEME_ELEMENT_DEFAULT_BUTTON :
+ XP_THEME_ELEMENT_BUTTON, style, x, y, width, height,
+ state_type))
+ {
+ return;
+ }
+
+ draw_push_button (cr, widget, style,
+ x, y, width, height, state_type, is_default);
+
+ return;
+ }
+
+ return;
+ }
+ else if (detail && !strcmp (detail, "spinbutton"))
+ {
+ if (xp_theme_is_drawable (XP_THEME_ELEMENT_SPIN_BUTTON_UP))
+ {
+ return;
+ }
+ }
+ else if (detail && (!strcmp (detail, "spinbutton_up")
+ || !strcmp (detail, "spinbutton_down")))
+ {
+ if (!xp_theme_draw (cr,
+ (!strcmp (detail, "spinbutton_up"))
+ ? XP_THEME_ELEMENT_SPIN_BUTTON_UP
+ : XP_THEME_ELEMENT_SPIN_BUTTON_DOWN,
+ style, x, y, width, height, state_type))
+ {
+ RECT rect;
+ XpDCInfo dc_info;
+ HDC dc;
+
+ dc = get_window_dc (style, cr, state_type, &dc_info,
+ x, y, width, height, &rect);
+ DrawEdge (dc, &rect,
+ state_type ==
+ GTK_STATE_ACTIVE ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT);
+ release_window_dc (&dc_info);
+ }
+ return;
+ }
+ else if (detail && !strcmp (detail, "slider"))
+ {
+ if (GTK_IS_SCROLLBAR (widget))
+ {
+ GtkScrollbar *scrollbar = GTK_SCROLLBAR (widget);
+ gboolean is_v = GTK_IS_VSCROLLBAR (widget);
+
+ if (xp_theme_draw (cr,
+ is_v
+ ? XP_THEME_ELEMENT_SCROLLBAR_V
+ : XP_THEME_ELEMENT_SCROLLBAR_H,
+ style, x, y, width, height, state_type))
+ {
+ XpThemeElement gripper =
+ (is_v ? XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V :
+ XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H);
+
+ /* Do not display grippers on tiny scroll bars,
+ the limit imposed is rather arbitrary, perhaps
+ we can fetch the gripper geometry from
+ somewhere and use that... */
+ if ((gripper ==
+ XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_H
+ && width < 16)
+ || (gripper ==
+ XP_THEME_ELEMENT_SCROLLBAR_GRIPPER_V && height < 16))
+ {
+ return;
+ }
+
+ xp_theme_draw (cr, gripper, style, x, y,
+ width, height, state_type);
+ return;
+ }
+ else
+ {
+ if (gtk_adjustment_get_page_size(gtk_range_get_adjustment(&scrollbar->range)) >=
+ (gtk_adjustment_get_page_size(gtk_range_get_adjustment(&scrollbar->range)) -
+ gtk_adjustment_get_page_size(gtk_range_get_adjustment(&scrollbar->range))))
+ {
+ return;
+ }
+ }
+ }
+ }
+ else if (detail && !strcmp (detail, "bar"))
+ {
+ if (widget && GTK_IS_PROGRESS_BAR (widget))
+ {
+ GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
+ XpThemeElement xp_progress_bar =
+ map_gtk_progress_bar_to_xp (progress_bar, FALSE);
+
+ if (xp_theme_draw (cr, xp_progress_bar, style, x, y,
+ width, height, state_type))
+ {
+ return;
+ }
+
+ shadow_type = GTK_SHADOW_NONE;
+ }
+ }
+ else if (detail && strcmp (detail, "menuitem") == 0)
+ {
+ shadow_type = GTK_SHADOW_NONE;
+ if (draw_menu_item (cr, widget, style,
+ x, y, width, height, state_type))
+ {
+ return;
+ }
+ }
+ else if (detail && !strcmp (detail, "trough"))
+ {
+ if (widget && GTK_IS_PROGRESS_BAR (widget))
+ {
+ GtkProgressBar *progress_bar = GTK_PROGRESS_BAR (widget);
+ XpThemeElement xp_progress_bar =
+ map_gtk_progress_bar_to_xp (progress_bar, TRUE);
+ if (xp_theme_draw
+ (cr, xp_progress_bar, style, x, y, width, height,
+ state_type))
+ {
+ return;
+ }
+ else
+ {
+ /* Blank in classic Windows */
+ }
+ }
+ else if (widget && GTK_IS_SCROLLBAR (widget))
+ {
+ gboolean is_vertical = GTK_IS_VSCROLLBAR (widget);
+
+ if (xp_theme_draw (cr,
+ is_vertical
+ ? XP_THEME_ELEMENT_TROUGH_V
+ : XP_THEME_ELEMENT_TROUGH_H,
+ style, x, y, width, height, state_type))
+ {
+ return;
+ }
+ else
+ {
+ HDC dc;
+ RECT rect;
+ XpDCInfo dc_info;
+
+ dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
+
+ SetTextColor (dc, GetSysColor (COLOR_3DHILIGHT));
+ SetBkColor (dc, GetSysColor (COLOR_BTNFACE));
+ FillRect (dc, &rect, get_dither_brush ());
+
+ release_window_dc (&dc_info);
+
+ return;
+ }
+ }
+ else if (widget && GTK_IS_SCALE (widget))
+ {
+ gboolean is_vertical = GTK_IS_VSCALE (widget);
+
+ if (!xp_theme_is_active ())
+ {
+ parent_class->draw_box (style, cr, state_type,
+ GTK_SHADOW_NONE,
+ widget, detail, x, y, width, height);
+ }
+
+ if (is_vertical)
+ {
+ if (xp_theme_draw
+ (cr, XP_THEME_ELEMENT_SCALE_TROUGH_V,
+ style, (2 * x + width) / 2, y, 2, height,
+ state_type))
+ {
+ return;
+ }
+
+ parent_class->draw_box (style, cr, state_type,
+ GTK_SHADOW_ETCHED_IN,
+ NULL, NULL,
+ (2 * x + width) / 2, y, 1, height);
+ }
+ else
+ {
+ if (xp_theme_draw
+ (cr, XP_THEME_ELEMENT_SCALE_TROUGH_H,
+ style, x, (2 * y + height) / 2, width, 2,
+ state_type))
+ {
+ return;
+ }
+
+ parent_class->draw_box (style, cr, state_type,
+ GTK_SHADOW_ETCHED_IN,
+ NULL, NULL, x,
+ (2 * y + height) / 2, width, 1);
+ }
+
+ return;
+ }
+ }
+ else if (detail && strcmp (detail, "optionmenu") == 0)
+ {
+ if (xp_theme_draw (cr, XP_THEME_ELEMENT_EDIT_TEXT,
+ style, x, y, width, height, state_type))
+ {
+ return;
+ }
+ }
+ else if (detail
+ && (strcmp (detail, "vscrollbar") == 0
+ || strcmp (detail, "hscrollbar") == 0))
+ {
+ return;
+ }
+ else if (detail
+ && (strcmp (detail, "handlebox_bin") == 0
+ || strcmp (detail, "toolbar") == 0
+ || strcmp (detail, "menubar") == 0))
+ {
+ if (xp_theme_draw (cr, XP_THEME_ELEMENT_REBAR,
+ style, x, y, width, height, state_type))
+ {
+ return;
+ }
+ }
+ else if (detail && (!strcmp (detail, "handlebox"))) /* grip */
+ {
+ if (!xp_theme_is_active ())
+ {
+ return;
+ }
+ }
+ else if (detail && !strcmp (detail, "notebook") && GTK_IS_NOTEBOOK (widget))
+ {
+ if (xp_theme_draw (cr, XP_THEME_ELEMENT_TAB_PANE, style,
+ x, y, width, height, state_type))
+ {
+ return;
+ }
+ }
+
+ else
+ {
+ const gchar *name = gtk_widget_get_name (widget);
+
+ if (name && !strcmp (name, "gtk-tooltips"))
+ {
+ if (xp_theme_draw
+ (cr, XP_THEME_ELEMENT_TOOLTIP, style, x, y, width,
+ height, state_type))
+ {
+ return;
+ }
+ else
+ {
+ HBRUSH brush;
+ RECT rect;
+ XpDCInfo dc_info;
+ HDC hdc;
+
+ hdc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
+
+ brush = GetSysColorBrush (COLOR_3DDKSHADOW);
+
+ if (brush)
+ {
+ FrameRect (hdc, &rect, brush);
+ }
+
+ InflateRect (&rect, -1, -1);
+ FillRect (hdc, &rect, (HBRUSH) (COLOR_INFOBK + 1));
+
+ release_window_dc (&dc_info);
+
+ return;
+ }
+ }
+ }
+
+ parent_class->draw_box (style, cr, state_type, shadow_type,
+ widget, detail, x, y, width, height);
+
+ if (detail && strcmp (detail, "optionmenu") == 0)
+ {
+ GtkRequisition indicator_size;
+ GtkBorder indicator_spacing;
+ gint vline_x;
+
+ option_menu_get_props (widget, &indicator_size, &indicator_spacing);
+
+ if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+ {
+ vline_x =
+ x + indicator_size.width + indicator_spacing.left +
+ indicator_spacing.right;
+ }
+ else
+ {
+ vline_x = x + width - (indicator_size.width +
+ indicator_spacing.left +
+ indicator_spacing.right) - style->xthickness;
+
+ parent_class->draw_vline (style, cr, state_type, widget,
+ detail,
+ y + style->ythickness + 1,
+ y + height - style->ythickness - 3, vline_x);
+ }
+ }
+}
+
+static void
+draw_tab (GtkStyle *style,
+ cairo_t *cr,
+ GtkStateType state,
+ GtkShadowType shadow,
+ GtkWidget *widget,
+ const gchar *detail, gint x, gint y, gint width, gint height)
+{
+ GtkRequisition indicator_size;
+ GtkBorder indicator_spacing;
+
+ gint arrow_height;
+
+ g_return_if_fail (style != NULL);
+ g_return_if_fail (cr != NULL);
+
+ if (detail && !strcmp (detail, "optionmenutab"))
+ {
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (widget, &allocation);
+ if (xp_theme_draw (cr, XP_THEME_ELEMENT_COMBOBUTTON,
+ style, x - 5, allocation.y + 1,
+ width + 10, allocation.height - 2,
+ state))
+ {
+ return;
+ }
+ }
+
+ option_menu_get_props (widget, &indicator_size, &indicator_spacing);
+
+ x += (width - indicator_size.width) / 2;
+ arrow_height = (indicator_size.width + 1) / 2;
+
+ y += (height - arrow_height) / 2;
+
+ draw_varrow (cr, &style->black, shadow, GTK_ARROW_DOWN,
+ x, y, indicator_size.width, arrow_height);
+}
+
+/* Draw classic Windows tab - thanks Mozilla!
+ (no system API for this, but DrawEdge can draw all the parts of a tab) */
+static void
+DrawTab (HDC hdc, const RECT R, gint32 aPosition, gboolean aSelected,
+ gboolean aDrawLeft, gboolean aDrawRight)
+{
+ gint32 leftFlag, topFlag, rightFlag, lightFlag, shadeFlag;
+ RECT topRect, sideRect, bottomRect, lightRect, shadeRect;
+ gint32 selectedOffset, lOffset, rOffset;
+
+ selectedOffset = aSelected ? 1 : 0;
+ lOffset = aDrawLeft ? 2 : 0;
+ rOffset = aDrawRight ? 2 : 0;
+
+ /* Get info for tab orientation/position (Left, Top, Right, Bottom) */
+ switch (aPosition)
+ {
+ case BF_LEFT:
+ leftFlag = BF_TOP;
+ topFlag = BF_LEFT;
+ rightFlag = BF_BOTTOM;
+ lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
+ shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
+
+ SetRect (&topRect, R.left, R.top + lOffset, R.right,
+ R.bottom - rOffset);
+ SetRect (&sideRect, R.left + 2, R.top, R.right - 2 + selectedOffset,
+ R.bottom);
+ SetRect (&bottomRect, R.right - 2, R.top, R.right, R.bottom);
+ SetRect (&lightRect, R.left, R.top, R.left + 3, R.top + 3);
+ SetRect (&shadeRect, R.left + 1, R.bottom - 2, R.left + 2,
+ R.bottom - 1);
+ break;
+
+ case BF_TOP:
+ leftFlag = BF_LEFT;
+ topFlag = BF_TOP;
+ rightFlag = BF_RIGHT;
+ lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
+ shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
+
+ SetRect (&topRect, R.left + lOffset, R.top, R.right - rOffset,
+ R.bottom);
+ SetRect (&sideRect, R.left, R.top + 2, R.right,
+ R.bottom - 1 + selectedOffset);
+ SetRect (&bottomRect, R.left, R.bottom - 1, R.right, R.bottom);
+ SetRect (&lightRect, R.left, R.top, R.left + 3, R.top + 3);
+ SetRect (&shadeRect, R.right - 2, R.top + 1, R.right - 1, R.top + 2);
+ break;
+
+ case BF_RIGHT:
+ leftFlag = BF_TOP;
+ topFlag = BF_RIGHT;
+ rightFlag = BF_BOTTOM;
+ lightFlag = BF_DIAGONAL_ENDTOPLEFT;
+ shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
+
+ SetRect (&topRect, R.left, R.top + lOffset, R.right,
+ R.bottom - rOffset);
+ SetRect (&sideRect, R.left + 2 - selectedOffset, R.top, R.right - 2,
+ R.bottom);
+ SetRect (&bottomRect, R.left, R.top, R.left + 2, R.bottom);
+ SetRect (&lightRect, R.right - 3, R.top, R.right - 1, R.top + 2);
+ SetRect (&shadeRect, R.right - 2, R.bottom - 3, R.right, R.bottom - 1);
+ break;
+
+ case BF_BOTTOM:
+ leftFlag = BF_LEFT;
+ topFlag = BF_BOTTOM;
+ rightFlag = BF_RIGHT;
+ lightFlag = BF_DIAGONAL_ENDTOPLEFT;
+ shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
+
+ SetRect (&topRect, R.left + lOffset, R.top, R.right - rOffset,
+ R.bottom);
+ SetRect (&sideRect, R.left, R.top + 2 - selectedOffset, R.right,
+ R.bottom - 2);
+ SetRect (&bottomRect, R.left, R.top, R.right, R.top + 2);
+ SetRect (&lightRect, R.left, R.bottom - 3, R.left + 2, R.bottom - 1);
+ SetRect (&shadeRect, R.right - 2, R.bottom - 3, R.right, R.bottom - 1);
+ break;
+
+ default:
+ g_return_if_reached ();
+ }
+
+ /* Background */
+ FillRect (hdc, &R, (HBRUSH) (COLOR_3DFACE + 1));
+
+ /* Tab "Top" */
+ DrawEdge (hdc, &topRect, EDGE_RAISED, BF_SOFT | topFlag);
+
+ /* Tab "Bottom" */
+ if (!aSelected)
+ DrawEdge (hdc, &bottomRect, EDGE_RAISED, BF_SOFT | topFlag);
+
+ /* Tab "Sides" */
+ if (!aDrawLeft)
+ leftFlag = 0;
+ if (!aDrawRight)
+ rightFlag = 0;
+
+ DrawEdge (hdc, &sideRect, EDGE_RAISED, BF_SOFT | leftFlag | rightFlag);
+
+ /* Tab Diagonal Corners */
+ if (aDrawLeft)
+ DrawEdge (hdc, &lightRect, EDGE_RAISED, BF_SOFT | lightFlag);
+
+ if (aDrawRight)
+ DrawEdge (hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag);
+}
+
+static gboolean
+draw_themed_tab_button (GtkStyle *style,
+ cairo_t *cr,
+ GtkStateType state_type,
+ GtkNotebook *notebook,
+ gint x, gint y,
+ gint width, gint height, gint gap_side)
+{
+/* FIXME: poop
+ GdkPixmap *pixmap = NULL;
+ */
+ gint border_width =
+ gtk_container_get_border_width (GTK_CONTAINER (notebook));
+ GtkWidget *widget = GTK_WIDGET (notebook);
+ GdkRectangle draw_rect;
+ GdkPixbufRotation rotation = GDK_PIXBUF_ROTATE_NONE;
+ GtkAllocation allocation;
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ if (gap_side == GTK_POS_TOP)
+ {
+ int widget_right;
+
+ if (state_type == GTK_STATE_NORMAL)
+ {
+ draw_rect.x = x;
+ draw_rect.y = y;
+ draw_rect.width = width + 2;
+ draw_rect.height = height;
+
+/* FIXME: wtf?
+ clip_rect.height--;
+ */
+ }
+ else
+ {
+ draw_rect.x = x + 2;
+ draw_rect.y = y;
+ draw_rect.width = width - 2;
+ draw_rect.height = height - 2;
+ }
+
+ /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
+ widget_right = allocation.x + allocation.width - border_width - 2;
+
+ if (draw_rect.x + draw_rect.width >= widget_right)
+ {
+ draw_rect.width = widget_right - draw_rect.x;
+ }
+ }
+ if (gap_side == GTK_POS_BOTTOM)
+ {
+ int widget_right;
+
+ if (state_type == GTK_STATE_NORMAL)
+ {
+ draw_rect.x = x;
+ draw_rect.y = y;
+ draw_rect.width = width + 2;
+ draw_rect.height = height;
+ }
+ else
+ {
+ draw_rect.x = x + 2;
+ draw_rect.y = y + 2;
+ draw_rect.width = width - 2;
+ draw_rect.height = height - 2;
+ }
+
+ /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */
+ widget_right = allocation.x + allocation.width - border_width - 2;
+
+ if (draw_rect.x + draw_rect.width >= widget_right)
+ {
+ draw_rect.width = widget_right - draw_rect.x;
+ }
+
+ rotation = GDK_PIXBUF_ROTATE_UPSIDEDOWN;
+ }
+ else if (gap_side == GTK_POS_LEFT)
+ {
+ int widget_bottom;
+
+ if (state_type == GTK_STATE_NORMAL)
+ {
+ draw_rect.x = x;
+ draw_rect.y = y;
+ draw_rect.width = width;
+ draw_rect.height = height + 2;
+
+/* FIXME: wtf?
+ clip_rect.width--;
+ */
+ }
+ else
+ {
+ draw_rect.x = x;
+ draw_rect.y = y + 2;
+ draw_rect.width = width - 2;
+ draw_rect.height = height - 2;
+ }
+
+ /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
+ widget_bottom = allocation.x + allocation.height - border_width - 2;
+
+ if (draw_rect.y + draw_rect.height >= widget_bottom)
+ {
+ draw_rect.height = widget_bottom - draw_rect.y;
+ }
+
+ rotation = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE;
+ }
+ else if (gap_side == GTK_POS_RIGHT)
+ {
+ int widget_bottom;
+
+ if (state_type == GTK_STATE_NORMAL)
+ {
+ draw_rect.x = x + 1;
+ draw_rect.y = y;
+ draw_rect.width = width;
+ draw_rect.height = height + 2;
+
+/* FIXME: wtf?
+ clip_rect.width--;
+ */
+ }
+ else
+ {
+ draw_rect.x = x + 2;
+ draw_rect.y = y + 2;
+ draw_rect.width = width - 2;
+ draw_rect.height = height - 2;
+ }
+
+ /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */
+ widget_bottom = allocation.x + allocation.height - border_width - 2;
+
+ if (draw_rect.y + draw_rect.height >= widget_bottom)
+ {
+ draw_rect.height = widget_bottom - draw_rect.y;
+ }
+
+ rotation = GDK_PIXBUF_ROTATE_CLOCKWISE;
+ }
+
+ if (gap_side == GTK_POS_TOP)
+ {
+ if (!xp_theme_draw (cr, XP_THEME_ELEMENT_TAB_ITEM, style,
+ draw_rect.x, draw_rect.y,
+ draw_rect.width, draw_rect.height,
+ state_type))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+/* FIXME: poop */
+#if 0
+ GdkPixbuf *pixbuf;
+ GdkPixbuf *rotated;
+
+ if (gap_side == GTK_POS_LEFT || gap_side == GTK_POS_RIGHT)
+ {
+ pixmap = gdk_pixmap_new (cr, draw_rect.height, draw_rect.width, -1);
+
+ if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
+/* FIXME: wtf? */
+ draw_rect.y - draw_rect.y, draw_rect.x - draw_rect.x,
+ draw_rect.height, draw_rect.width, state_type, 0))
+ {
+ g_object_unref (pixmap);
+ return FALSE;
+ }
+
+ pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
+ draw_rect.height, draw_rect.width);
+ g_object_unref (pixmap);
+ }
+ else
+ {
+ pixmap = gdk_pixmap_new (cr, draw_rect.width, draw_rect.height, -1);
+
+ if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style,
+/* FIXME: wtf? */
+ draw_rect.x - draw_rect.x, draw_rect.y - draw_rect.y,
+ draw_rect.width, draw_rect.height, state_type, 0))
+ {
+ g_object_unref (pixmap);
+ return FALSE;
+ }
+
+ pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0,
+ draw_rect.width, draw_rect.height);
+ g_object_unref (pixmap);
+ }
+
+ rotated = gdk_pixbuf_rotate_simple (pixbuf, rotation);
+ g_object_unref (pixbuf);
+ pixbuf = rotated;
+
+ // XXX - This is really hacky and evil. When we're drawing the left-most tab
+ // while it is active on a bottom-oriented notebook, there is one white
+ // pixel at the top. There may be a better solution than this if someone
+ // has time to discover it.
+ if (gap_side == GTK_POS_BOTTOM && state_type == GTK_STATE_NORMAL
+ && x == allocation.x)
+ {
+ int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+ int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+ int psub = 0;
+
+ guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
+ guchar *p = pixels + rowstride;
+
+ for (psub = 0; psub < n_channels; psub++)
+ {
+ pixels[psub] = p[psub];
+ }
+ }
+
+ gdk_cairo_set_source_pixbuf (cr, pixbuf, clip_rect.x, clip_rect.y);
+ cairo_paint (cr);
+ g_object_unref (pixbuf);
+#endif
+ }
+
+ return TRUE;
+}
+
+static gboolean
+draw_tab_button (GtkStyle *style,
+ cairo_t *cr,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GtkWidget *widget,
+ const gchar *detail,
+ gint x, gint y, gint width, gint height, gint gap_side)
+{
+ if (gap_side == GTK_POS_TOP || gap_side == GTK_POS_BOTTOM)
+ {
+ /* experimental tab-drawing code from mozilla */
+ RECT rect;
+ XpDCInfo dc_info;
+ HDC dc;
+ gint32 aPosition;
+
+ dc = get_window_dc (style, cr, state_type, &dc_info, x, y, width, height, &rect);
+
+ if (gap_side == GTK_POS_TOP)
+ aPosition = BF_TOP;
+ else if (gap_side == GTK_POS_BOTTOM)
+ aPosition = BF_BOTTOM;
+ else if (gap_side == GTK_POS_LEFT)
+ aPosition = BF_LEFT;
+ else
+ aPosition = BF_RIGHT;
+
+ if (state_type == GTK_STATE_PRELIGHT)
+ state_type = GTK_STATE_NORMAL;
+
+/* FIXME: wtf?
+ gdk_cairo_set_source_color (cr, &style->dark[state_type]);
+ */
+
+ DrawTab (dc, rect, aPosition,
+ state_type != GTK_STATE_PRELIGHT,
+ (gap_side != GTK_POS_LEFT), (gap_side != GTK_POS_RIGHT));
+
+ release_window_dc (&dc_info);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+draw_extension (GtkStyle *style,
+ cairo_t *cr,
+ GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GtkWidget *widget,
+ const gchar *detail,
+ gint x, gint y,
+ gint width, gint height, GtkPositionType gap_side)
+{
+ if (widget && GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "tab"))
+ {
+ GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+
+ /* draw_themed_tab_button and draw_tab_button expect to work with tab
+ * position, instead of simply taking the "side of the gap" (gap_side)
+ * which simply said is the side of the tab that touches the notebook
+ * frame and is always the exact opposite of the gap side... */
+ int tab_pos = gtk_notebook_get_tab_pos (notebook);
+
+ if (!draw_themed_tab_button (style, cr, state_type,
+ notebook, x, y,
+ width, height, tab_pos))
+ {
+ if (!draw_tab_button (style, cr, state_type,
+ shadow_type, widget,
+ detail, x, y, width, height, tab_pos))
+ {
+ /* GtkStyle expects the usual gap_side */
+ parent_class->draw_extension (style, cr, state_type,
+ shadow_type, widget, detail,
+ x, y, width, height,
+ gap_side);
+ }
+ }
+ }
+}
+
+static void
+draw_box_gap (GtkStyle *style, cairo_t *cr, GtkStateType state_type,
+ GtkShadowType shadow_type,
+ GtkWidget *widget, const gchar *detail, gint x,
+ gint y, gint width, gint height, GtkPositionType gap_side,
+ gint gap_x, gint gap_width)
+{
+ if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "notebook"))
+ {
+ GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+ int side = gtk_notebook_get_tab_pos (notebook);
+ int x2 = x, y2 = y, w2 = width, h2 = height;
+
+ if (side == GTK_POS_TOP)
+ {
+ x2 = x;
+ y2 = y - gtk_notebook_get_tab_vborder (notebook);
+ w2 = width;
+ h2 = height + gtk_notebook_get_tab_vborder (notebook) * 2;
+ }
+ else if (side == GTK_POS_BOTTOM)
+ {
+ x2 = x;
+ y2 = y;
+ w2 = width;
+ h2 = height + gtk_notebook_get_tab_vborder (notebook) * 2;
+ }
+ else if (side == GTK_POS_LEFT)
+ {
+ x2 = x - gtk_notebook_get_tab_hborder (notebook);
+ y2 = y;
+ w2 = width + gtk_notebook_get_tab_hborder (notebook);
+ h2 = height;
+ }
+ else if (side == GTK_POS_RIGHT)
+ {
+ x2 = x;
+ y2 = y;
+ w2 = width + gtk_notebook_get_tab_hborder (notebook) * 2;
+ h2 = height;
+ }
+
+ if (xp_theme_draw (cr, XP_THEME_ELEMENT_TAB_PANE, style,
+ x2, y2, w2, h2, state_type))
+ {
+ return;
+ }
+ }
+
+ parent_class->draw_box_gap (style, cr, state_type, shadow_type,
+ widget, detail, x, y, width, height,
+ gap_side, gap_x, gap_width);
+}
+
+static gboolean
+is_popup_window_child (GtkWidget *widget)
+{
+ GtkWidget *top;
+ GtkWindowType type = -1;
+
+ top = gtk_widget_get_toplevel (widget);
+
+ if (top && GTK_IS_WINDOW (top))
+ {
+ g_object_get (top, "type", &type, NULL);
+
+ if (type == GTK_WINDOW_POPUP)
+ { /* Hack for combo boxes */
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+draw_flat_box (GtkStyle *style, cairo_t *cr,
+ GtkStateType state_type, GtkShadowType shadow_type,
+ GtkWidget *widget,
+ const gchar *detail, gint x, gint y, gint width, gint height)
+{
+ if (detail)
+ {
+ if (state_type == GTK_STATE_SELECTED &&
+ (!strncmp ("cell_even", detail, 9) || !strncmp ("cell_odd", detail, 8)))
+ {
+ GdkColor *gc = gtk_widget_has_focus (widget) ? &style->base[state_type] : &style->base[GTK_STATE_ACTIVE];
+
+ _cairo_draw_rectangle (cr, gc, TRUE, x, y, width, height);
+
+ return;
+ }
+ else if (!strcmp (detail, "checkbutton"))
+ {
+ if (state_type == GTK_STATE_PRELIGHT)
+ {
+ return;
+ }
+ }
+ }
+
+ parent_class->draw_flat_box (style, cr, state_type, shadow_type,
+ widget, detail, x, y, width, height);
+}
+
+static gboolean
+draw_menu_border (cairo_t *cr, GtkStyle *style,
+ gint x, gint y, gint width, gint height)
+{
+ RECT rect;
+ XpDCInfo dc_info;
+ HDC dc;
+
+ dc = get_window_dc (style, cr, GTK_STATE_NORMAL, &dc_info, x, y, width, height, &rect);
+
+ if (!dc)
+ return FALSE;
+
+ if (xp_theme_is_active ())
+ {
+ FrameRect (dc, &rect, GetSysColorBrush (COLOR_3DSHADOW));
+ }
+ else
+ {
+ DrawEdge (dc, &rect, EDGE_RAISED, BF_RECT);
+ }
+
+ release_window_dc (&dc_info);