]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
* macterm.c (XTread_socket): Call DragWindow only for mouseDown events.
[gnu-emacs] / src / xterm.c
index 590ce4f7917d9e3c36ee3abb416dd65c5aa787d2..c686824a00353e83badb2bad4f8e2999b73656c4 100644 (file)
@@ -159,7 +159,12 @@ extern void _XEditResCheckMessages ();
 #define abs(x) ((x) < 0 ? -(x) : (x))
 
 /* Default to using XIM if available.  */
+#ifdef USE_XIM
 int use_xim = 1;
+#else
+int use_xim = 0;  /* configure --without-xim */
+#endif
+
 \f
 
 /* Non-nil means Emacs uses toolkit scroll bars.  */
@@ -299,7 +304,7 @@ static Lisp_Object Qvendor_specific_keysyms;
 static Lisp_Object Qlatin_1;
 
 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
-
+extern int x_bitmap_mask P_ ((FRAME_PTR, int));
 
 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
 static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
@@ -357,7 +362,7 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            Lisp_Object *, Lisp_Object *,
                                            unsigned long *));
 static void x_check_fullscreen P_ ((struct frame *));
-static void x_check_fullscreen_move P_ ((struct frame *));
+static void x_check_expected_move P_ ((struct frame *));
 static int handle_one_xevent P_ ((struct x_display_info *,
                                   XEvent *,
                                   struct input_event **,
@@ -529,7 +534,7 @@ x_draw_vertical_window_border (w, x, y0, y1)
      int x, y0, y1;
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  
+
   XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
             f->output_data.x->normal_gc, x, y0, x, y1);
 }
@@ -3983,7 +3988,7 @@ xt_action_hook (widget, client_data, action_name, event, params,
       x_send_scroll_bar_event (window_being_scrolled,
                               scroll_bar_end_scroll, 0, 0);
       w = XWINDOW (window_being_scrolled);
-      
+
       if (!NILP (XSCROLL_BAR (w->vertical_scroll_bar)->dragging))
        {
          XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
@@ -5985,6 +5990,9 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           x_real_positions (f, &x, &y);
           f->left_pos = x;
           f->top_pos = y;
+
+          /* Perhaps reparented due to a WM restart.  Reset this.  */
+          FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
         }
       goto OTHER;
       break;
@@ -6720,7 +6728,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
              do this one, the right one will come later.
              The toolkit version doesn't seem to need this, but we
              need to reset it below.  */
-          int dont_resize 
+          int dont_resize
            = ((f->want_fullscreen & FULLSCREEN_WAIT)
               && f->new_text_cols != 0);
           int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event.xconfigure.height);
@@ -6762,7 +6770,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                 Convert that to the position of the window manager window.  */
              x_real_positions (f, &f->left_pos, &f->top_pos);
 
-             x_check_fullscreen_move (f);
+             x_check_expected_move (f);
              if (f->want_fullscreen & FULLSCREEN_WAIT)
                f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
             }
@@ -6989,10 +6997,14 @@ x_dispatch_event (event, display)
 {
   struct x_display_info *dpyinfo;
   struct input_event bufp[10];
-  struct input_event *bufpp = bufp;
+  struct input_event *bufpp;
   int numchars = 10;
   int finish = X_EVENT_NORMAL;
 
+  for (bufpp = bufp; bufpp != bufp + 10; bufpp++)
+    EVENT_INIT (*bufpp);
+  bufpp = bufp;
+
   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
     if (dpyinfo->display == display)
       break;
@@ -7455,24 +7467,36 @@ x_bitmap_icon (f, file)
   if (FRAME_X_WINDOW (f) == 0)
     return 1;
 
-  /* Free up our existing icon bitmap if any.  */
+  /* 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))
-    bitmap_id = x_create_bitmap_from_file (f, 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 if necessary.  */
+      /* 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);
+       {
+         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,
+      /* The first time we create the GNU bitmap and mask,
         this increments the ref-count one extra time.
-        As a result, the GNU bitmap is never freed.
+        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);
 
@@ -8003,6 +8027,7 @@ xim_open_dpy (dpyinfo, resource_name)
 {
   XIM xim;
 
+#ifdef HAVE_XIM
   if (use_xim)
     {
       xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name,
@@ -8027,6 +8052,7 @@ xim_open_dpy (dpyinfo, resource_name)
     }
 
   else
+#endif /* HAVE_XIM */
     dpyinfo->xim = NULL;
 }
 
