/* * Return value is Qt if we have dispatched the command, * or Qnil if id has not been mapped to a callback. * Window procedure may try other targets to route the * command if we return nil */ Lisp_Object mswindows_handle_gui_wm_command (struct frame* f, HWND ctrl, LPARAM id) { /* Try to map the command id through the proper hash table */ Lisp_Object callback, callback_ex, image_instance, frame, event; XSETFRAME (frame, f); /* #### make_int should assert that --kkm */ assert (XINT (make_int (id)) == id); image_instance = Fgethash (make_int (id), FRAME_MSWINDOWS_WIDGET_HASH_TABLE1 (f), Qnil); /* It is possible for a widget action to cause it to get out of sync with its instantiator. Thus it is necessary to signal this possibility. */ if (IMAGE_INSTANCEP (image_instance)) XIMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (image_instance) = 1; callback = Fgethash (make_int (id), FRAME_MSWINDOWS_WIDGET_HASH_TABLE2 (f), Qnil); callback_ex = Fgethash (make_int (id), FRAME_MSWINDOWS_WIDGET_HASH_TABLE3 (f), Qnil); if (!NILP (callback_ex) && !UNBOUNDP (callback_ex)) { event = Fmake_event (Qnil, Qnil); XEVENT (event)->event_type = misc_user_event; XEVENT (event)->channel = frame; XEVENT (event)->timestamp = GetTickCount (); XEVENT (event)->event.eval.function = Qeval; XEVENT (event)->event.eval.object = list4 (Qfuncall, callback_ex, image_instance, event); } else if (NILP (callback) || UNBOUNDP (callback)) return Qnil; else { Lisp_Object fn, arg; event = Fmake_event (Qnil, Qnil); get_gui_callback (callback, &fn, &arg); XEVENT (event)->event_type = misc_user_event; XEVENT (event)->channel = frame; XEVENT (event)->timestamp = GetTickCount (); XEVENT (event)->event.eval.function = fn; XEVENT (event)->event.eval.object = arg; } mswindows_enqueue_dispatch_event (event); /* The result of this evaluation could cause other instances to change so enqueue an update callback to check this. */ enqueue_magic_eval_event (update_widget_instances, frame); return Qt; }
void popup_selection_callback(Widget widget, LWLIB_ID ignored_id, XtPointer client_data) { Lisp_Object data, image_instance, callback, callback_ex; Lisp_Object frame, event; int update_subwindows_p = 0; struct device *d = get_device_from_display(XtDisplay(widget)); struct frame *f = x_any_widget_or_parent_to_frame(d, widget); /* set in lwlib to the time stamp associated with the most recent menu operation */ extern Time x_focus_timestamp_really_sucks_fix_me_better; if (!f) return; if (((EMACS_INT) client_data) == 0) return; VOID_TO_LISP(data, client_data); XSETFRAME(frame, f); #if 0 /* #### What the hell? I can't understand why this call is here, and doing it is really courting disaster in the new event model, since popup_selection_callback is called from within next_event_internal() and Faccept_process_output() itself calls next_event_internal(). --Ben */ /* Flush the X and process input */ Faccept_process_output(Qnil, Qnil, Qnil); #endif if (((EMACS_INT) client_data) == -1) { event = Fmake_event(Qnil, Qnil); XEVENT(event)->event_type = misc_user_event; XEVENT(event)->channel = frame; XEVENT(event)->event.eval.function = Qrun_hooks; XEVENT(event)->event.eval.object = Qmenu_no_selection_hook; } else { image_instance = XCAR(data); callback = XCAR(XCDR(data)); callback_ex = XCDR(XCDR(data)); update_subwindows_p = 1; /* It is possible for a widget action to cause it to get out of sync with its instantiator. Thus it is necessary to signal this possibility. */ if (IMAGE_INSTANCEP(image_instance)) XIMAGE_INSTANCE_WIDGET_ACTION_OCCURRED(image_instance) = 1; if (!NILP(callback_ex) && !UNBOUNDP(callback_ex)) { event = Fmake_event(Qnil, Qnil); XEVENT(event)->event_type = misc_user_event; XEVENT(event)->channel = frame; XEVENT(event)->event.eval.function = Qeval; XEVENT(event)->event.eval.object = list4(Qfuncall, callback_ex, image_instance, event); } else if (NILP(callback) || UNBOUNDP(callback)) event = Qnil; else { Lisp_Object fn, arg; event = Fmake_event(Qnil, Qnil); get_gui_callback(callback, &fn, &arg); XEVENT(event)->event_type = misc_user_event; XEVENT(event)->channel = frame; XEVENT(event)->event.eval.function = fn; XEVENT(event)->event.eval.object = arg; } } /* This is the timestamp used for asserting focus so we need to get an up-to-date value event if no events have been dispatched to emacs */ #if defined(HAVE_MENUBARS) DEVICE_X_MOUSE_TIMESTAMP(d) = x_focus_timestamp_really_sucks_fix_me_better; #else DEVICE_X_MOUSE_TIMESTAMP(d) = DEVICE_X_GLOBAL_MOUSE_TIMESTAMP(d); #endif if (!NILP(event)) enqueue_Xt_dispatch_event(event); /* The result of this evaluation could cause other instances to change so enqueue an update callback to check this. */ if (update_subwindows_p && !NILP(event)) enqueue_magic_eval_event(update_widget_instances, frame); }
static void gtk_output_toolbar_button (struct frame *f, Lisp_Object button) { int shadow_thickness = 2; int x_adj, y_adj, width_adj, height_adj; GdkWindow *x_win = FRAME_GTK_TEXT_WIDGET (f)->window; GdkGC *background_gc = get_toolbar_gc (f); Lisp_Object instance, frame, window, glyph; struct toolbar_button *tb = XTOOLBAR_BUTTON (button); struct Lisp_Image_Instance *p; struct window *w; int vertical = tb->vertical; int border_width = tb->border_width; if (vertical) { x_adj = border_width; width_adj = - 2 * border_width; y_adj = 0; height_adj = 0; } else { x_adj = 0; width_adj = 0; y_adj = border_width; height_adj = - 2 * border_width; } XSETFRAME (frame, f); window = FRAME_LAST_NONMINIBUF_WINDOW (f); w = XWINDOW (window); glyph = get_toolbar_button_glyph (w, tb); if (tb->enabled) { if (tb->down) { shadow_thickness = -2; } else { shadow_thickness = 2; } } else { shadow_thickness = 0; } background_gc = get_toolbar_gc (f); /* Clear the entire area. */ gdk_draw_rectangle (x_win, background_gc, TRUE, tb->x + x_adj, tb->y + y_adj, tb->width + width_adj, tb->height + height_adj); /* Draw the outline. */ if (shadow_thickness) gtk_output_shadows (f, tb->x + x_adj, tb->y + y_adj, tb->width + width_adj, tb->height + height_adj, shadow_thickness); /* Do the border. */ gdk_draw_rectangle (x_win, background_gc, TRUE, tb->x, tb->y, (vertical ? border_width : tb->width), (vertical ? tb->height : border_width)); gdk_draw_rectangle (x_win, background_gc, TRUE, (vertical ? tb->x + tb->width - border_width : tb->x), (vertical ? tb->y : tb->y + tb->height - border_width), (vertical ? border_width : tb->width), (vertical ? tb->height : border_width)); background_gc = get_toolbar_gc (f); /* #### It is currently possible for users to trash us by directly changing the toolbar glyphs. Avoid crashing in that case. */ if (GLYPHP (glyph)) instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); else instance = Qnil; if (IMAGE_INSTANCEP (instance)) { int width = tb->width + width_adj - shadow_thickness * 2; int height = tb->height + height_adj - shadow_thickness * 2; int x_offset = x_adj + shadow_thickness; int y_offset = y_adj + shadow_thickness; p = XIMAGE_INSTANCE (instance); if (IMAGE_INSTANCE_PIXMAP_TYPE_P (p)) { if (width > (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p)) { x_offset += ((int) (width - IMAGE_INSTANCE_PIXMAP_WIDTH (p)) / 2); width = IMAGE_INSTANCE_PIXMAP_WIDTH (p); } if (height > (int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p)) { y_offset += ((int) (height - IMAGE_INSTANCE_PIXMAP_HEIGHT (p)) / 2); height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p); } gtk_output_gdk_pixmap (f, XIMAGE_INSTANCE (instance), tb->x + x_offset, tb->y + y_offset, 0, 0, 0, 0, width, height, 0, 0, 0, background_gc); } else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_TEXT) { /* #### We need to make the face used configurable. */ struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, DEFAULT_INDEX); struct display_line dl; Lisp_Object string = IMAGE_INSTANCE_TEXT_STRING (p); unsigned char charsets[NUM_LEADING_BYTES]; Emchar_dynarr *buf; struct font_metric_info fm; /* This could be true if we were called via the Expose event handler. Mark the button as dirty and return immediately. */ if (f->window_face_cache_reset) { tb->dirty = 1; MARK_TOOLBAR_CHANGED; return; } buf = Dynarr_new (Emchar); convert_bufbyte_string_into_emchar_dynarr (XSTRING_DATA (string), XSTRING_LENGTH (string), buf); find_charsets_in_emchar_string (charsets, Dynarr_atp (buf, 0), Dynarr_length (buf)); ensure_face_cachel_complete (cachel, window, charsets); face_cachel_charset_font_metric_info (cachel, charsets, &fm); dl.ascent = fm.ascent; dl.descent = fm.descent; dl.ypos = tb->y + y_offset + fm.ascent; if (fm.ascent + fm.descent <= height) { dl.ypos += (height - fm.ascent - fm.descent) / 2; dl.clip = 0; } else { dl.clip = fm.ascent + fm.descent - height; } gtk_output_string (w, &dl, buf, tb->x + x_offset, 0, 0, width, DEFAULT_INDEX, 0, 0, 0, 0); Dynarr_free (buf); } /* We silently ignore the image if it isn't a pixmap or text. */ } tb->dirty = 0; }