comparison src/gtkconv.c @ 11279:ed5302df41b0

[gaim-migrate @ 13474] Patch by Sadrul Habib Chowdhury to fix tab dragging. Many thanks also to Cae for helping to track down the exact behavior, and for helping to test this patch so that Sadrul could provide a version that actually fixes the bug. :-) committer: Tailor Script <tailor@pidgin.im>
author Luke Schierer <lschiere@pidgin.im>
date Tue, 16 Aug 2005 18:54:40 +0000
parents 17ebda61c6ce
children 65658ff2deb8
comparison
equal deleted inserted replaced
11278:93258e8fb6d2 11279:ed5302df41b0
2091 } 2091 }
2092 else { /* Otherwise, draw the arrows. */ 2092 else { /* Otherwise, draw the arrows. */
2093 GaimConvWindow *dest_win; 2093 GaimConvWindow *dest_win;
2094 GaimGtkWindow *dest_gtkwin; 2094 GaimGtkWindow *dest_gtkwin;
2095 GtkNotebook *dest_notebook; 2095 GtkNotebook *dest_notebook;
2096 GtkWidget *tab, *last_vis_tab = NULL; 2096 GtkWidget *tab;
2097 gint nb_x, nb_y, page_num, i, last_vis_tab_loc = -1; 2097 gint nb_x, nb_y, page_num;
2098 gint arrow1_x, arrow1_y, arrow2_x, arrow2_y; 2098 gint arrow1_x, arrow1_y, arrow2_x, arrow2_y;
2099 gboolean horiz_tabs = FALSE, tab_found = FALSE; 2099 gboolean horiz_tabs = FALSE;
2100 GList *l;
2101 2100
2102 /* Get the window that the cursor is over. */ 2101 /* Get the window that the cursor is over. */
2103 dest_win = gaim_gtkwin_get_at_xy(e->x_root, e->y_root); 2102 dest_win = gaim_gtkwin_get_at_xy(e->x_root, e->y_root);
2104 2103
2105 if (dest_win == NULL) { 2104 if (dest_win == NULL) {
2124 gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_BOTTOM) { 2123 gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_BOTTOM) {
2125 2124
2126 horiz_tabs = TRUE; 2125 horiz_tabs = TRUE;
2127 } 2126 }
2128 2127
2129 /* Find out where to put the arrows. */ 2128 tab = gaim_gtk_get_gtkconv_at_index(dest_win, page_num)->tabby;
2130 for (l = gaim_conv_window_get_conversations(dest_win), i = 0; 2129
2131 l != NULL; 2130 if (horiz_tabs) {
2132 l = l->next, i++) { 2131 arrow1_x = arrow2_x = nb_x + tab->allocation.x;
2133 2132
2134 GaimConversation *conv = l->data; 2133 if ((gpointer)gtkwin == (gpointer)dest_gtkwin && gtkwin->drag_tab < page_num) {
2135 2134 arrow1_x += tab->allocation.width;
2136 tab = GAIM_GTK_CONVERSATION(conv)->tabby; 2135 arrow2_x += tab->allocation.width;
2137
2138 /*
2139 * If this is the correct tab, record the positions
2140 * for the arrows.
2141 */
2142 if (i == page_num) {
2143 if (horiz_tabs) {
2144 arrow1_x = arrow2_x = nb_x + tab->allocation.x;
2145 arrow1_y = nb_y + tab->allocation.y;
2146 arrow2_y = nb_y + tab->allocation.y +
2147 tab->allocation.height;
2148 }
2149 else {
2150 arrow1_x = nb_x + tab->allocation.x;
2151 arrow2_x = nb_x + tab->allocation.x +
2152 tab->allocation.width;
2153 arrow1_y = arrow2_y = nb_y + tab->allocation.y;
2154 }
2155
2156 tab_found = TRUE;
2157 break;
2158 } 2136 }
2159 else { /* Keep track of the right-most tab that we see. */ 2137
2160 if (horiz_tabs && tab->allocation.x > last_vis_tab_loc) { 2138 arrow1_y = nb_y + tab->allocation.y;
2161 last_vis_tab = tab; 2139 arrow2_y = nb_y + tab->allocation.y +
2162 last_vis_tab_loc = tab->allocation.x; 2140 tab->allocation.height;
2163 } 2141 }
2164 else if (!horiz_tabs && tab->allocation.y > last_vis_tab_loc) { 2142 else {
2165 last_vis_tab = tab; 2143 arrow1_x = nb_x + tab->allocation.x;
2166 last_vis_tab_loc = tab->allocation.y; 2144 arrow2_x = nb_x + tab->allocation.x +
2167 } 2145 tab->allocation.width;
2168 } 2146 arrow1_y = arrow2_y = nb_y + tab->allocation.y + tab->allocation.height/2;
2169 } 2147
2170 2148 if ((gpointer)gtkwin == (gpointer)dest_win && gtkwin->drag_tab > page_num) {
2171 /* 2149 arrow1_y += tab->allocation.height;
2172 * If we didn't find the tab, then we'll just place the 2150 arrow2_y += tab->allocation.height;
2173 * arrows to the right/bottom of the last visible tab.
2174 */
2175 if (!tab_found && last_vis_tab) {
2176 if (horiz_tabs) {
2177 arrow1_x = arrow2_x = nb_x + last_vis_tab->allocation.x +
2178 last_vis_tab->allocation.width;
2179 arrow1_y = nb_y + last_vis_tab->allocation.y;
2180 arrow2_y = nb_y + last_vis_tab->allocation.y +
2181 last_vis_tab->allocation.height;
2182 }
2183 else {
2184 arrow1_x = nb_x + last_vis_tab->allocation.x;
2185 arrow2_x = nb_x + last_vis_tab->allocation.x +
2186 last_vis_tab->allocation.width;
2187 arrow1_y = arrow2_y = nb_y + last_vis_tab->allocation.y +
2188 last_vis_tab->allocation.height;
2189 } 2151 }
2190 } 2152 }
2191 2153
2192 if (horiz_tabs) { 2154 if (horiz_tabs) {
2193 dnd_hints_show(HINT_ARROW_DOWN, arrow1_x, arrow1_y); 2155 dnd_hints_show(HINT_ARROW_DOWN, arrow1_x, arrow1_y);
2230 static gboolean 2192 static gboolean
2231 notebook_press_cb(GtkWidget *widget, GdkEventButton *e, GaimConvWindow *win) 2193 notebook_press_cb(GtkWidget *widget, GdkEventButton *e, GaimConvWindow *win)
2232 { 2194 {
2233 GaimGtkWindow *gtkwin; 2195 GaimGtkWindow *gtkwin;
2234 gint nb_x, nb_y, x_rel, y_rel; 2196 gint nb_x, nb_y, x_rel, y_rel;
2235 GList *l;
2236 int tab_clicked; 2197 int tab_clicked;
2198 GtkWidget *page;
2237 2199
2238 if (e->button != 1 || e->type != GDK_BUTTON_PRESS) 2200 if (e->button != 1 || e->type != GDK_BUTTON_PRESS)
2239 return FALSE; 2201 return FALSE;
2240 2202
2241 gtkwin = GAIM_GTK_WINDOW(win); 2203 gtkwin = GAIM_GTK_WINDOW(win);
2269 gtkwin->drag_min_y = 0; 2231 gtkwin->drag_min_y = 0;
2270 gtkwin->drag_max_x = 0; 2232 gtkwin->drag_max_x = 0;
2271 gtkwin->drag_max_y = 0; 2233 gtkwin->drag_max_y = 0;
2272 2234
2273 /* Find out which tab was dragged. */ 2235 /* Find out which tab was dragged. */
2274 for (l = gaim_conv_window_get_conversations(win); l != NULL; l = l->next) { 2236 page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(gtkwin->notebook), tab_clicked);
2275 GaimConversation *conv = l->data; 2237 GtkWidget *tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(gtkwin->notebook), page);
2276 GtkWidget *tab = GAIM_GTK_CONVERSATION(conv)->tabby; 2238
2277 2239 gtkwin->drag_min_x = tab->allocation.x + nb_x;
2278 if (!GTK_WIDGET_VISIBLE(tab)) 2240 gtkwin->drag_min_y = tab->allocation.y + nb_y;
2279 continue; 2241 gtkwin->drag_max_x = tab->allocation.width + gtkwin->drag_min_x;
2280 2242 gtkwin->drag_max_y = tab->allocation.height + gtkwin->drag_min_y;
2281 if (tab->allocation.x > x_rel || tab->allocation.y > y_rel)
2282 break;
2283
2284 /* Save the borders of the tab. */
2285 gtkwin->drag_min_x = tab->allocation.x + nb_x;
2286 gtkwin->drag_min_y = tab->allocation.y + nb_y;
2287 gtkwin->drag_max_x = tab->allocation.width + gtkwin->drag_min_x;
2288 gtkwin->drag_max_y = tab->allocation.height + gtkwin->drag_min_y;
2289 }
2290 2243
2291 /* Make sure the click occurred in the tab. */ 2244 /* Make sure the click occurred in the tab. */
2292 if (e->x_root < gtkwin->drag_min_x || 2245 if (e->x_root < gtkwin->drag_min_x ||
2293 e->x_root >= gtkwin->drag_max_x || 2246 e->x_root >= gtkwin->drag_max_x ||
2294 e->y_root < gtkwin->drag_min_y || 2247 e->y_root < gtkwin->drag_min_y ||
2296 2249
2297 return FALSE; 2250 return FALSE;
2298 } 2251 }
2299 2252
2300 gtkwin->in_predrag = TRUE; 2253 gtkwin->in_predrag = TRUE;
2254 gtkwin->drag_tab = tab_clicked;
2301 2255
2302 /* Connect the new motion signals. */ 2256 /* Connect the new motion signals. */
2303 gtkwin->drag_motion_signal = 2257 gtkwin->drag_motion_signal =
2304 g_signal_connect(G_OBJECT(widget), "motion_notify_event", 2258 g_signal_connect(G_OBJECT(widget), "motion_notify_event",
2305 G_CALLBACK(notebook_motion_cb), win); 2259 G_CALLBACK(notebook_motion_cb), win);
5928 5882
5929 int 5883 int
5930 gaim_gtkconv_get_tab_at_xy(GaimConvWindow *win, int x, int y) 5884 gaim_gtkconv_get_tab_at_xy(GaimConvWindow *win, int x, int y)
5931 { 5885 {
5932 GaimGtkWindow *gtkwin; 5886 GaimGtkWindow *gtkwin;
5933 GList *l;
5934 gint nb_x, nb_y, x_rel, y_rel; 5887 gint nb_x, nb_y, x_rel, y_rel;
5935 GtkNotebook *notebook; 5888 GtkNotebook *notebook;
5936 GtkWidget *tab; 5889 GtkWidget *page, *tab;
5937 gint i, page_num = 0; 5890 gint i, page_num = -1;
5938 gboolean first_visible = TRUE; 5891 gint count;
5892 gboolean horiz;
5939 5893
5940 if (!GAIM_IS_GTK_WINDOW(win)) 5894 if (!GAIM_IS_GTK_WINDOW(win))
5941 return -1; 5895 return -1;
5942 5896
5943 gtkwin = GAIM_GTK_WINDOW(win); 5897 gtkwin = GAIM_GTK_WINDOW(win);
5945 5899
5946 gdk_window_get_origin(gtkwin->notebook->window, &nb_x, &nb_y); 5900 gdk_window_get_origin(gtkwin->notebook->window, &nb_x, &nb_y);
5947 x_rel = x - nb_x; 5901 x_rel = x - nb_x;
5948 y_rel = y - nb_y; 5902 y_rel = y - nb_y;
5949 5903
5950 for (l = gaim_conv_window_get_conversations(win), i = 0; 5904 horiz = (gtk_notebook_get_tab_pos(notebook) == GTK_POS_TOP ||
5951 l != NULL; 5905 gtk_notebook_get_tab_pos(notebook) == GTK_POS_BOTTOM);
5952 l = l->next, i++) { 5906
5953 5907 count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook));
5954 GaimConversation *conv = l->data; 5908
5955 tab = GAIM_GTK_CONVERSATION(conv)->tab_label; 5909 for (i = 0; i < count; i++) {
5956 5910
5957 if (!GTK_WIDGET_MAPPED(tab)) 5911 page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i);
5958 continue; 5912 tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), page);
5959 5913
5960 if (first_visible) { 5914 if (horiz) {
5961 first_visible = FALSE; 5915 if (x_rel >= tab->allocation.x - GAIM_HIG_BOX_SPACE &&
5962 5916 x_rel <= tab->allocation.x + tab->allocation.width + GAIM_HIG_BOX_SPACE) {
5963 if (x_rel < tab->allocation.x) x_rel = tab->allocation.x; 5917 page_num = i;
5964 if (y_rel < tab->allocation.y) y_rel = tab->allocation.y; 5918 break;
5965 }
5966
5967 if (gtk_notebook_get_tab_pos(notebook) == GTK_POS_TOP ||
5968 gtk_notebook_get_tab_pos(notebook) == GTK_POS_BOTTOM) {
5969
5970 if (tab->allocation.x <= x_rel) {
5971 if (tab->allocation.x + tab->allocation.width <= x_rel)
5972 page_num = i + 1;
5973 else
5974 page_num = i;
5975 } 5919 }
5976 else 5920 } else {
5921 if (y_rel >= tab->allocation.y - GAIM_HIG_BOX_SPACE &&
5922 y_rel <= tab->allocation.y + tab->allocation.height + GAIM_HIG_BOX_SPACE) {
5923 page_num = i;
5977 break; 5924 break;
5978 }
5979 else {
5980 if (tab->allocation.y <= y_rel) {
5981 if (tab->allocation.y + tab->allocation.height <= y_rel)
5982 page_num = i + 1;
5983 else
5984 page_num = i;
5985 } 5925 }
5986 else 5926 }
5987 break; 5927 }
5988 }
5989 }
5990
5991 if (i == gaim_conv_window_get_conversation_count(win) + 1)
5992 return -1;
5993 5928
5994 return page_num; 5929 return page_num;
5995 } 5930 }
5996 5931
5997 int 5932 int
5998 gaim_gtkconv_get_dest_tab_at_xy(GaimConvWindow *win, int x, int y) 5933 gaim_gtkconv_get_dest_tab_at_xy(GaimConvWindow *win, int x, int y)
5999 { 5934 {
6000 GaimGtkWindow *gtkwin; 5935 return gaim_gtkconv_get_tab_at_xy(win, x, y);
6001 GList *l;
6002 gint nb_x, nb_y, x_rel, y_rel;
6003 GtkNotebook *notebook;
6004 GtkWidget *tab;
6005 gint i, page_num = 0;
6006
6007 if (!GAIM_IS_GTK_WINDOW(win))
6008 return -1;
6009
6010 gtkwin = GAIM_GTK_WINDOW(win);
6011 notebook = GTK_NOTEBOOK(gtkwin->notebook);
6012
6013 gdk_window_get_origin(gtkwin->notebook->window, &nb_x, &nb_y);
6014 x_rel = x - nb_x;
6015 y_rel = y - nb_y;
6016
6017 for (l = gaim_conv_window_get_conversations(win), i = 0;
6018 l != NULL;
6019 l = l->next, i++) {
6020
6021 GaimConversation *conv = l->data;
6022 tab = GAIM_GTK_CONVERSATION(conv)->tab_label;
6023
6024 if (!GTK_WIDGET_MAPPED(tab))
6025 continue;
6026
6027 if (gtk_notebook_get_tab_pos(notebook) == GTK_POS_TOP ||
6028 gtk_notebook_get_tab_pos(notebook) == GTK_POS_BOTTOM) {
6029
6030 if (tab->allocation.x <= x_rel) {
6031 if (tab->allocation.x + (tab->allocation.width / 2) <= x_rel)
6032 page_num = i + 1;
6033 else
6034 page_num = i;
6035 }
6036 else
6037 break;
6038 }
6039 else {
6040 if (tab->allocation.y <= y_rel) {
6041 if (tab->allocation.y + (tab->allocation.height / 2) <= y_rel)
6042 page_num = i + 1;
6043 else
6044 page_num = i;
6045 }
6046 else
6047 break;
6048 }
6049 }
6050
6051 if (i == gaim_conv_window_get_conversation_count(win) + 1)
6052 return -1;
6053
6054 return page_num;
6055 } 5936 }
6056 5937
6057 static void 5938 static void
6058 close_on_tabs_pref_cb(const char *name, GaimPrefType type, gpointer value, 5939 close_on_tabs_pref_cb(const char *name, GaimPrefType type, gpointer value,
6059 gpointer data) 5940 gpointer data)