@@ -8101,6 +8127,7 @@ xim_initialize (dpyinfo, resource_name)
      struct x_display_info *dpyinfo;
      char *resource_name;
 {
+#ifdef HAVE_XIM
   if (use_xim)
     {
 #ifdef HAVE_X11R6_XIM
@@ -8116,10 +8143,10 @@ xim_initialize (dpyinfo, resource_name)
       XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
                                      resource_name, EMACS_CLASS,
                                      xim_instantiate_callback,
-                                     /* Fixme: This is XPointer in
-                                        XFree86 but (XPointer *) on
-                                        Tru64, at least.  */
-                                     (XPointer) xim_inst);
+                                     /* This is XPointer in XFree86
+                                        but (XPointer *) on Tru64, at
+                                        least, hence the configure test.  */
+                                     (XRegisterIMInstantiateCallback_arg6) xim_inst);
 #else /* not HAVE_X11R6_XIM */
       dpyinfo->xim = NULL;
       xim_open_dpy (dpyinfo, resource_name);
@@ -8127,6 +8154,7 @@ xim_initialize (dpyinfo, resource_name)
 
     }
   else
+#endif /* HAVE_XIM */
     dpyinfo->xim = NULL;
 }
 
@@ -8137,6 +8165,7 @@ static void
 xim_close_dpy (dpyinfo)
      struct x_display_info *dpyinfo;
 {
+#ifdef HAVE_XIM
   if (use_xim)
     {
 #ifdef HAVE_X11R6_XIM
@@ -8150,6 +8179,7 @@ xim_close_dpy (dpyinfo)
       dpyinfo->xim = NULL;
       XFree (dpyinfo->xim_styles);
     }
+#endif /* HAVE_XIM */
 }
 
 #endif /* not HAVE_X11R6_XIM */
@@ -8287,12 +8317,13 @@ x_set_offset (f, xoff, yoff, change_gravity)
       f->win_gravity = NorthWestGravity;
     }
   x_calc_absolute_position (f);
-
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
   modified_left = f->left_pos;
   modified_top = f->top_pos;
+
 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
         this seems to be unnecessary and incorrect.  rms, 4/17/97.  */
   /* It is a mystery why we need to add the border_width here
@@ -8304,8 +8335,26 @@ x_set_offset (f, xoff, yoff, change_gravity)
     }
 #endif
 
+  if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
+    {
+      /* Some WMs (twm, wmaker at least) has an offset that is smaller
+         than the WM decorations.  So we use the calculated offset instead
+         of the WM decoration sizes here (x/y_pixels_outer_diff).  */
+      modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
+      modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
+    }
+
   XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
                modified_left, modified_top);
+
+  if (FRAME_VISIBLE_P (f)
+      && FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
+    {
+      FRAME_X_OUTPUT (f)->check_expected_move = 1;
+      FRAME_X_OUTPUT (f)->expected_top = f->top_pos;
+      FRAME_X_OUTPUT (f)->expected_left = f->left_pos;
+    }
+
   UNBLOCK_INPUT;
 }
 
@@ -8326,7 +8375,7 @@ x_check_fullscreen (f)
       /* We do not need to move the window, it shall be taken care of
          when setting WM manager hints.
          If the frame is visible already, the position is checked by
-         x_check_fullscreen_move. */
+         x_check_expected_move. */
       if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
         {
           change_frame_size (f, height, width, 0, 1, 0);
@@ -8340,30 +8389,33 @@ x_check_fullscreen (f)
 }
 
 /* If frame parameters are set after the frame is mapped, we need to move
-   the window.  This is done in xfns.c.
+   the window.
    Some window managers moves the window to the right position, some
    moves the outer window manager window to the specified position.
    Here we check that we are in the right spot.  If not, make a second
    move, assuming we are dealing with the second kind of window manager. */
 static void
