From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Terje Rosten Newsgroups: gmane.emacs.devel Subject: Adding mask to the window icon Date: Fri, 23 May 2003 12:44:51 +0200 Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: main.gmane.org 1053689697 29726 80.91.224.249 (23 May 2003 11:34:57 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Fri, 23 May 2003 11:34:57 +0000 (UTC) Original-X-From: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Fri May 23 13:34:56 2003 Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 19JAnl-0007eR-00 for ; Fri, 23 May 2003 13:33:33 +0200 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 19JAzU-00016J-00 for ; Fri, 23 May 2003 13:45:40 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.20) id 19JAgy-0004qe-D2 for emacs-devel@quimby.gnus.org; Fri, 23 May 2003 07:26:32 -0400 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.20) id 19JAcH-0003H0-Hg for emacs-devel@gnu.org; Fri, 23 May 2003 07:21:41 -0400 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.20) id 19JAc9-0003EJ-Ou for emacs-devel@gnu.org; Fri, 23 May 2003 07:21:35 -0400 Original-Received: from igor.phys.ntnu.no ([129.241.48.108]) by monty-python.gnu.org with esmtp (Exim 4.20) id 19JA2k-00060a-Az for emacs-devel@gnu.org; Fri, 23 May 2003 06:44:58 -0400 Original-Received: (from terjeros@localhost) by igor.phys.ntnu.no (8.11.6/8.11.6) id h4NAipc12960; Fri, 23 May 2003 12:44:51 +0200 X-Authentication-Warning: igor.phys.ntnu.no: terjeros set sender to terjeros@phys.ntnu.no using -f Original-To: emacs-devel@gnu.org User-Agent: Gnus/5.1003 (Gnus v5.10.3) Emacs/21.2 (gnu/linux) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1b5 Precedence: list List-Id: Emacs development discussions. List-Help: List-Post: List-Subscribe: , List-Archive: List-Unsubscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:14121 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:14121 I have added support for the WM_HINTS IconMaskHint property. In order the achieve this I have added a new member to the x_bitmap_record struct in xterm.h and created a two new functions for bitmaps: x_bitmap_mask() and x_create_bitmap_mask(). Gtk+ has a simple gtk_window_set_icon_from_file() and in the patch this function is used instead of the internal Emacs icon machinery if Emacs is compiled with Gtk+ support. The advantage of this is that the icon then will not be restricted to bitmaps. The new relevant function is xg_set_icon in xfns.c. Please review the patch and apply if it's appropriate. - Terje Index: src/xfns.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/xfns.c,v retrieving revision 1.579 diff -c -r1.579 xfns.c *** src/xfns.c 21 May 2003 22:12:15 -0000 1.579 --- src/xfns.c 23 May 2003 09:58:04 -0000 *************** *** 550,555 **** --- 550,563 ---- return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap; } + int + x_bitmap_mask (f, id) + FRAME_PTR f; + int id; + { + return FRAME_X_DISPLAY_INFO (f)->bitmaps[id - 1].mask; + } + /* Allocate a new bitmap record. Returns index of new record. */ *************** *** 693,698 **** --- 701,707 ---- { BLOCK_INPUT; XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].pixmap); + XFreePixmap (FRAME_X_DISPLAY (f), dpyinfo->bitmaps[id - 1].mask); if (dpyinfo->bitmaps[id - 1].file) { xfree (dpyinfo->bitmaps[id - 1].file); *************** *** 714,719 **** --- 723,729 ---- if (dpyinfo->bitmaps[i].refcount > 0) { XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].pixmap); + XFreePixmap (dpyinfo->display, dpyinfo->bitmaps[i].mask); if (dpyinfo->bitmaps[i].file) xfree (dpyinfo->bitmaps[i].file); } *************** *** 721,726 **** --- 731,835 ---- } + + + /* Useful functions defined in the section + `Image type independent image structures' below. */ + + static unsigned long four_corners_best P_ ((XImage *ximg, unsigned long width, + unsigned long height)); + + static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height, + int depth, XImage **ximg, + Pixmap *pixmap)); + + static void x_destroy_x_image P_ ((XImage *ximg)); + + + /* Create a mask of a bitmap. Note is this not a perfect mask. + It's nicer with some borders in this context */ + + int + x_create_bitmap_mask(f, id) + struct frame *f; + int id; + { + Pixmap pixmap, mask; + XImage *ximg, *mask_img; + unsigned long width, height; + int result; + unsigned long bg; + unsigned long x, y, xp, xm, yp, ym; + GC gc; + + int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f)); + struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + + if (!(id > 0)) + return -1; + + pixmap = x_bitmap_pixmap(f, id); + width = x_bitmap_width(f, id); + height = x_bitmap_height(f, id); + + BLOCK_INPUT; + ximg = XGetImage (FRAME_X_DISPLAY (f), pixmap, 0, 0, width, height, + ~0, ZPixmap); + + if (!ximg) + { + UNBLOCK_INPUT; + return -1; + } + + result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask); + + UNBLOCK_INPUT; + if (!result) + { + XDestroyImage(ximg); + return -1; + } + + bg = four_corners_best (ximg, width, height); + + for (y = 0; y < ximg->height; ++y) + { + for (x = 0; x < ximg->width; ++x) + { + xp = x != ximg->width - 1 ? x + 1 : 0; + xm = x != 0 ? x - 1 : ximg->width - 1; + yp = y != ximg->height - 1 ? y + 1 : 0; + ym = y != 0 ? y - 1 : ximg->height - 1; + if (XGetPixel (ximg, x, y) == bg + && XGetPixel (ximg, x, yp) == bg + && XGetPixel (ximg, x, ym) == bg + && XGetPixel (ximg, xp, y) == bg + && XGetPixel (ximg, xp, yp) == bg + && XGetPixel (ximg, xp, ym) == bg + && XGetPixel (ximg, xm, y) == bg + && XGetPixel (ximg, xm, yp) == bg + && XGetPixel (ximg, xm, ym) == bg) + XPutPixel (mask_img, x, y, 0); + else + XPutPixel (mask_img, x, y, 1); + } + } + + xassert (interrupt_input_blocked); + gc = XCreateGC (FRAME_X_DISPLAY (f), mask, 0, NULL); + XPutImage (FRAME_X_DISPLAY (f), mask, gc, mask_img, 0, 0, 0, 0, + width, height); + XFreeGC (FRAME_X_DISPLAY (f), gc); + + dpyinfo->bitmaps[id - 1].mask = mask; + + XDestroyImage (ximg); + x_destroy_x_image(mask_img); + + return 0; + } + static Lisp_Object unwind_create_frame P_ ((Lisp_Object)); static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object)); static void x_disable_image P_ ((struct frame *, struct image *)); *************** *** 974,979 **** --- 1083,1123 ---- { f->output_data.x->wait_for_wm = !NILP (new_value); } + + #ifdef USE_GTK + + /* Wrapper for gtk_window_icon_from_file() */ + + int + xg_set_icon(f, file) + struct frame *f; + Lisp_Object file; + { + struct gcpro gcpro1, gcpro2, gcpro3; + int fd; + int result = 1; + Lisp_Object found, search_path; + char *filename; + + search_path = Fcons (Vdata_directory, Vx_bitmap_file_path); + + GCPRO3 (found, search_path, file); + fd = openp (search_path, file, Qnil, &found, Qnil); + if (fd > 0) + { + filename = (char *) SDATA (found); + BLOCK_INPUT; + result = + gtk_window_set_icon_from_file (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + filename, + NULL); + UNBLOCK_INPUT; + } + emacs_close (fd); + UNGCPRO; + return result; + } + #endif /* USE_GTK */ /* Functions called only from `x_set_frame_param' Index: src/xterm.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/xterm.c,v retrieving revision 1.793 diff -c -r1.793 xterm.c *** src/xterm.c 21 May 2003 22:11:50 -0000 1.793 --- src/xterm.c 23 May 2003 09:58:05 -0000 *************** *** 7479,7502 **** if (FRAME_X_WINDOW (f) == 0) return 1; ! /* Free up our existing icon bitmap if any. */ if (f->output_data.x->icon_bitmap > 0) x_destroy_bitmap (f, f->output_data.x->icon_bitmap); f->output_data.x->icon_bitmap = 0; if (STRINGP (file)) ! bitmap_id = x_create_bitmap_from_file (f, file); else { ! /* Create the GNU bitmap if necessary. */ if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0) ! FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id ! = x_create_bitmap_from_data (f, gnu_bits, ! gnu_width, gnu_height); ! /* The first time we create the GNU bitmap, this increments the ref-count one extra time. ! As a result, the GNU bitmap is never freed. That way, we don't have to worry about allocating it again. */ x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); --- 7479,7514 ---- if (FRAME_X_WINDOW (f) == 0) return 1; ! /* Free up our existing icon bitmap and mask if any. */ if (f->output_data.x->icon_bitmap > 0) x_destroy_bitmap (f, f->output_data.x->icon_bitmap); f->output_data.x->icon_bitmap = 0; if (STRINGP (file)) ! { ! #ifdef USE_GTK ! /* Use gtk_window_set_icon_from_file() if available, ! It's not restricted to bitmaps */ ! if (!xg_set_icon(f, file)) ! return 0; ! #endif /* USE_GTK */ ! bitmap_id = x_create_bitmap_from_file (f, file); ! x_create_bitmap_mask(f, bitmap_id); ! } else { ! /* Create the GNU bitmap and mask if necessary. */ if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0) ! { ! FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id ! = x_create_bitmap_from_data (f, gnu_bits, ! gnu_width, gnu_height); ! x_create_bitmap_mask(f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); ! } ! /* The first time we create the GNU bitmap and mask, this increments the ref-count one extra time. ! As a result, the GNU bitmap and mask are never freed. That way, we don't have to worry about allocating it again. */ x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id); *************** *** 9315,9321 **** struct frame *f; int pixmap_id; { ! Pixmap icon_pixmap; #ifndef USE_X_TOOLKIT Window window = FRAME_OUTER_WINDOW (f); --- 9327,9333 ---- struct frame *f; int pixmap_id; { ! Pixmap icon_pixmap, icon_mask; #ifndef USE_X_TOOLKIT Window window = FRAME_OUTER_WINDOW (f); *************** *** 9325,9330 **** --- 9337,9344 ---- { icon_pixmap = x_bitmap_pixmap (f, pixmap_id); f->output_data.x->wm_hints.icon_pixmap = icon_pixmap; + icon_mask = x_bitmap_mask (f, pixmap_id); + f->output_data.x->wm_hints.icon_mask = icon_mask; } else { *************** *** 9337,9342 **** --- 9351,9357 ---- best to explicitly give up. */ #if 0 f->output_data.x->wm_hints.icon_pixmap = None; + f->output_data.x->wm_hints.icon_mask = None; #else return; #endif *************** *** 9348,9358 **** Arg al[1]; XtSetArg (al[0], XtNiconPixmap, icon_pixmap); XtSetValues (f->output_data.x->widget, al, 1); } #else /* not USE_X_TOOLKIT */ ! f->output_data.x->wm_hints.flags |= IconPixmapHint; XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints); #endif /* not USE_X_TOOLKIT */ --- 9363,9375 ---- Arg al[1]; XtSetArg (al[0], XtNiconPixmap, icon_pixmap); XtSetValues (f->output_data.x->widget, al, 1); + XtSetArg (al[0], XtNiconMask, icon_mask); + XtSetValues (f->output_data.x->widget, al, 1); } #else /* not USE_X_TOOLKIT */ ! f->output_data.x->wm_hints.flags |= (IconPixmapHint | IconMaskHint); XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints); #endif /* not USE_X_TOOLKIT */ Index: src/xterm.h =================================================================== RCS file: /cvsroot/emacs/emacs/src/xterm.h,v retrieving revision 1.147 diff -c -r1.147 xterm.h *** src/xterm.h 21 May 2003 22:11:31 -0000 1.147 --- src/xterm.h 23 May 2003 09:58:05 -0000 *************** *** 126,131 **** --- 126,132 ---- struct x_bitmap_record { Pixmap pixmap; + Pixmap mask; char *file; int refcount; /* Record some info about this pixmap. */ *************** *** 1096,1101 **** --- 1097,1106 ---- unsigned int, unsigned int)); extern int x_create_bitmap_from_file P_ ((struct frame *, Lisp_Object)); extern void x_destroy_bitmap P_ ((struct frame *, int)); + extern int x_create_bitmap_mask P_ ((struct frame * , int)); + + extern int xg_set_icon P_ ((struct frame *, Lisp_Object)); + extern void x_real_positions P_ ((struct frame *, int *, int *)); extern int defined_color P_ ((struct frame *, char *, XColor *, int)); extern void x_set_border_pixel P_ ((struct frame *, int));