File indexing completed on 2024-04-21 05:47:01
0001 /***************************************************************************** 0002 * Copyright 2003 - 2010 Craig Drummond <craig.p.drummond@gmail.com> * 0003 * Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com> * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU Lesser General Public License as * 0007 * published by the Free Software Foundation; either version 2.1 of the * 0008 * License, or (at your option) version 3, or any later version accepted * 0009 * by the membership of KDE e.V. (or its successor approved by the * 0010 * membership of KDE e.V.), which shall act as a proxy defined in * 0011 * Section 6 of version 3 of the license. * 0012 * * 0013 * This program is distributed in the hope that it will be useful, * 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 0016 * Lesser General Public License for more details. * 0017 * * 0018 * You should have received a copy of the GNU Lesser General Public * 0019 * License along with this library. If not, * 0020 * see <http://www.gnu.org/licenses/>. * 0021 *****************************************************************************/ 0022 0023 #include "scrolledwindow.h" 0024 0025 #include "qt_settings.h" 0026 0027 #include <qtcurve-utils/gtkprops.h> 0028 #include <qtcurve-cairo/utils.h> 0029 #include <common/common.h> 0030 0031 namespace QtCurve { 0032 namespace ScrolledWindow { 0033 0034 static void 0035 cleanup(GtkWidget *widget) 0036 { 0037 GtkWidgetProps props(widget); 0038 if (widget && props->scrolledWindowHacked) { 0039 props->scrolledWindowDestroy.disconn(); 0040 props->scrolledWindowUnrealize.disconn(); 0041 props->scrolledWindowStyleSet.disconn(); 0042 if (opts.unifyCombo && opts.unifySpin) { 0043 props->scrolledWindowEnter.disconn(); 0044 props->scrolledWindowLeave.disconn(); 0045 } 0046 props->scrolledWindowFocusIn.disconn(); 0047 props->scrolledWindowFocusOut.disconn(); 0048 props->scrolledWindowHacked = false; 0049 } 0050 } 0051 0052 static gboolean 0053 styleSet(GtkWidget *widget, GtkStyle*, void*) 0054 { 0055 cleanup(widget); 0056 return false; 0057 } 0058 0059 static gboolean 0060 destroy(GtkWidget *widget, GdkEvent*, void*) 0061 { 0062 cleanup(widget); 0063 return false; 0064 } 0065 0066 static GtkWidget *focusWidget = nullptr; 0067 static GtkWidget *hoverWidget = nullptr; 0068 0069 static gboolean 0070 enter(GtkWidget *widget, GdkEventMotion*, void *data) 0071 { 0072 GtkWidget *w = data ? (GtkWidget*)data : widget; 0073 if (GTK_IS_SCROLLED_WINDOW(w) && hoverWidget != w) { 0074 hoverWidget = w; 0075 gtk_widget_queue_draw(w); 0076 } 0077 return false; 0078 } 0079 0080 static gboolean 0081 leave(GtkWidget *widget, GdkEventMotion*, void *data) 0082 { 0083 GtkWidget *w = data ? (GtkWidget*)data : widget; 0084 if (GTK_IS_SCROLLED_WINDOW(w) && hoverWidget == w) { 0085 hoverWidget = nullptr; 0086 gtk_widget_queue_draw(w); 0087 } 0088 return false; 0089 } 0090 0091 static gboolean 0092 focusIn(GtkWidget *widget, GdkEventMotion*, void *data) 0093 { 0094 GtkWidget *w = data ? (GtkWidget*)data : widget; 0095 if (GTK_IS_SCROLLED_WINDOW(w) && focusWidget != w) { 0096 focusWidget = w; 0097 gtk_widget_queue_draw(w); 0098 } 0099 return false; 0100 } 0101 0102 static gboolean 0103 focusOut(GtkWidget *widget, GdkEventMotion*, void *data) 0104 { 0105 GtkWidget *w = data ? (GtkWidget*)data : widget; 0106 if (GTK_IS_SCROLLED_WINDOW(w) && focusWidget == w) { 0107 focusWidget = nullptr; 0108 gtk_widget_queue_draw(w); 0109 } 0110 return false; 0111 } 0112 0113 static void 0114 setupConnections(GtkWidget *widget, GtkWidget *parent) 0115 { 0116 GtkWidgetProps props(widget); 0117 if (widget && !props->scrolledWindowHacked) { 0118 props->scrolledWindowHacked = true; 0119 gtk_widget_add_events(widget, GDK_LEAVE_NOTIFY_MASK | 0120 GDK_ENTER_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK); 0121 props->scrolledWindowDestroy.conn("destroy-event", destroy, parent); 0122 props->scrolledWindowUnrealize.conn("unrealize", destroy, parent); 0123 props->scrolledWindowStyleSet.conn("style-set", styleSet, parent); 0124 if (opts.unifyCombo && opts.unifySpin) { 0125 props->scrolledWindowEnter.conn("enter-notify-event", 0126 enter, parent); 0127 props->scrolledWindowLeave.conn("leave-notify-event", 0128 leave, parent); 0129 } 0130 props->scrolledWindowFocusIn.conn("focus-in-event", focusIn, parent); 0131 props->scrolledWindowFocusOut.conn("focus-out-event", focusOut, parent); 0132 if (parent && opts.unifyCombo && opts.unifySpin) { 0133 QtcRect alloc = Widget::getAllocation(parent); 0134 int x; 0135 int y; 0136 gdk_window_get_pointer(gtk_widget_get_window(parent), 0137 &x, &y, nullptr); 0138 if (x >= 0 && x <alloc.width && y >= 0 && y < alloc.height) { 0139 hoverWidget = parent; 0140 } 0141 } 0142 } 0143 } 0144 0145 void 0146 setup(GtkWidget *widget) 0147 { 0148 GtkWidgetProps props(widget); 0149 if (widget && GTK_IS_SCROLLED_WINDOW(widget) && 0150 !props->scrolledWindowHacked) { 0151 GtkScrolledWindow *scrolledWindow = GTK_SCROLLED_WINDOW(widget); 0152 GtkWidget *child; 0153 0154 if ((child = gtk_scrolled_window_get_hscrollbar(scrolledWindow))) { 0155 setupConnections(child, widget); 0156 } 0157 if ((child = gtk_scrolled_window_get_vscrollbar(scrolledWindow))) { 0158 setupConnections(child, widget); 0159 } 0160 if ((child = gtk_bin_get_child(GTK_BIN(widget)))) { 0161 if (GTK_IS_TREE_VIEW(child) || GTK_IS_TEXT_VIEW(child) || 0162 GTK_IS_ICON_VIEW(child)) { 0163 setupConnections(child, widget); 0164 } else if (oneOf(gTypeName(child), "ExoIconView", 0165 "FMIconContainer")) { 0166 setupConnections(child, widget); 0167 } 0168 } 0169 props->scrolledWindowHacked = true; 0170 } 0171 } 0172 0173 void 0174 registerChild(GtkWidget *child) 0175 { 0176 GtkWidget *parent = child ? gtk_widget_get_parent(child) : nullptr; 0177 0178 GtkWidgetProps parentProps(parent); 0179 if (parent && GTK_IS_SCROLLED_WINDOW(parent) && 0180 parentProps->scrolledWindowHacked) { 0181 setupConnections(child, parent); 0182 } 0183 } 0184 0185 bool 0186 hasFocus(GtkWidget *widget) 0187 { 0188 return widget && (gtk_widget_has_focus(widget) || widget == focusWidget); 0189 } 0190 0191 bool 0192 hovered(GtkWidget *widget) 0193 { 0194 return widget && (gtk_widget_get_state(widget) == GTK_STATE_PRELIGHT || 0195 widget == hoverWidget); 0196 } 0197 0198 } 0199 }