-x_check_fullscreen_move (f)
+x_check_expected_move (f)
      struct frame *f;
 {
-  if (f->want_fullscreen & FULLSCREEN_MOVE_WAIT)
+  if (FRAME_X_OUTPUT (f)->check_expected_move)
   {
-    int expect_top = f->top_pos;
-    int expect_left = f->left_pos;
-
-    if (f->want_fullscreen & FULLSCREEN_HEIGHT)
-      expect_top = 0;
-    if (f->want_fullscreen & FULLSCREEN_WIDTH)
-      expect_left = 0;
+    int expect_top = FRAME_X_OUTPUT (f)->expected_top;
+    int expect_left = FRAME_X_OUTPUT (f)->expected_left;
 
     if (expect_top != f->top_pos || expect_left != f->left_pos)
-      x_set_offset (f, expect_left, expect_top, 1);
+      {
+        FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
+        FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos;
+        FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos;
+
+        x_set_offset (f, expect_left, expect_top, 1);
+      }
+    else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
+      FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_B;
 
     /* Just do this once */
-    f->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
+    FRAME_X_OUTPUT (f)->check_expected_move = 0;
   }
 }
 
@@ -9287,7 +9339,7 @@ x_wm_set_icon_pixmap (f, pixmap_id)
      struct frame *f;
      int pixmap_id;
 {
-  Pixmap icon_pixmap;
+  Pixmap icon_pixmap, icon_mask;
 
 #ifndef USE_X_TOOLKIT
   Window window = FRAME_OUTER_WINDOW (f);
@@ -9297,6 +9349,8 @@ x_wm_set_icon_pixmap (f, pixmap_id)
     {
       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
     {
@@ -9309,6 +9363,7 @@ x_wm_set_icon_pixmap (f, pixmap_id)
         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
@@ -9320,11 +9375,13 @@ x_wm_set_icon_pixmap (f, pixmap_id)
     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;
+  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 */
@@ -9834,6 +9891,7 @@ x_load_font (f, fontname, size)
 
     /* Now fill in the slots of *FONTP.  */
     BLOCK_INPUT;
+    bzero (fontp, sizeof (*fontp));
     fontp->font = font;
     fontp->font_idx = i;
     fontp->name = (char *) xmalloc (strlen (fontname) + 1);
@@ -10088,6 +10146,34 @@ same_x_server (name1, name2)
 }
 #endif
 
+/* Count number of set bits in mask and number of bits to shift to
+   get to the first bit.  With MASK 0x7e0, *BITS is set to 6, and *OFFSET
+   to 5.  */
+static void
+get_bits_and_offset (mask, bits, offset)
+     unsigned long mask;
+     int *bits;
+     int *offset;
+{
+  int nr = 0;
+  int off = 0;
+
+  while (!(mask & 1))
+    {
+      off++;
+      mask >>= 1;
+    }
+
+  while (mask & 1)
+    {
+      nr++;
+      mask >>= 1;
+    }
+
+  *offset = off;
+  *bits = nr;
+}
+
 struct x_display_info *
 x_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -10104,7 +10190,7 @@ x_term_init (display_name, xrm_option, resource_name)
   if (!x_initialized)
     {
       x_initialize ();
-      x_initialized = 1;
+      ++x_initialized;
     }
 
 #ifdef USE_GTK
@@ -10120,8 +10206,6 @@ x_term_init (display_name, xrm_option, resource_name)
     if (x_initialized > 1)
       return 0;
 
-    x_initialized++;
-
     for (argc = 0; argc < NUM_ARGV; ++argc)
       argv[argc] = 0;
 
@@ -10162,7 +10246,7 @@ x_term_init (display_name, xrm_option, resource_name)
       s = make_string (file, strlen (file));
       abs_file = Fexpand_file_name(s, Qnil);
 
-      if (! NILP (abs_file) && Ffile_readable_p (abs_file))
+      if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
         gtk_rc_parse (SDATA (abs_file));
 
       UNGCPRO;
@@ -10311,6 +10395,7 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->height = HeightOfScreen (dpyinfo->screen);
   dpyinfo->width = WidthOfScreen (dpyinfo->screen);
   dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
+  dpyinfo->client_leader_window = 0;
   dpyinfo->grabbed = 0;
   dpyinfo->reference_count = 0;
   dpyinfo->icon_bitmap_id = -1;
@@ -10335,7 +10420,22 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo->x_focus_event_frame = 0;
   dpyinfo->x_highlight_frame = 0;
   dpyinfo->image_cache = make_image_cache ();
+  dpyinfo->wm_type = X_WMTYPE_UNKNOWN;
+
+  /* See if we can construct pixel values from RGB values.  */
+  dpyinfo->red_bits = dpyinfo->blue_bits = dpyinfo->green_bits = 0;
+  dpyinfo->red_offset = dpyinfo->blue_offset = dpyinfo->green_offset = 0;
 
+  if (dpyinfo->visual->class == TrueColor)
+    {
+      get_bits_and_offset (dpyinfo->visual->red_mask,
+                           &dpyinfo->red_bits, &dpyinfo->red_offset);
+      get_bits_and_offset (dpyinfo->visual->blue_mask,
+                           &dpyinfo->blue_bits, &dpyinfo->blue_offset);
+      get_bits_and_offset (dpyinfo->visual->green_mask,
+                           &dpyinfo->green_bits, &dpyinfo->green_offset);
+    }
+      
   /* See if a private colormap is requested.  */
   if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
     {
@@ -10380,6 +10480,8 @@ x_term_init (display_name, xrm_option, resource_name)
     = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
   dpyinfo->Xatom_wm_window_moved
     = XInternAtom (dpyinfo->display, "WM_MOVED", False);
+  dpyinfo->Xatom_wm_client_leader
+    = XInternAtom (dpyinfo->display, "WM_CLIENT_LEADER", False);
   dpyinfo->Xatom_editres
     = XInternAtom (dpyinfo->display, "Editres", False);
   dpyinfo->Xatom_CLIPBOARD
@@ -10514,19 +10616,32 @@ x_term_init (display_name, xrm_option, resource_name)
            || !strcmp (SDATA (value), "on")))
       XSynchronize (dpyinfo->display, True);
   }
