X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=unix%2Fgtkwin.c;h=eca119eb76799476530cd471b8b105f380e49050;hb=095072fa46b2d7b8beafaddb2f873d2f500a1e10;hp=fb45324d10c04e24382743d07b804c0d0b8f7a71;hpb=4ba7ff006a5ef48f2961239d9402bddcd37fd648;p=PuTTY.git diff --git a/unix/gtkwin.c b/unix/gtkwin.c index fb45324d..eca119eb 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -94,11 +94,7 @@ struct gui_data { GtkIMContext *imc; #endif unifont *fonts[4]; /* normal, bold, wide, widebold */ -#if GTK_CHECK_VERSION(2,0,0) - const char *geometry; -#else int xpos, ypos, gotpos, gravity; -#endif GdkCursor *rawcursor, *textcursor, *blankcursor, *waitcursor, *currcursor; GdkColor cols[NALLCOLOURS]; #if !GTK_CHECK_VERSION(3,0,0) @@ -341,6 +337,8 @@ void move_window(void *frontend, int x, int y) * though. */ #if GTK_CHECK_VERSION(2,0,0) + /* in case we reset this at startup due to a geometry string */ + gtk_window_set_gravity(GTK_WINDOW(inst->window), GDK_GRAVITY_NORTH_EAST); gtk_window_move(GTK_WINDOW(inst->window), x, y); #else gdk_window_move(gtk_widget_get_window(inst->window), x, y); @@ -640,6 +638,8 @@ char *dup_keyval_name(guint keyval) } #endif +static void change_font_size(struct gui_data *inst, int increment); + gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) { struct gui_data *inst = (struct gui_data *)data; @@ -840,6 +840,23 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) } } + if (event->keyval == GDK_KEY_greater && + (event->state & GDK_CONTROL_MASK)) { +#ifdef KEY_EVENT_DIAGNOSTICS + debug((" - Ctrl->: increase font size\n")); +#endif + change_font_size(inst, +1); + return TRUE; + } + if (event->keyval == GDK_KEY_less && + (event->state & GDK_CONTROL_MASK)) { +#ifdef KEY_EVENT_DIAGNOSTICS + debug((" - Ctrl-<: increase font size\n")); +#endif + change_font_size(inst, -1); + return TRUE; + } + /* * Shift-PgUp and Shift-PgDn don't even generate keystrokes * at all. @@ -3609,6 +3626,18 @@ char *setup_fonts_ucs(struct gui_data *inst) return NULL; } +#if GTK_CHECK_VERSION(3,0,0) +struct find_app_menu_bar_ctx { + GtkWidget *area, *menubar; +}; +static void find_app_menu_bar(GtkWidget *widget, gpointer data) +{ + struct find_app_menu_bar_ctx *ctx = (struct find_app_menu_bar_ctx *)data; + if (widget != ctx->area && GTK_IS_MENU_BAR(widget)) + ctx->menubar = widget; +} +#endif + static void compute_geom_hints(struct gui_data *inst, GdkGeometry *geom) { /* @@ -3619,7 +3648,7 @@ static void compute_geom_hints(struct gui_data *inst, GdkGeometry *geom) /* * Set up the geometry fields we care about, with reference to - * just the drawing area. We'll correct for the scrollbar in a + * just the drawing area. We'll correct for other widgets in a * moment. */ geom->min_width = inst->font_width + 2*inst->window_border; @@ -3664,15 +3693,63 @@ static void compute_geom_hints(struct gui_data *inst, GdkGeometry *geom) if (geom->min_height < min_sb_height) geom->min_height = min_sb_height; } + +#if GTK_CHECK_VERSION(3,0,0) + /* + * And if we're running a gtkapp.c based program and + * GtkApplicationWindow has given us a menu bar inside the window, + * then we must take that into account as well. + * + * In its unbounded wisdom, GtkApplicationWindow doesn't actually + * give us a direct function call to _find_ the menu bar widget. + * Fortunately, we can find it by enumerating the children of the + * top-level window and looking for one we didn't put there + * ourselves. + */ + { + struct find_app_menu_bar_ctx actx, *ctx = &actx; + ctx->area = inst->area; + ctx->menubar = NULL; + gtk_container_foreach(GTK_CONTAINER(inst->window), + find_app_menu_bar, ctx); + + if (ctx->menubar) { + GtkRequisition req; + int min_menu_width; + gtk_widget_get_preferred_size(ctx->menubar, NULL, &req); + + /* + * This time, the height adjustment is easy (the menu bar + * sits above everything), but we have to take care with + * the _width_ to ensure we keep min_width and base_width + * congruent modulo width_inc. + */ + geom->min_height += req.height; + geom->base_height += req.height; + + min_menu_width = req.width; + min_menu_width += geom->width_inc - 1; + min_menu_width -= + ((min_menu_width - geom->base_width%geom->width_inc) + % geom->width_inc); + if (geom->min_width < min_menu_width) + geom->min_width = min_menu_width; + } + } +#endif } void set_geom_hints(struct gui_data *inst) { GdkGeometry geom; + gint flags = GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC; compute_geom_hints(inst, &geom); - gtk_window_set_geometry_hints - (GTK_WINDOW(inst->window), NULL, &geom, - GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC); +#if GTK_CHECK_VERSION(2,0,0) + if (inst->gotpos) + flags |= GDK_HINT_USER_POS; +#endif + gtk_window_set_geometry_hints(GTK_WINDOW(inst->window), + NULL, &geom, flags); } #if GTK_CHECK_VERSION(2,0,0) @@ -3914,6 +3991,67 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data) inst->reconfiguring = FALSE; } +static void change_font_size(struct gui_data *inst, int increment) +{ + static const int conf_keys[lenof(inst->fonts)] = { + CONF_font, CONF_boldfont, CONF_widefont, CONF_wideboldfont, + }; + FontSpec *oldfonts[lenof(inst->fonts)]; + FontSpec *newfonts[lenof(inst->fonts)]; + char *errmsg = NULL; + int i; + + for (i = 0; i < lenof(newfonts); i++) + oldfonts[i] = newfonts[i] = NULL; + + for (i = 0; i < lenof(inst->fonts); i++) { + if (inst->fonts[i]) { + char *newname = unifont_size_increment(inst->fonts[i], increment); + if (!newname) + goto cleanup; + newfonts[i] = fontspec_new(newname); + sfree(newname); + } + } + + for (i = 0; i < lenof(newfonts); i++) { + if (newfonts[i]) { + oldfonts[i] = fontspec_copy( + conf_get_fontspec(inst->conf, conf_keys[i])); + conf_set_fontspec(inst->conf, conf_keys[i], newfonts[i]); + } + } + + errmsg = setup_fonts_ucs(inst); + if (errmsg) + goto cleanup; + + /* Success, so suppress putting everything back */ + for (i = 0; i < lenof(newfonts); i++) { + if (oldfonts[i]) { + fontspec_free(oldfonts[i]); + oldfonts[i] = NULL; + } + } + + set_geom_hints(inst); + request_resize(inst, conf_get_int(inst->conf, CONF_width), + conf_get_int(inst->conf, CONF_height)); + term_invalidate(inst->term); + gtk_widget_queue_draw(inst->area); + + cleanup: + for (i = 0; i < lenof(oldfonts); i++) { + if (oldfonts[i]) { + conf_set_fontspec(inst->conf, conf_keys[i], oldfonts[i]); + fontspec_free(oldfonts[i]); + } + if (newfonts[i]) + fontspec_free(newfonts[i]); + } + sfree(errmsg); +} + void dup_session_menuitem(GtkMenuItem *item, gpointer gdata) { struct gui_data *inst = (struct gui_data *)gdata; @@ -4153,11 +4291,8 @@ struct gui_data *new_session_window(Conf *conf, const char *geometry_string) inst->cumulative_scroll = 0.0; #endif +#ifndef NOT_X_WINDOWS if (geometry_string) { -#if GTK_CHECK_VERSION(2,0,0) - inst->geometry = geometry_string; -#else - /* On GTK 1, we have to do this using raw Xlib */ int flags, x, y; unsigned int w, h; flags = XParseGeometry(geometry_string, &x, &y, &w, &h); @@ -4173,8 +4308,8 @@ struct gui_data *new_session_window(Conf *conf, const char *geometry_string) inst->gravity = ((flags & XNegative ? 1 : 0) | (flags & YNegative ? 2 : 0)); } -#endif } +#endif if (!compound_text_atom) compound_text_atom = gdk_atom_intern("COMPOUND_TEXT", FALSE); @@ -4233,6 +4368,13 @@ struct gui_data *new_session_window(Conf *conf, const char *geometry_string) show_scrollbar(inst, conf_get_int(inst->conf, CONF_scrollbar)); gtk_widget_show(GTK_WIDGET(inst->hbox)); + /* + * We must call gtk_widget_realize before setting up the geometry + * hints, so that GtkApplicationWindow will have actually created + * its menu bar (if it's going to) and hence compute_geom_hints + * can find it to take its size into account. + */ + gtk_widget_realize(inst->window); set_geom_hints(inst); #if GTK_CHECK_VERSION(3,0,0) @@ -4254,8 +4396,21 @@ struct gui_data *new_session_window(Conf *conf, const char *geometry_string) #endif #if GTK_CHECK_VERSION(2,0,0) - if (inst->geometry) { - gtk_window_parse_geometry(GTK_WINDOW(inst->window), inst->geometry); + if (inst->gotpos) { + static const GdkGravity gravities[] = { + GDK_GRAVITY_NORTH_WEST, + GDK_GRAVITY_NORTH_EAST, + GDK_GRAVITY_SOUTH_WEST, + GDK_GRAVITY_SOUTH_EAST, + }; + int x = inst->xpos, y = inst->ypos; + int wp, hp; + compute_whole_window_size(inst, inst->width, inst->height, &wp, &hp); + if (inst->gravity & 1) x += (gdk_screen_width() - wp); + if (inst->gravity & 2) y += (gdk_screen_height() - hp); + gtk_window_set_gravity(GTK_WINDOW(inst->window), + gravities[inst->gravity & 3]); + gtk_window_move(GTK_WINDOW(inst->window), x, y); } #else if (inst->gotpos) {