(Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym)
[bpt/emacs.git] / src / xterm.c
index fd2964e..e638253 100644 (file)
@@ -381,6 +381,11 @@ extern int errno;
 
 extern int extra_keyboard_modifiers;
 
+/* The keysyms to use for the various modifiers.  */
+
+Lisp_Object Vx_alt_keysym, Vx_hyper_keysym, Vx_meta_keysym, Vx_super_keysym;
+static Lisp_Object Qalt, Qhyper, Qmeta, Qsuper, Qmodifier_value;
+
 static Lisp_Object Qvendor_specific_keysyms;
 
 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
@@ -490,6 +495,8 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            enum scroll_bar_part *,
                                            Lisp_Object *, Lisp_Object *,
                                            unsigned long *));
+static void x_check_fullscreen P_ ((struct frame *));
+static void x_check_fullscreen_move P_ ((struct frame *));
 
 /* Flush display of frame F, or of all frames if F is null.  */
 
@@ -1608,7 +1615,7 @@ x_append_stretch_glyph (it, object, width, height, ascent)
    4. `:height HEIGHT' specifies that the height of the stretch produced
    should be HEIGHT, measured in canonical character units.
 
-   5. `:relative-height FACTOR' specifies that the height of the the
+   5. `:relative-height FACTOR' specifies that the height of the
    stretch should be FACTOR times the height of the characters having
    the glyph property.
 
@@ -3837,6 +3844,7 @@ x_setup_relief_colors (s)
   if (s->face->use_box_color_for_shadows_p)
     color = s->face->box_color;
   else if (s->first_glyph->type == IMAGE_GLYPH
+          && s->img->pixmap
           && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
     color = IMAGE_BACKGROUND (s->img, s->f, 0);
   else
@@ -6419,12 +6427,28 @@ x_x_to_emacs_modifiers (dpyinfo, state)
      struct x_display_info *dpyinfo;
      unsigned int state;
 {
+  EMACS_UINT mod_meta = meta_modifier;
+  EMACS_UINT mod_alt  = alt_modifier;
+  EMACS_UINT mod_hyper = hyper_modifier;
+  EMACS_UINT mod_super = super_modifier;
+  Lisp_Object tem;
+  
+  tem = Fget (Vx_alt_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
+  tem = Fget (Vx_meta_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
+  tem = Fget (Vx_hyper_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
+  tem = Fget (Vx_super_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
+  
+
   return (  ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
-         | ((state & ControlMask)             ? ctrl_modifier  : 0)
-         | ((state & dpyinfo->meta_mod_mask)  ? meta_modifier  : 0)
-         | ((state & dpyinfo->alt_mod_mask)   ? alt_modifier  : 0)
-         | ((state & dpyinfo->super_mod_mask) ? super_modifier  : 0)
-         | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier  : 0));
+            | ((state & ControlMask)                   ? ctrl_modifier : 0)
+            | ((state & dpyinfo->meta_mod_mask)                ? mod_meta      : 0)
+            | ((state & dpyinfo->alt_mod_mask)         ? mod_alt       : 0)
+            | ((state & dpyinfo->super_mod_mask)       ? mod_super     : 0)
+            | ((state & dpyinfo->hyper_mod_mask)       ? mod_hyper     : 0));
 }
 
 static unsigned int
@@ -6432,12 +6456,29 @@ x_emacs_to_x_modifiers (dpyinfo, state)
      struct x_display_info *dpyinfo;
      unsigned int state;
 {
-  return (  ((state & alt_modifier)    ? dpyinfo->alt_mod_mask   : 0)
-         | ((state & super_modifier)   ? dpyinfo->super_mod_mask : 0)
-         | ((state & hyper_modifier)   ? dpyinfo->hyper_mod_mask : 0)
-         | ((state & shift_modifier)   ? ShiftMask        : 0)
-         | ((state & ctrl_modifier)    ? ControlMask      : 0)
-         | ((state & meta_modifier)    ? dpyinfo->meta_mod_mask  : 0));
+  EMACS_UINT mod_meta = meta_modifier;
+  EMACS_UINT mod_alt  = alt_modifier;
+  EMACS_UINT mod_hyper = hyper_modifier;
+  EMACS_UINT mod_super = super_modifier;
+  
+  Lisp_Object tem;
+  
+  tem = Fget (Vx_alt_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_alt = XUINT (tem);
+  tem = Fget (Vx_meta_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_meta = XUINT (tem);
+  tem = Fget (Vx_hyper_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_hyper = XUINT (tem);
+  tem = Fget (Vx_super_keysym, Qmodifier_value);
+  if (! EQ (tem, Qnil)) mod_super = XUINT (tem);
+  
+  
+  return (  ((state & mod_alt)         ? dpyinfo->alt_mod_mask   : 0)
+            | ((state & mod_super)     ? dpyinfo->super_mod_mask : 0)
+            | ((state & mod_hyper)     ? dpyinfo->hyper_mod_mask : 0)
+            | ((state & shift_modifier)        ? ShiftMask        : 0)
+            | ((state & ctrl_modifier) ? ControlMask      : 0)
+            | ((state & mod_meta)      ? dpyinfo->meta_mod_mask  : 0));
 }
 
 /* Convert a keysym to its name.  */
@@ -7467,7 +7508,7 @@ note_tool_bar_highlight (f, x, y)
       
  set_help_echo:
   
-  /* Set help_echo to a help string.to display for this tool-bar item.
+  /* Set help_echo to a help string to display for this tool-bar item.
      XTread_socket does the rest.  */
   help_echo_object = help_echo_window = Qnil;
   help_echo_pos = -1;
@@ -7653,9 +7694,9 @@ fast_find_position (w, pos, hpos, vpos, x, y, stop)
 #endif /* not 0 */
 
 
-/* Find the position of the the glyph for position POS in OBJECT in
-   window W's current matrix, and return in *X/*Y the pixel
-   coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
+/* Find the position of the glyph for position POS in OBJECT in
+   window W's current matrix, and return in *X*Y the pixel
+   coordinates, and return in *HPOS*VPOS the column/row of the glyph.
 
    RIGHT_P non-zero means return the position of the right edge of the
    glyph, RIGHT_P zero means return the left edge position.
@@ -10242,6 +10283,8 @@ XTread_socket (sd, bufp, numchars, expected)
              f = x_window_to_frame (dpyinfo, event.xexpose.window);
              if (f)
                {
+                  x_check_fullscreen (f);
+
                  if (f->async_visible == 0)
                    {
                      f->async_visible = 1;
@@ -10844,8 +10887,17 @@ XTread_socket (sd, bufp, numchars, expected)
              if (f)
                {
 #ifndef USE_X_TOOLKIT
+                  /* If there is a pending resize for fullscreen, don't
+                     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 =
+                    ((f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
+                     && FRAME_NEW_WIDTH (f) != 0);
                  int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
                  int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
+                  if (dont_resize)
+                    goto OTHER;
                  
                  /* In the toolkit version, change_frame_size
                     is called by the code that handles resizing
@@ -10873,6 +10925,10 @@ XTread_socket (sd, bufp, numchars, expected)
                  x_real_positions (f, &f->output_data.x->left_pos,
                                    &f->output_data.x->top_pos);
 
+                  x_check_fullscreen_move(f);
+                  if (f->output_data.x->want_fullscreen & FULLSCREEN_WAIT)
+                    f->output_data.x->want_fullscreen &=
+                      ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
 #ifdef HAVE_X_I18N
                  if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
                    xic_set_statusarea (f);
@@ -11378,6 +11434,12 @@ x_erase_phys_cursor (w)
   if (!cursor_row->enabled_p)
     goto mark_cursor_off;
   
+  /* If row is completely invisible, don't attempt to delete a cursor which
+     isn't there.  This can happen if cursor is at top of a window, and
+     we switch to a buffer with a header line in that window.  */
+  if (cursor_row->visible_height <= 0)
+    goto mark_cursor_off;
+  
   /* This can happen when the new row is shorter than the old one.
      In this case, either x_draw_glyphs or clear_end_of_line
      should have cleared the cursor.  Note that we wouldn't be
@@ -12642,6 +12704,114 @@ x_set_offset (f, xoff, yoff, change_gravity)
   UNBLOCK_INPUT;
 }
 
+/* Check if we need to resize the frame due to a fullscreen request.
+   If so needed, resize the frame. */
+static void
+x_check_fullscreen (f)
+     struct frame *f;
+{
+  if (f->output_data.x->want_fullscreen & FULLSCREEN_BOTH)
+    {
+      int width, height, ign;
+                      
+      x_real_positions (f, &f->output_data.x->left_pos,
+                        &f->output_data.x->top_pos);
+
+      x_fullscreen_adjust (f, &width, &height, &ign, &ign);
+                  
+      /* 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. */
+      if (f->width != width || f->height != height)
+        {
+          change_frame_size (f, height, width, 0, 1, 0);
+          SET_FRAME_GARBAGED (f);
+          cancel_mouse_face (f);
+
+          /* Wait for the change of frame size to occur */
+          f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT;
+          
+        }
+    }
+}
+
+/* If frame parameters are set after the frame is mapped, we need to move
+   the window.  This is done in xfns.c.
+   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)
+     struct frame *f;
+{
+  if (f->output_data.x->want_fullscreen & FULLSCREEN_MOVE_WAIT)
+  {
+    int expect_top = f->output_data.x->top_pos;
+    int expect_left = f->output_data.x->left_pos;
+
+    if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
+      expect_top = 0;
+    if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
+      expect_left = 0;
+    
+    if (expect_top != f->output_data.x->top_pos
+        || expect_left != f->output_data.x->left_pos)
+      x_set_offset (f, expect_left, expect_top, 1);
+
+    /* Just do this once */
+    f->output_data.x->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
+  }
+}
+
+
+/* Calculate fullscreen size.  Return in *TOP_POS and *LEFT_POS the
+   wanted positions of the WM window (not emacs window).
+   Return in *WIDTH and *HEIGHT the wanted width and height of Emacs
+   window (FRAME_X_WINDOW).
+ */
+void
+x_fullscreen_adjust (f, width, height, top_pos, left_pos)
+     struct frame *f;
+     int *width;
+     int *height;
+     int *top_pos;
+     int *left_pos;
+{
+  int newwidth = f->width, newheight = f->height;
+
+  *top_pos = f->output_data.x->top_pos;
+  *left_pos = f->output_data.x->left_pos;
+  
+  if (f->output_data.x->want_fullscreen & FULLSCREEN_HEIGHT)
+    {
+      int ph;
+      
+      ph = FRAME_X_DISPLAY_INFO (f)->height;
+      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+      ph = CHAR_TO_PIXEL_HEIGHT (f, newheight)
+        - f->output_data.x->y_pixels_diff;
+      newheight = PIXEL_TO_CHAR_HEIGHT (f, ph);
+      *top_pos = 0;
+    }
+
+  if (f->output_data.x->want_fullscreen & FULLSCREEN_WIDTH)
+    {
+      int pw;
+      
+      pw = FRAME_X_DISPLAY_INFO (f)->width;
+      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+      pw = CHAR_TO_PIXEL_WIDTH (f, newwidth)
+        - f->output_data.x->x_pixels_diff;
+      newwidth = PIXEL_TO_CHAR_WIDTH (f, pw);
+      *left_pos = 0;
+    }
+
+  *width = newwidth;
+  *height = newheight;
+}
+
 
 /* Change the size of frame F's X window to COLS/ROWS in the case F
    doesn't have a widget.  If CHANGE_GRAVITY is 1, we change to
@@ -14172,10 +14342,10 @@ x_load_font (f, fontname, size)
 
     /* Set global flag fonts_changed_p to non-zero if the font loaded
        has a character with a smaller width than any other character
-       before, or if the font loaded has a smalle>r height than any
+       before, or if the font loaded has a smaller height than any
        other font loaded before.  If this happens, it will make a
        glyph matrix reallocation necessary.  */
-    fonts_changed_p = x_compute_min_glyph_bounds (f);
+    fonts_changed_p |= x_compute_min_glyph_bounds (f);
     UNBLOCK_INPUT;
     return fontp;
   }
@@ -14903,6 +15073,45 @@ Otherwise, value is a symbol describing the X toolkit.  */);
 
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
+  
+  Qmodifier_value = intern ("modifier-value");
+  Qalt = intern ("alt");
+  Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
+  Qhyper = intern ("hyper");
+  Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
+  Qmeta = intern ("meta");
+  Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
+  Qsuper = intern ("super");
+  Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
+  
+  DEFVAR_LISP ("x-alt-keysym", &Vx_alt_keysym,
+    doc: /* Which keys Emacs uses for the alt modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `alt' means use the Alt_L and Alt_R keysyms.  The default
+is nil, which is the same as `alt'.  */);
+  Vx_alt_keysym = Qnil;
+  
+  DEFVAR_LISP ("x-hyper-keysym", &Vx_hyper_keysym,
+    doc: /* Which keys Emacs uses for the hyper modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `hyper' means use the Hyper_L and Hyper_R keysyms.  The
+default is nil, which is the same as `hyper'.  */);
+  Vx_hyper_keysym = Qnil;
+  
+  DEFVAR_LISP ("x-meta-keysym", &Vx_meta_keysym,
+    doc: /* Which keys Emacs uses for the meta modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `meta' means use the Meta_L and Meta_R keysyms.  The
+default is nil, which is the same as `meta'.  */);
+  Vx_meta_keysym = Qnil;
+  
+  DEFVAR_LISP ("x-super-keysym", &Vx_super_keysym,
+    doc: /* Which keys Emacs uses for the super modifier.
+This should be one of the symbols `alt', `hyper', `meta', `super'.
+For example, `super' means use the Super_L and Super_R keysyms.  The
+default is nil, which is the same as `super'.  */);
+  Vx_super_keysym = Qnil;
+
 }
 
 #endif /* HAVE_X_WINDOWS */