-  
+
   {
     Lisp_Object value;
     value = display_x_get_resource (dpyinfo,
                                    build_string ("useXIM"),
                                    build_string ("UseXIM"),
                                    Qnil, Qnil);
+#ifdef USE_XIM
     if (STRINGP (value)
        && (!strcmp (XSTRING (value)->data, "false")
            || !strcmp (XSTRING (value)->data, "off")))
       use_xim = 0;
+#else
+    if (STRINGP (value)
+       && (!strcmp (XSTRING (value)->data, "true")
+           || !strcmp (XSTRING (value)->data, "on")))
+      use_xim = 1;
+#endif
   }
 
+#ifdef HAVE_X_SM
+  /* Only do this for the first display.  */
+  if (x_initialized == 1)
+    x_session_initialize (dpyinfo);
+#endif
+
   UNBLOCK_INPUT;
 
   return dpyinfo;
@@ -10539,6 +10654,8 @@ void
 x_delete_display (dpyinfo)
      struct x_display_info *dpyinfo;
 {
+  int i;
+
   delete_keyboard_wait_descriptor (dpyinfo->connection);
 
   /* Discard this display from x_display_name_list and x_display_list.
@@ -10590,6 +10707,18 @@ x_delete_display (dpyinfo)
     xim_close_dpy (dpyinfo);
 #endif
 
+  /* Free the font names in the font table.  */
+  for (i = 0; i < dpyinfo->n_fonts; i++)
+    if (dpyinfo->font_table[i].name)
+      {
+       if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
+         xfree (dpyinfo->font_table[i].full_name);
+       xfree (dpyinfo->font_table[i].name);
+      }
+
+  if (dpyinfo->font_table->font_encoder)
+    xfree (dpyinfo->font_table->font_encoder);
+
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->x_id_name);
   xfree (dpyinfo->color_cells);
@@ -10740,10 +10869,6 @@ x_initialize ()
 #endif /* SIGWINCH */
 
   signal (SIGPIPE, x_connection_signal);
-
-#ifdef HAVE_X_SM
-  x_session_initialize ();
-#endif
 }
 
 
@@ -10846,3 +10971,6 @@ default is nil, which is the same as `super'.  */);
 }
 
 #endif /* HAVE_X_WINDOWS */
+
+/* arch-tag: 6d4e4cb7-abc1-4302-9585-d84dcfb09d0f
+   (do not change this comment) */