emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Adding mask to the window icon


From: Terje Rosten
Subject: Adding mask to the window icon
Date: Fri, 23 May 2003 12:44:51 +0200
User-agent: Gnus/5.1003 (Gnus v5.10.3) Emacs/21.2 (gnu/linux)

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));





reply via email to

[Prev in Thread] Current Thread [Next in Thread]