From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Dmitry Antipov Newsgroups: gmane.emacs.devel Subject: Re: GTK scroll bar question Date: Thu, 31 Jul 2014 09:05:11 +0400 Message-ID: <53D9CE87.20800@yandex.ru> References: <53D8D2DE.4090700@yandex.ru> <53D8E765.2030303@gmx.at> <53D91162.9010503@yandex.ru> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------070404090809070406000503" X-Trace: ger.gmane.org 1406783153 26148 80.91.229.3 (31 Jul 2014 05:05:53 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 31 Jul 2014 05:05:53 +0000 (UTC) Cc: Emacs development discussions To: =?windows-1252?Q?Jan_Dj=E4rv?= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Jul 31 07:05:46 2014 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1XCiYj-0007oh-UE for ged-emacs-devel@m.gmane.org; Thu, 31 Jul 2014 07:05:46 +0200 Original-Received: from localhost ([::1]:54297 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XCiYh-0004K1-3r for ged-emacs-devel@m.gmane.org; Thu, 31 Jul 2014 01:05:43 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:60740) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XCiYX-0004Js-Rs for emacs-devel@gnu.org; Thu, 31 Jul 2014 01:05:40 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XCiYQ-0008Lc-Jo for emacs-devel@gnu.org; Thu, 31 Jul 2014 01:05:33 -0400 Original-Received: from forward3l.mail.yandex.net ([84.201.143.136]:33927) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XCiYP-0008KQ-Ta for emacs-devel@gnu.org; Thu, 31 Jul 2014 01:05:26 -0400 Original-Received: from smtp4o.mail.yandex.net (smtp4o.mail.yandex.net [37.140.190.29]) by forward3l.mail.yandex.net (Yandex) with ESMTP id 5983515012B3; Thu, 31 Jul 2014 09:05:24 +0400 (MSK) Original-Received: from smtp4o.mail.yandex.net (localhost [127.0.0.1]) by smtp4o.mail.yandex.net (Yandex) with ESMTP id E2005232267D; Thu, 31 Jul 2014 09:05:23 +0400 (MSK) Original-Received: from 31.gprs.mts.ru (31.gprs.mts.ru [213.87.131.31]) by smtp4o.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id HsdPBlEWxb-5KuK5nMP; Thu, 31 Jul 2014 09:05:20 +0400 (using TLSv1.2 with cipher AES128-SHA (128/128 bits)) (Client certificate not present) X-Yandex-Uniq: 3ea9c716-00a1-4892-b49e-e04fac4c8b73 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1406783123; bh=S5SY9TrAwgPdJYaAxB/eclcZAqF4uvMYW8UXAb6oe9s=; h=Message-ID:Date:From:User-Agent:MIME-Version:To:CC:Subject: References:In-Reply-To:Content-Type; b=duHxMYRhyZWRPaop0yhiWG6XikojgrY0tLPbIOFRbZV/wQuhy+3hba1TjHYKNXaD1 1zJlWM7sJQErZ/Y7f1+nZNeVaIlZ1o1gH1cD+inl8xNYfgpdBClWqU/skepwBVBwQV bORdx+Iw6RF7AaSAUmlmmH7KrcIl5zUkUN+IVyVI= Authentication-Results: smtp4o.mail.yandex.net; dkim=pass header.i=@yandex.ru User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.0 In-Reply-To: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 84.201.143.136 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:173307 Archived-At: This is a multi-part message in MIME format. --------------070404090809070406000503 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: quoted-printable On 07/30/2014 10:30 PM, Jan Dj=E4rv wrote: > This: > > + /* Realize so we can ask for underlying resources. */ > + gtk_widget_realize (wscroll); > is a noop on newer Gtk+ versions. Hm...in this particular case, adding or removing call to gtk_widget_reali= ze doesn't change anything; but, looking through source code of this functio= n, it's hard to believe that this is just another version of do { } while (0= ). > Scrollbars does not have their own X window, they write on the parent = window. Is it legitimate to use Window id (of scroll bar or it's parent) returned= by gdk_x11_window_get_xid (gtk_widget_get_window (...)) in x_window_to_[whatever] functions from xterm.c? If yes, there is a sim= ple way to get rid of id_to_widget map, as I've tried in attached patch. Dmitry --------------070404090809070406000503 Content-Type: text/x-patch; name="window_widget.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="window_widget.patch" === modified file 'src/gtkutil.c' --- src/gtkutil.c 2014-07-27 13:21:30 +0000 +++ src/gtkutil.c 2014-07-31 04:42:26 +0000 @@ -107,6 +107,7 @@ #define gtk_scrollbar_new(ori, spacing) \ ((ori) == GTK_ORIENTATION_HORIZONTAL \ ? gtk_hscrollbar_new ((spacing)) : gtk_vscrollbar_new ((spacing))) +#define gdk_x11_window_get_xid(w) gdk_x11_drawable_get_xid (w) #ifndef GDK_KEY_g #define GDK_KEY_g GDK_g #endif @@ -3427,85 +3428,6 @@ static int scroll_bar_width_for_theme; static int scroll_bar_height_for_theme; -/* Xlib's `Window' fits in 32 bits. But we want to store pointers, and they - may be larger than 32 bits. Keep a mapping from integer index to widget - pointers to get around the 32 bit limitation. */ - -static struct -{ - GtkWidget **widgets; - ptrdiff_t max_size; - ptrdiff_t used; -} id_to_widget; - -/* Grow this much every time we need to allocate more */ - -#define ID_TO_WIDGET_INCR 32 - -/* Store the widget pointer W in id_to_widget and return the integer index. */ - -static ptrdiff_t -xg_store_widget_in_map (GtkWidget *w) -{ - ptrdiff_t i; - - if (id_to_widget.max_size == id_to_widget.used) - { - ptrdiff_t new_size; - if (TYPE_MAXIMUM (Window) - ID_TO_WIDGET_INCR < id_to_widget.max_size) - memory_full (SIZE_MAX); - - new_size = id_to_widget.max_size + ID_TO_WIDGET_INCR; - id_to_widget.widgets = xnrealloc (id_to_widget.widgets, - new_size, sizeof (GtkWidget *)); - - for (i = id_to_widget.max_size; i < new_size; ++i) - id_to_widget.widgets[i] = 0; - id_to_widget.max_size = new_size; - } - - /* Just loop over the array and find a free place. After all, - how many scroll bars are we creating? Should be a small number. - The check above guarantees we will find a free place. */ - for (i = 0; i < id_to_widget.max_size; ++i) - { - if (! id_to_widget.widgets[i]) - { - id_to_widget.widgets[i] = w; - ++id_to_widget.used; - - return i; - } - } - - /* Should never end up here */ - emacs_abort (); -} - -/* Remove pointer at IDX from id_to_widget. - Called when scroll bar is destroyed. */ - -static void -xg_remove_widget_from_map (ptrdiff_t idx) -{ - if (idx < id_to_widget.max_size && id_to_widget.widgets[idx] != 0) - { - id_to_widget.widgets[idx] = 0; - --id_to_widget.used; - } -} - -/* Get the widget pointer at IDX from id_to_widget. */ - -static GtkWidget * -xg_get_widget_from_map (ptrdiff_t idx) -{ - if (idx < id_to_widget.max_size && id_to_widget.widgets[idx] != 0) - return id_to_widget.widgets[idx]; - - return 0; -} - static void update_theme_scrollbar_width (void) { @@ -3523,8 +3445,7 @@ gtk_widget_style_get (wscroll, "slider-width", &w, "trough-border", &b, NULL); gtk_widget_destroy (wscroll); g_object_unref (G_OBJECT (wscroll)); - w += 2*b; - if (w < 16) w = 16; + w += 2 * b; scroll_bar_width_for_theme = w; } @@ -3545,8 +3466,7 @@ gtk_widget_style_get (wscroll, "slider-width", &w, "trough-border", &b, NULL); gtk_widget_destroy (wscroll); g_object_unref (G_OBJECT (wscroll)); - w += 2*b; - if (w < 12) w = 12; + w += 2 * b; scroll_bar_height_for_theme = w; } @@ -3563,38 +3483,6 @@ return scroll_bar_width_for_theme; } -/* Return the scrollbar id for X Window WID on display DPY. - Return -1 if WID not in id_to_widget. */ - -ptrdiff_t -xg_get_scroll_id_for_window (Display *dpy, Window wid) -{ - ptrdiff_t idx; - GtkWidget *w; - - w = xg_win_to_widget (dpy, wid); - - if (w) - { - for (idx = 0; idx < id_to_widget.max_size; ++idx) - if (id_to_widget.widgets[idx] == w) - return idx; - } - - return -1; -} - -/* Callback invoked when scroll bar WIDGET is destroyed. - DATA is the index into id_to_widget for WIDGET. - We free pointer to last scroll bar values here and remove the index. */ - -static void -xg_gtk_scroll_destroy (GtkWidget *widget, gpointer data) -{ - intptr_t id = (intptr_t) data; - xg_remove_widget_from_map (id); -} - /* Create a scroll bar widget for frame F. Store the scroll bar in BAR. SCROLL_CALLBACK is the callback to invoke when the value of the @@ -3612,7 +3500,6 @@ { GtkWidget *wscroll; GtkWidget *webox; - intptr_t scroll_id; #ifdef HAVE_GTK3 GtkAdjustment *vadj; #else @@ -3632,12 +3519,6 @@ #endif g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f); - scroll_id = xg_store_widget_in_map (wscroll); - - g_signal_connect (G_OBJECT (wscroll), - "destroy", - G_CALLBACK (xg_gtk_scroll_destroy), - (gpointer) scroll_id); g_signal_connect (G_OBJECT (wscroll), "change-value", scroll_callback, @@ -3656,11 +3537,12 @@ gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1); gtk_container_add (GTK_CONTAINER (webox), wscroll); - /* Set the cursor to an arrow. */ xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); - bar->x_window = scroll_id; + /* Remember X window and widget in the scroll bar vector. */ + bar->x_window = gdk_x11_window_get_xid (gtk_widget_get_window (wscroll)); + bar->widget = wscroll; bar->horizontal = 0; } @@ -3679,7 +3561,6 @@ { GtkWidget *wscroll; GtkWidget *webox; - intptr_t scroll_id; #ifdef HAVE_GTK3 GtkAdjustment *hadj; #else @@ -3699,12 +3580,6 @@ #endif g_object_set_data (G_OBJECT (wscroll), XG_FRAME_DATA, (gpointer)f); - scroll_id = xg_store_widget_in_map (wscroll); - - g_signal_connect (G_OBJECT (wscroll), - "destroy", - G_CALLBACK (xg_gtk_scroll_destroy), - (gpointer) scroll_id); g_signal_connect (G_OBJECT (wscroll), "change-value", scroll_callback, @@ -3723,20 +3598,21 @@ gtk_fixed_put (GTK_FIXED (f->output_data.x->edit_widget), webox, -1, -1); gtk_container_add (GTK_CONTAINER (webox), wscroll); - /* Set the cursor to an arrow. */ xg_set_cursor (webox, FRAME_DISPLAY_INFO (f)->xg_cursor); - bar->x_window = scroll_id; + /* Remember X window and widget in the scroll bar vector. */ + bar->x_window = gdk_x11_window_get_xid (gtk_widget_get_window (wscroll)); + bar->widget = wscroll; bar->horizontal = 1; } -/* Remove the scroll bar represented by SCROLLBAR_ID from the frame F. */ +/* Remove the scroll bar BAR from the frame F. */ void -xg_remove_scroll_bar (struct frame *f, ptrdiff_t scrollbar_id) +xg_remove_scroll_bar (struct frame *f, struct scroll_bar *bar) { - GtkWidget *w = xg_get_widget_from_map (scrollbar_id); + GtkWidget *w = bar->widget; if (w) { GtkWidget *wparent = gtk_widget_get_parent (w); @@ -3753,14 +3629,14 @@ void xg_update_scrollbar_pos (struct frame *f, - ptrdiff_t scrollbar_id, + struct scroll_bar *bar, int top, int left, int width, int height) { - GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id); + GtkWidget *wscroll = bar->widget; if (wscroll) { @@ -3819,14 +3695,14 @@ void xg_update_horizontal_scrollbar_pos (struct frame *f, - ptrdiff_t scrollbar_id, + struct scroll_bar *bar, int top, int left, int width, int height) { - GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id); + GtkWidget *wscroll = bar->widget; if (wscroll) { @@ -3896,7 +3772,7 @@ int position, int whole) { - GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window); + GtkWidget *wscroll = bar->widget; struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); @@ -3981,7 +3857,7 @@ int position, int whole) { - GtkWidget *wscroll = xg_get_widget_from_map (bar->x_window); + GtkWidget *wscroll = bar->widget; if (wscroll && bar->dragging == -1) { @@ -5187,9 +5063,6 @@ xg_menu_cb_list.prev = xg_menu_cb_list.next = xg_menu_item_cb_list.prev = xg_menu_item_cb_list.next = 0; - id_to_widget.max_size = id_to_widget.used = 0; - id_to_widget.widgets = 0; - settings = gtk_settings_get_for_screen (gdk_display_get_default_screen (gdk_display_get_default ())); /* Remove F10 as a menu accelerator, it does not mix well with Emacs key === modified file 'src/gtkutil.h' --- src/gtkutil.h 2014-07-27 13:21:30 +0000 +++ src/gtkutil.h 2014-07-31 04:40:40 +0000 @@ -110,8 +110,6 @@ extern bool xg_have_tear_offs (struct frame *f); -extern ptrdiff_t xg_get_scroll_id_for_window (Display *dpy, Window wid); - extern void xg_create_scroll_bar (struct frame *f, struct scroll_bar *bar, GCallback scroll_callback, @@ -122,16 +120,16 @@ GCallback scroll_callback, GCallback end_callback, const char *scroll_bar_name); -extern void xg_remove_scroll_bar (struct frame *f, ptrdiff_t scrollbar_id); +extern void xg_remove_scroll_bar (struct frame *f, struct scroll_bar *); extern void xg_update_scrollbar_pos (struct frame *f, - ptrdiff_t scrollbar_id, + struct scroll_bar *bar, int top, int left, int width, int height); extern void xg_update_horizontal_scrollbar_pos (struct frame *f, - ptrdiff_t scrollbar_id, + struct scroll_bar *bar, int top, int left, int width, === modified file 'src/xterm.c' --- src/xterm.c 2014-07-30 04:03:45 +0000 +++ src/xterm.c 2014-07-31 04:40:40 +0000 @@ -4187,10 +4187,6 @@ { Lisp_Object tail, frame; -#if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS) - window_id = (Window) xg_get_scroll_id_for_window (display, window_id); -#endif /* USE_GTK && USE_TOOLKIT_SCROLL_BARS */ - FOR_EACH_FRAME (tail, frame) { Lisp_Object bar, condemned; @@ -4789,7 +4785,6 @@ static void x_create_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) { - Window xwindow; Widget widget; Arg av[20]; int ac = 0; @@ -4976,9 +4971,8 @@ action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0); /* Remember X window and widget in the scroll bar vector. */ - SET_SCROLL_BAR_X_WIDGET (bar, widget); - xwindow = XtWindow (widget); - bar->x_window = xwindow; + bar->x_window = XtWindow (widget); + bar->widget = widget; bar->whole = 1; bar->horizontal = 0; @@ -4988,7 +4982,6 @@ static void x_create_horizontal_toolkit_scroll_bar (struct frame *f, struct scroll_bar *bar) { - Window xwindow; Widget widget; Arg av[20]; int ac = 0; @@ -5176,9 +5169,8 @@ = XtAppAddActionHook (Xt_app_con, xt_horizontal_action_hook, 0); /* Remember X window and widget in the scroll bar vector. */ - SET_SCROLL_BAR_X_WIDGET (bar, widget); - xwindow = XtWindow (widget); - bar->x_window = xwindow; + bar->x_window = XtWindow (widget); + bar->widget = widget; bar->whole = 1; bar->horizontal = 1; @@ -5208,8 +5200,7 @@ x_set_toolkit_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole) { - struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); - Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); + Widget widget = bar->widget; float top, shown; block_input (); @@ -5320,8 +5311,7 @@ x_set_toolkit_horizontal_scroll_bar_thumb (struct scroll_bar *bar, int portion, int position, int whole) { - struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); - Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); + Widget widget = bar->widget; float top, shown; block_input (); @@ -5491,15 +5481,13 @@ { #ifdef USE_GTK if (horizontal) - xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, - left, width, max (height, 1)); + xg_update_horizontal_scrollbar_pos (f, bar, top, left, + width, max (height, 1)); else - xg_update_scrollbar_pos (f, bar->x_window, top, - left, width, max (height, 1)); + xg_update_scrollbar_pos (f, bar, top, left, width, max (height, 1)); #else /* not USE_GTK */ - Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); - XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0); - XtMapWidget (scroll_bar); + XtConfigureWidget (bar->widget, left, top, width, max (height, 1), 0); + XtMapWidget (bar->widget); #endif /* not USE_GTK */ } #else /* not USE_TOOLKIT_SCROLL_BARS */ @@ -5622,14 +5610,16 @@ static void x_scroll_bar_remove (struct scroll_bar *bar) { +#if defined (USE_GTK) || !defined (USE_X_TOOLKIT) struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); +#endif block_input (); #ifdef USE_TOOLKIT_SCROLL_BARS #ifdef USE_GTK - xg_remove_scroll_bar (f, bar->x_window); + xg_remove_scroll_bar (f, bar); #else /* not USE_GTK */ - XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar)); + XtDestroyWidget (bar->widget); #endif /* not USE_GTK */ #else XDestroyWindow (FRAME_X_DISPLAY (f), bar->x_window); @@ -5708,11 +5698,9 @@ x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), left, top, width, height); #ifdef USE_GTK - xg_update_scrollbar_pos (f, bar->x_window, top, - left, width, max (height, 1)); + xg_update_scrollbar_pos (f, bar, top, left, width, max (height, 1)); #else /* not USE_GTK */ - XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar), - left, top, width, max (height, 1), 0); + XtConfigureWidget (bar->widget, left, top, width, max (height, 1), 0); #endif /* not USE_GTK */ } #else /* not USE_TOOLKIT_SCROLL_BARS */ @@ -5828,11 +5816,10 @@ WINDOW_LEFT_EDGE_X (w), top, pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height); #ifdef USE_GTK - xg_update_horizontal_scrollbar_pos (f, bar->x_window, top, left, + xg_update_horizontal_scrollbar_pos (f, bar, top, left, width, height); #else /* not USE_GTK */ - XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar), - left, top, width, height, 0); + XtConfigureWidget (bar->widget, left, top, width, height, 0); #endif /* not USE_GTK */ } #else /* not USE_TOOLKIT_SCROLL_BARS */ === modified file 'src/xterm.h' --- src/xterm.h 2014-07-27 13:21:30 +0000 +++ src/xterm.h 2014-07-31 04:40:40 +0000 @@ -798,6 +798,13 @@ /* The X window representing this scroll bar. */ Window x_window; + /* Toolkit-dependent widget used for this scroll bar. */ +#if defined (USE_GTK) + GtkWidget *widget; +#elif defined (USE_X_TOOLKIT) + Widget widget; +#endif + /* The position and size of the scroll bar in pixels, relative to the frame. */ int top, left, width, height; @@ -838,25 +845,6 @@ /* Turning a lisp vector value into a pointer to a struct scroll_bar. */ #define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec)) -#ifdef USE_X_TOOLKIT - -/* Extract the X widget of the scroll bar from a struct scroll_bar. - XtWindowToWidget should be fast enough since Xt uses a hash table - to map windows to widgets. */ - -#define SCROLL_BAR_X_WIDGET(dpy, ptr) \ - XtWindowToWidget (dpy, ptr->x_window) - -/* Store a widget id in a struct scroll_bar. */ - -#define SET_SCROLL_BAR_X_WIDGET(ptr, w) \ - do { \ - Window window = XtWindow (w); \ - ptr->x_window = window; \ - } while (false) - -#endif /* USE_X_TOOLKIT */ - /* Return the inside width of a vertical scroll bar, given the outside width. */ #define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(f, width) \ --------------070404090809070406000503--