X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/da85a02af7585384008d3ebec836a7b8571f175d..92dca4df0956bc153431f79dbfdd0235c1f9fded:/src/widget.c diff --git a/src/widget.c b/src/widget.c index a09ec2631a..bd0fe826e6 100644 --- a/src/widget.c +++ b/src/widget.c @@ -1,5 +1,5 @@ /* The emacs frame widget. - Copyright (C) 1992-1993, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1992-1993, 2000-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -30,7 +30,7 @@ along with GNU Emacs. If not, see . */ #include #include -#include + #include "lisp.h" #include "xterm.h" @@ -50,9 +50,6 @@ along with GNU Emacs. If not, see . */ #include #include "../lwlib/lwlib.h" -#include -#include "syssignal.h" - #include "character.h" #include "font.h" @@ -86,12 +83,12 @@ static XtGeometryResult EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry #undef XtOffset #define XtOffset(p_type,field) \ ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0))) -#define offset(field) XtOffset(EmacsFrame, emacs_frame.field) +#define offset(field) XtOffset (EmacsFrame, emacs_frame.field) static XtResource resources[] = { - {XtNgeometry, XtCGeometry, XtRString, sizeof(String), + {XtNgeometry, XtCGeometry, XtRString, sizeof (String), offset (geometry), XtRString, (XtPointer) 0}, - {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean), + {XtNiconic, XtCIconic, XtRBoolean, sizeof (Boolean), offset (iconic), XtRImmediate, (XtPointer) False}, {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer), @@ -105,12 +102,12 @@ static XtResource resources[] = { offset (internal_border_width), XtRImmediate, (XtPointer)4}, {XtNinterline, XtCInterline, XtRInt, sizeof (int), offset (interline), XtRImmediate, (XtPointer)0}, - {XtNfont, XtCFont, XtRFontStruct, sizeof(struct font *), - offset(font),XtRString, DEFAULT_FACE_FONT}, - {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), - offset(foreground_pixel), XtRString, "XtDefaultForeground"}, - {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel), - offset(cursor_color), XtRString, "XtDefaultForeground"}, + {XtNfont, XtCFont, XtRFontStruct, sizeof (struct font *), + offset (font),XtRString, DEFAULT_FACE_FONT}, + {XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel), + offset (foreground_pixel), XtRString, "XtDefaultForeground"}, + {XtNcursorColor, XtCForeground, XtRPixel, sizeof (Pixel), + offset (cursor_color), XtRString, "XtDefaultForeground"}, {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean), offset (bar_cursor), XtRImmediate, (XtPointer)0}, {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean), @@ -141,7 +138,7 @@ static EmacsFrameClassRec emacsFrameClassRec = { { /* core fields */ /* superclass */ &widgetClassRec, /* class_name */ "EmacsFrame", - /* widget_size */ sizeof(EmacsFrameRec), + /* widget_size */ sizeof (EmacsFrameRec), /* class_initialize */ 0, /* class_part_initialize */ 0, /* class_inited */ FALSE, @@ -151,7 +148,7 @@ static EmacsFrameClassRec emacsFrameClassRec = { /* actions */ 0, /*emacsFrameActionsTable*/ /* num_actions */ 0, /*XtNumber (emacsFrameActionsTable)*/ /* resources */ resources, - /* resource_count */ XtNumber(resources), + /* resource_count */ XtNumber (resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, @@ -192,6 +189,14 @@ pixel_to_char_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height *char_height = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, (int) pixel_height); } +static void +pixel_to_text_size (EmacsFrame ew, Dimension pixel_width, Dimension pixel_height, int *text_width, int *text_height) +{ + struct frame* f = ew->emacs_frame.frame; + *text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, (int) pixel_width); + *text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, (int) pixel_height); +} + static void char_to_pixel_size (EmacsFrame ew, int char_width, int char_height, Dimension *pixel_width, Dimension *pixel_height) { @@ -226,7 +231,7 @@ get_wm_shell (Widget w) static void mark_shell_size_user_specified (Widget wmshell) { - if (! XtIsWMShell (wmshell)) abort (); + if (! XtIsWMShell (wmshell)) emacs_abort (); /* This is kind of sleazy, but I can't see how else to tell it to make it mark the WM_SIZE_HINTS size as user specified when appropriate. */ ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize; @@ -290,7 +295,7 @@ set_frame_size (EmacsFrame ew) Widget wmshell = get_wm_shell ((Widget) ew); /* Each Emacs shell is now independent and top-level. */ - if (! XtIsSubclass (wmshell, shellWidgetClass)) abort (); + if (! XtIsSubclass (wmshell, shellWidgetClass)) emacs_abort (); /* We don't need this for the moment. The geometry is computed in xfns.c. */ @@ -407,15 +412,13 @@ set_frame_size (EmacsFrame ew) might end up with a frame width that is not a multiple of the frame's character width which is bad for vertically split windows. */ - f->scroll_bar_actual_width - = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f); compute_fringe_widths (f, 0); #if 0 /* This can run Lisp code, and it is dangerous to give out the frame to Lisp code before it officially exists. This is handled in Fx_create_frame so not needed here. */ - change_frame_size (f, h, w, 1, 0, 0); + change_frame_size (f, w, h, 1, 0, 0, 0); #endif char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height); ew->core.width = pixel_width; @@ -429,25 +432,15 @@ set_frame_size (EmacsFrame ew) { /* the tricky things with the sign is to make sure that -0 is printed -0. */ - int len; - char *tem; sprintf (shell_position, "=%c%d%c%d", flags & XNegative ? '-' : '+', x < 0 ? -x : x, flags & YNegative ? '-' : '+', y < 0 ? -y : y); - len = strlen (shell_position) + 1; - tem = (char *) xmalloc (len); - strncpy (tem, shell_position, len); - XtVaSetValues (wmshell, XtNgeometry, tem, NULL); + XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL); } else if (flags & (WidthValue | HeightValue)) { - int len; - char *tem; sprintf (shell_position, "=%dx%d", pixel_width, pixel_height); - len = strlen (shell_position) + 1; - tem = (char *) xmalloc (len); - strncpy (tem, shell_position, len); - XtVaSetValues (wmshell, XtNgeometry, tem, NULL); + XtVaSetValues (wmshell, XtNgeometry, xstrdup (shell_position), NULL); } /* If the geometry spec we're using has W/H components, mark the size @@ -476,8 +469,11 @@ update_wm_hints (EmacsFrame ew) int base_height; int min_rows = 0, min_cols = 0; + /* This happens when the frame is just created. */ + if (! wmshell) return; + #if 0 - check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols); + check_frame_size (ew->emacs_frame.frame, &min_cols, &min_rows, 0); #endif pixel_to_char_size (ew, ew->core.width, ew->core.height, @@ -499,32 +495,20 @@ update_wm_hints (EmacsFrame ew) XtVaSetValues (wmshell, XtNbaseWidth, (XtArgVal) base_width, XtNbaseHeight, (XtArgVal) base_height, - XtNwidthInc, (XtArgVal) cw, - XtNheightInc, (XtArgVal) ch, + XtNwidthInc, (XtArgVal) (frame_resize_pixelwise ? 1 : cw), + XtNheightInc, (XtArgVal) (frame_resize_pixelwise ? 1 : ch), XtNminWidth, (XtArgVal) (base_width + min_cols * cw), XtNminHeight, (XtArgVal) (base_height + min_rows * ch), NULL); } -#if 0 - -static void -create_frame_gcs (EmacsFrame ew) +void +widget_update_wm_size_hints (Widget widget) { - struct frame *s = ew->emacs_frame.frame; - - s->output_data.x->normal_gc - = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0); - s->output_data.x->reverse_gc - = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0); - s->output_data.x->cursor_gc - = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0); - s->output_data.x->black_relief.gc = 0; - s->output_data.x->white_relief.gc = 0; + EmacsFrame ew = (EmacsFrame)widget; + update_wm_hints (ew); } -#endif /* 0 */ - static char setup_frame_cursor_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -547,7 +531,7 @@ setup_frame_gcs (EmacsFrame ew) font = Ffont_xlfd_name (font, Qnil); if (STRINGP (font)) { - XFontStruct *xfont = XLoadQueryFont (FRAME_X_DISPLAY_INFO (s)->display, + XFontStruct *xfont = XLoadQueryFont (FRAME_DISPLAY_INFO (s)->display, SSDATA (font)); if (xfont) { @@ -574,7 +558,7 @@ setup_frame_gcs (EmacsFrame ew) never actually get used as a background tile! */ blank_tile - = XCreatePixmapFromBitmapData (XtDisplay(ew), + = XCreatePixmapFromBitmapData (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), setup_frame_cursor_bits, 2, 2, 0, 1, ew->core.depth); @@ -614,11 +598,18 @@ static void update_various_frame_slots (EmacsFrame ew) { struct frame *f = ew->emacs_frame.frame; - struct x_output *x = f->output_data.x; - FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height; - FRAME_PIXEL_WIDTH (f) = ew->core.width; - f->internal_border_width = ew->emacs_frame.internal_border_width; + /* Don't do that: It confuses the check in change_frame_size_1 whether + the pixel size of the frame changed due to a change of the internal + border width. Bug#16736. */ + if (false) + { + struct x_output *x = f->output_data.x; + FRAME_PIXEL_HEIGHT (f) = ew->core.height + x->menubar_height; + FRAME_PIXEL_WIDTH (f) = ew->core.width; + } + + f->internal_border_width = ew->emacs_frame.internal_border_width; } static void @@ -652,6 +643,15 @@ EmacsFrameInitialize (Widget request, Widget new, ArgList dum1, Cardinal *dum2) set_frame_size (ew); } +static void +resize_cb (Widget widget, + XtPointer closure, + XEvent* event, + Boolean* continue_to_dispatch) +{ + EmacsFrameResize (widget); +} + static void EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs) @@ -667,27 +667,16 @@ EmacsFrameRealize (Widget widget, XtValueMask *mask, XSetWindowAttributes *attrs *mask |= CWEventMask; XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask, attrs); + /* Some ConfigureNotify events does not end up in EmacsFrameResize so + make sure we get them all. Seen with xfcwm4 for example. */ + XtAddRawEventHandler (widget, StructureNotifyMask, False, resize_cb, NULL); update_wm_hints (ew); } -extern void free_frame_faces (struct frame *); - static void EmacsFrameDestroy (Widget widget) { - EmacsFrame ew = (EmacsFrame) widget; - struct frame* s = ew->emacs_frame.frame; - - if (! s) abort (); - if (! s->output_data.x) abort (); - - BLOCK_INPUT; - x_free_gcs (s); - if (s->output_data.x->white_relief.gc) - XFreeGC (XtDisplay (widget), s->output_data.x->white_relief.gc); - if (s->output_data.x->black_relief.gc) - XFreeGC (XtDisplay (widget), s->output_data.x->black_relief.gc); - UNBLOCK_INPUT; + /* All GCs are now freed in x_free_frame_resources. */ } static void @@ -695,15 +684,39 @@ EmacsFrameResize (Widget widget) { EmacsFrame ew = (EmacsFrame)widget; struct frame *f = ew->emacs_frame.frame; - int columns; - int rows; - pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows); - change_frame_size (f, rows, columns, 0, 1, 0); - update_wm_hints (ew); - update_various_frame_slots (ew); + /* Always process resize requests pixelwise. Frame maximizing + should work even when frame_resize_pixelwise is nil. */ + if (true || frame_resize_pixelwise) + { + int width, height; - cancel_mouse_face (f); + pixel_to_text_size (ew, ew->core.width, ew->core.height, &width, &height); + change_frame_size (f, width, height, 0, 1, 0, 1); + + update_wm_hints (ew); + update_various_frame_slots (ew); + + cancel_mouse_face (f); + } + else + { + struct x_output *x = f->output_data.x; + int columns, rows; + + pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows); + if (columns != FRAME_COLS (f) + || rows != FRAME_LINES (f) + || ew->core.width != FRAME_PIXEL_WIDTH (f) + || ew->core.height + x->menubar_height != FRAME_PIXEL_HEIGHT (f)) + { + change_frame_size (f, columns, rows, 0, 1, 0, 0); + update_wm_hints (ew); + update_various_frame_slots (ew); + + cancel_mouse_face (f); + } + } } static Boolean @@ -743,6 +756,7 @@ EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, Ar if (has_to_recompute_size) { + /* Don't do this pixelwise, hopefully. */ pixel_width = new->core.width; pixel_height = new->core.height; pixel_to_char_size (new, pixel_width, pixel_height, &char_width, @@ -752,8 +766,8 @@ EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, Ar new->core.width = pixel_width; new->core.height = pixel_height; - change_frame_size (new->emacs_frame.frame, char_height, char_width, - 1, 0, 0); + change_frame_size (new->emacs_frame.frame, char_width, char_height, + 1, 0, 0, 0); needs_a_refresh = True; } @@ -808,14 +822,14 @@ EmacsFrameQueryGeometry (Widget widget, XtWidgetGeometry *request, XtWidgetGeome return result->request_mode ? XtGeometryAlmost : XtGeometryYes; } -/* Special entrypoints */ +/* Special entry points */ void EmacsFrameSetCharSize (Widget widget, int columns, int rows) { EmacsFrame ew = (EmacsFrame) widget; struct frame *f = ew->emacs_frame.frame; - x_set_window_size (f, 0, columns, rows); + x_set_window_size (f, 0, columns, rows, 0); } @@ -823,7 +837,7 @@ void widget_store_internal_border (Widget widget) { EmacsFrame ew = (EmacsFrame) widget; - FRAME_PTR f = ew->emacs_frame.frame; + struct frame *f = ew->emacs_frame.frame; ew->emacs_frame.internal_border_width = f->internal_border_width; }