Make sure grab-notify is emitted on toplevels as well as child widgets.

2006-05-22  Alexander Larsson  <alexl@redhat.com>

	* gtk/gtkmain.c:
	Make sure grab-notify is emitted on toplevels as well as
	child widgets.

	* gtk/Makefile.am:
	* gtk/gtkwin32embedwidget.[ch]
	Add new widget used for win32 port to embed gtk+
	widgets in windows dialog.

	* gtk/gtkmarshalers.list:
	Add POINTER:VOID

	* gtk/gtkprintoperation-private.h:
	* gtk/gtkprintoperation.[ch]:
	Generic support for custom widgets in print dialog.

	* gtk/gtkprintoperation-win32.c:
	Implement custom widget support for win32.

	* tests/print-editor.c:
	Allow setting of font using custom widgets in the print dialog.
This commit is contained in:
Alexander Larsson 2006-05-22 17:19:10 +00:00 committed by Alexander Larsson
parent fb3eeb8686
commit d2cb6c6eb2
12 changed files with 800 additions and 22 deletions

View File

@ -1,3 +1,27 @@
2006-05-22 Alexander Larsson <alexl@redhat.com>
* gtk/gtkmain.c:
Make sure grab-notify is emitted on toplevels as well as
child widgets.
* gtk/Makefile.am:
* gtk/gtkwin32embedwidget.[ch]
Add new widget used for win32 port to embed gtk+
widgets in windows dialog.
* gtk/gtkmarshalers.list:
Add POINTER:VOID
* gtk/gtkprintoperation-private.h:
* gtk/gtkprintoperation.[ch]:
Generic support for custom widgets in print dialog.
* gtk/gtkprintoperation-win32.c:
Implement custom widget support for win32.
* tests/print-editor.c:
Allow setting of font using custom widgets in the print dialog.
2006-05-22 Behdad Esfahbod <behdad@gnome.org>
Rollback the following changes, to fix it the proper way in Pango:

View File

@ -1,3 +1,27 @@
2006-05-22 Alexander Larsson <alexl@redhat.com>
* gtk/gtkmain.c:
Make sure grab-notify is emitted on toplevels as well as
child widgets.
* gtk/Makefile.am:
* gtk/gtkwin32embedwidget.[ch]
Add new widget used for win32 port to embed gtk+
widgets in windows dialog.
* gtk/gtkmarshalers.list:
Add POINTER:VOID
* gtk/gtkprintoperation-private.h:
* gtk/gtkprintoperation.[ch]:
Generic support for custom widgets in print dialog.
* gtk/gtkprintoperation-win32.c:
Implement custom widget support for win32.
* tests/print-editor.c:
Allow setting of font using custom widgets in the print dialog.
2006-05-22 Behdad Esfahbod <behdad@gnome.org>
Rollback the following changes, to fix it the proper way in Pango:

View File

@ -623,8 +623,8 @@ gtk_c_sources += \
gtktrayicon-x11.c
else
if USE_WIN32
gtk_private_h_sources += gtkwin32embed.h
gtk_c_sources += gtkplug-win32.c gtksocket-win32.c gtkwin32embed.c
gtk_private_h_sources += gtkwin32embed.h gtkwin32embedwidget.h
gtk_c_sources += gtkplug-win32.c gtksocket-win32.c gtkwin32embed.c gtkwin32embedwidget.c
else
gtk_c_sources += gtkplug-stub.c gtksocket-stub.c
endif
@ -778,7 +778,7 @@ libgtk_directfb_2_0_la_LDFLAGS = $(libtool_opts)
libgtk_x11_2_0_la_LIBADD = $(libadd)
libgtk_linux_fb_2_0_la_LIBADD = $(libadd)
libgtk_win32_2_0_la_LIBADD = $(libadd) -lole32 -lgdi32 -lcomdlg32 -lwinspool
libgtk_win32_2_0_la_LIBADD = $(libadd) -lole32 -lgdi32 -lcomdlg32 -lwinspool -lcomctl32
libgtk_win32_2_0_la_DEPENDENCIES = $(gtk_def) $(gtk_win32_res)
libgtk_quartz_2_0_la_LIBADD = $(libadd)
libgtk_directfb_2_0_la_LIBADD = $(libadd)

View File

@ -1560,8 +1560,7 @@ gtk_grab_notify (GtkWindowGroup *group,
info.is_grabbed = FALSE;
if (group == gtk_window_get_group (toplevel))
gtk_container_foreach (GTK_CONTAINER (toplevel),
gtk_grab_notify_foreach, &info);
gtk_grab_notify_foreach (GTK_WIDGET (toplevel), &info);
g_object_unref (toplevel);
}

View File

@ -52,6 +52,7 @@ NONE:INT,BOOL
NONE:INT,INT
NONE:NONE
NONE:STRING,INT,POINTER
POINTER:VOID
STRING:DOUBLE
VOID:DOUBLE
VOID:BOOLEAN

View File

@ -57,7 +57,8 @@ struct _GtkPrintOperationPrivate
guint manual_orientation : 1;
double manual_scale;
GtkPageSet manual_page_set;
GtkWidget *custom_widget;
gpointer platform_data;
GDestroyNotify free_platform_data;

View File

@ -33,7 +33,11 @@
#include "gtkprint-win32.h"
#include "gtkintl.h"
#include "gtkinvisible.h"
#include "gtkplug.h"
#include "gtkstock.h"
#include "gtkalias.h"
#include "gtk.h"
#include "gtkwin32embedwidget.h"
#define MAX_PAGE_RANGES 20
#define STATUS_POLLING_TIME 2000
@ -53,6 +57,8 @@ typedef struct {
HANDLE printerHandle;
int job_id;
guint timeout_id;
GtkWidget *embed_widget;
} GtkPrintOperationWin32;
static void win32_poll_status (GtkPrintOperation *op);
@ -593,7 +599,6 @@ get_parent_hwnd (GtkWidget *widget)
return gdk_win32_drawable_get_handle (widget->window);
}
static void
devnames_to_settings (GtkPrintSettings *settings,
HANDLE hDevNames)
@ -1267,6 +1272,126 @@ print_callback_new (void)
return &callback->iPrintDialogCallback;
}
static void
plug_grab_notify (GtkWidget *widget,
gboolean was_grabbed,
GtkPrintOperation *op)
{
EnableWindow(GetAncestor (GDK_WINDOW_HWND (widget->window), GA_ROOT),
was_grabbed);
}
static BOOL CALLBACK
pageDlgProc (HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
{
GtkPrintOperation *op;
GtkPrintOperationWin32 *op_win32;
if (message == WM_INITDIALOG)
{
PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lparam;
GtkWidget *plug;
op = GTK_PRINT_OPERATION ((gpointer)page->lParam);
op_win32 = op->priv->platform_data;
SetWindowLongPtrW(wnd, GWLP_USERDATA, (LONG_PTR)op);
plug = _gtk_win32_embed_widget_new ((GdkNativeWindow) wnd);
op_win32->embed_widget = plug;
gtk_container_add (GTK_CONTAINER (plug), op->priv->custom_widget);
gtk_widget_show (op->priv->custom_widget);
gtk_widget_show (plug);
gdk_window_focus (plug->window, GDK_CURRENT_TIME);
/* This dialog is modal, so we grab the embed widget */
gtk_grab_add (plug);
/* When we lose the grab we need to disable the print dialog */
g_signal_connect (plug, "grab-notify", G_CALLBACK (plug_grab_notify), op);
return FALSE;
}
else if (message == WM_DESTROY)
{
op = GTK_PRINT_OPERATION (GetWindowLongPtrW(wnd, GWLP_USERDATA));
op_win32 = op->priv->platform_data;
g_signal_emit_by_name (op, "custom-widget-apply", op->priv->custom_widget);
gtk_widget_destroy (op_win32->embed_widget);
op_win32->embed_widget = NULL;
op->priv->custom_widget = NULL;
}
else
{
op = GTK_PRINT_OPERATION (GetWindowLongPtrW(wnd, GWLP_USERDATA));
op_win32 = op->priv->platform_data;
return _gtk_win32_embed_widget_dialog_procedure (GTK_WIN32_EMBED_WIDGET (op_win32->embed_widget),
wnd, message, wparam, lparam);
}
return FALSE;
}
static HPROPSHEETPAGE
create_application_page (GtkPrintOperation *op)
{
HPROPSHEETPAGE hpage;
PROPSHEETPAGEW page;
DLGTEMPLATE *template;
HGLOBAL htemplate;
LONG base_units;
WORD baseunitX, baseunitY;
WORD *array;
GtkRequisition requisition;
const char *app_name;
/* Make the template the size of the custom widget size request */
gtk_widget_size_request (op->priv->custom_widget, &requisition);
base_units = GetDialogBaseUnits();
baseunitX = LOWORD(base_units);
baseunitY = HIWORD(base_units);
htemplate = GlobalAlloc (GMEM_MOVEABLE,
sizeof (DLGTEMPLATE) + sizeof(WORD) * 3);
template = GlobalLock (htemplate);
template->style = WS_CHILDWINDOW | DS_CONTROL;
template->dwExtendedStyle = WS_EX_CONTROLPARENT;
template->cdit = 0;
template->x = MulDiv(0, 4, baseunitX);
template->y = MulDiv(0, 8, baseunitY);
template->cx = MulDiv(requisition.width, 4, baseunitX);
template->cy = MulDiv(requisition.height, 8, baseunitY);
array = (WORD *) (template+1);
*array++ = 0; /* menu */
*array++ = 0; /* class */
*array++ = 0; /* title */
memset(&page, 0, sizeof (page));
page.dwSize = sizeof (page);
page.dwFlags = PSP_DLGINDIRECT | PSP_USETITLE | PSP_PREMATURE;
page.hInstance = GetModuleHandle (NULL);
page.pResource = template;
app_name = g_get_application_name ();
if (app_name == NULL)
app_name = "Application";
page.pszTitle = g_utf8_to_utf16 (app_name,
-1, NULL, NULL, NULL);
page.pfnDlgProc = pageDlgProc;
page.pfnCallback = NULL;
page.lParam = (LPARAM) op;
hpage = CreatePropertySheetPageW(&page);
GlobalUnlock (htemplate);
/* TODO: We're leaking htemplate here... */
return hpage;
}
GtkPrintOperationResult
_gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
GtkWindow *parent,
@ -1281,9 +1406,14 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
GtkPrintOperationResult result;
GtkPrintOperationWin32 *op_win32;
IPrintDialogCallback *callback;
HPROPSHEETPAGE prop_page;
*do_print = FALSE;
op_win32 = g_new0 (GtkPrintOperationWin32, 1);
op->priv->platform_data = op_win32;
op->priv->free_platform_data = (GDestroyNotify) op_win32_free;
if (parent == NULL)
{
invisible = gtk_invisible_new ();
@ -1338,8 +1468,18 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
printdlgex->hInstance = 0;
printdlgex->lpPrintTemplateName = NULL;
printdlgex->lpCallback = NULL;
printdlgex->nPropertyPages = 0;
printdlgex->lphPropertyPages = NULL;
g_signal_emit_by_name (op, "create-custom-widget",
&op->priv->custom_widget);
if (op->priv->custom_widget) {
prop_page = create_application_page (op);
printdlgex->nPropertyPages = 1;
printdlgex->lphPropertyPages = &prop_page;
} else {
printdlgex->nPropertyPages = 0;
printdlgex->lphPropertyPages = NULL;
}
printdlgex->nStartPage = START_PAGE_GENERAL;
printdlgex->dwResultAction = 0;
@ -1348,7 +1488,7 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
callback = print_callback_new ();
printdlgex->lpCallback = (IUnknown *)callback;
got_gdk_events_message = RegisterWindowMessage ("GDK_WIN32_GOT_EVENTS");
hResult = PrintDlgExW(printdlgex);
IUnknown_Release ((IUnknown *)callback);
gdk_win32_set_modal_dialog_libgtk_only (NULL);
@ -1426,9 +1566,6 @@ _gtk_print_operation_platform_backend_run_dialog (GtkPrintOperation *op,
goto out;
}
op_win32 = g_new (GtkPrintOperationWin32, 1);
op->priv->platform_data = op_win32;
op->priv->free_platform_data = (GDestroyNotify) op_win32_free;
op_win32->hdc = printdlgex->hDC;
op_win32->devmode = printdlgex->hDevMode;
op_win32->devnames = printdlgex->hDevNames;

View File

@ -36,6 +36,8 @@ enum {
DRAW_PAGE,
END_PRINT,
STATUS_CHANGED,
CREATE_CUSTOM_WIDGET,
CUSTOM_WIDGET_APPLY,
LAST_SIGNAL
};
@ -230,6 +232,29 @@ gtk_print_operation_get_property (GObject *object,
}
}
static GtkWidget *
gtk_print_operation_create_custom_widget (GtkPrintOperation *operation)
{
return NULL;
}
static gboolean
custom_widget_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer dummy)
{
gboolean continue_emission;
GtkWidget *widget;
widget = g_value_get_pointer (handler_return);
if (widget != NULL)
g_value_set_pointer (return_accu, widget);
continue_emission = (widget == NULL);
return continue_emission;
}
static void
gtk_print_operation_class_init (GtkPrintOperationClass *class)
{
@ -238,6 +263,8 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class)
gobject_class->set_property = gtk_print_operation_set_property;
gobject_class->get_property = gtk_print_operation_get_property;
gobject_class->finalize = gtk_print_operation_finalize;
class->create_custom_widget = gtk_print_operation_create_custom_widget;
g_type_class_add_private (gobject_class, sizeof (GtkPrintOperationPrivate));
@ -384,12 +411,60 @@ gtk_print_operation_class_init (GtkPrintOperationClass *class)
*/
signals[STATUS_CHANGED] =
g_signal_new (I_("status-changed"),
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkPrintOperationClass, status_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkPrintOperationClass, status_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* GtkPrintOperation::get-custom-widget:
* @operation: the #GtkPrintOperation on which the signal was emitted
*
* Gets emitted when displaying the print dialog. If you return a
* widget in a handler for this signal it will be added to a custom
* tab in the print dialog. You typically return a container widget
* with multiple widgets in it.
*
* The print dialog owns the returned widget, and its lifetime
* isn't controlled by the app. However, the widget is guaranteed
* to stay around until the custom-widget-apply signal is emitted
* on the operation. Then you can read out any information you need
* from the widgets.
*
* Since: 2.10
*/
signals[CREATE_CUSTOM_WIDGET] =
g_signal_new (I_("create-custom-widget"),
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkPrintOperationClass, create_custom_widget),
custom_widget_accumulator, NULL,
_gtk_marshal_POINTER__VOID,
G_TYPE_POINTER, 0);
/**
* GtkPrintOperation::custom-widget-apply:
* @operation: the #GtkPrintOperation on which the signal was emitted
* @widget: the custom widget added in create-custom-widget
*
* This signal gets emitted right before begin-print if you added
* a custom widget in the create-custom-widget handler. When you get
* this signal you should read the information from the custom widgets,
* as the widgets are not guaraneed to be around at a later time.
*
* Since: 2.10
*/
signals[CUSTOM_WIDGET_APPLY] =
g_signal_new (I_("custom-widget-apply"),
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkPrintOperationClass, custom_widget_apply),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
/**
* GtkPrintOperation:default-page-setup:

View File

@ -80,6 +80,10 @@ struct _GtkPrintOperationClass
void (*end_print) (GtkPrintOperation *operation,
GtkPrintContext *context);
void (*status_changed) (GtkPrintOperation *operation);
GtkWidget *(*create_custom_widget) (GtkPrintOperation *operation);
void (*custom_widget_apply) (GtkPrintOperation *operation,
GtkWidget *widget);
/* Padding for future expansion */
void (*_gtk_reserved1) (void);

394
gtk/gtkwin32embedwidget.c Normal file
View File

@ -0,0 +1,394 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-2006. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include <config.h>
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkwin32embedwidget.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkalias.h"
static void gtk_win32_embed_widget_realize (GtkWidget *widget);
static void gtk_win32_embed_widget_unrealize (GtkWidget *widget);
static void gtk_win32_embed_widget_show (GtkWidget *widget);
static void gtk_win32_embed_widget_hide (GtkWidget *widget);
static void gtk_win32_embed_widget_map (GtkWidget *widget);
static void gtk_win32_embed_widget_unmap (GtkWidget *widget);
static void gtk_win32_embed_widget_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_win32_embed_widget_set_focus (GtkWindow *window,
GtkWidget *focus);
static gboolean gtk_win32_embed_widget_focus (GtkWidget *widget,
GtkDirectionType direction);
static void gtk_win32_embed_widget_check_resize (GtkContainer *container);
static GtkBinClass *bin_class = NULL;
G_DEFINE_TYPE (GtkWin32EmbedWidget, gtk_win32_embed_widget, GTK_TYPE_WINDOW)
static void
gtk_win32_embed_widget_class_init (GtkWin32EmbedWidgetClass *class)
{
GtkWidgetClass *widget_class = (GtkWidgetClass *)class;
GtkWindowClass *window_class = (GtkWindowClass *)class;
GtkContainerClass *container_class = (GtkContainerClass *)class;
bin_class = g_type_class_peek (GTK_TYPE_BIN);
widget_class->realize = gtk_win32_embed_widget_realize;
widget_class->unrealize = gtk_win32_embed_widget_unrealize;
widget_class->show = gtk_win32_embed_widget_show;
widget_class->hide = gtk_win32_embed_widget_hide;
widget_class->map = gtk_win32_embed_widget_map;
widget_class->unmap = gtk_win32_embed_widget_unmap;
widget_class->size_allocate = gtk_win32_embed_widget_size_allocate;
widget_class->focus = gtk_win32_embed_widget_focus;
container_class->check_resize = gtk_win32_embed_widget_check_resize;
window_class->set_focus = gtk_win32_embed_widget_set_focus;
}
static void
gtk_win32_embed_widget_init (GtkWin32EmbedWidget *embed_widget)
{
GtkWindow *window;
window = GTK_WINDOW (embed_widget);
window->type = GTK_WINDOW_TOPLEVEL;
GTK_WIDGET_SET_FLAGS (embed_widget, GTK_TOPLEVEL);
gtk_container_set_resize_mode (GTK_CONTAINER (embed_widget), GTK_RESIZE_QUEUE);
}
GtkWidget*
_gtk_win32_embed_widget_new (GdkNativeWindow parent_id)
{
GtkWin32EmbedWidget *embed_widget;
embed_widget = g_object_new (GTK_TYPE_WIN32_EMBED_WIDGET, NULL);
embed_widget->parent_window =
gdk_window_lookup_for_display (gdk_display_get_default (),
parent_id);
if (!embed_widget->parent_window)
embed_widget->parent_window =
gdk_window_foreign_new_for_display (gdk_display_get_default (),
parent_id);
return GTK_WIDGET (embed_widget);
}
BOOL
_gtk_win32_embed_widget_dialog_procedure (GtkWin32EmbedWidget *embed_widget,
HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
{
GtkWidget *widget = GTK_WIDGET (embed_widget);
if (message == WM_SIZE)
{
widget->allocation.width = LOWORD(lparam);
widget->allocation.height = HIWORD(lparam);
gtk_widget_queue_resize (widget);
}
return 0;
}
static void
gtk_win32_embed_widget_unrealize (GtkWidget *widget)
{
GtkWin32EmbedWidget *embed_widget;
g_return_if_fail (GTK_IS_WIN32_EMBED_WIDGET (widget));
embed_widget = GTK_WIN32_EMBED_WIDGET (widget);
embed_widget->old_window_procedure = NULL;
if (embed_widget->parent_window != NULL)
{
gdk_window_set_user_data (embed_widget->parent_window, NULL);
g_object_unref (embed_widget->parent_window);
embed_widget->parent_window = NULL;
}
if (GTK_WIDGET_CLASS (gtk_win32_embed_widget_parent_class)->unrealize)
(* GTK_WIDGET_CLASS (gtk_win32_embed_widget_parent_class)->unrealize) (widget);
}
static LRESULT CALLBACK
gtk_win32_embed_widget_window_process (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
GdkWindow *window;
GtkWin32EmbedWidget *embed_widget;
gpointer user_data;
window = gdk_window_lookup ((GdkNativeWindow)hwnd);
if (window == NULL) {
g_warning ("No such window!");
return 0;
}
gdk_window_get_user_data (window, &user_data);
embed_widget = GTK_WIN32_EMBED_WIDGET (user_data);
if (msg == WM_GETDLGCODE) {
return DLGC_WANTALLKEYS;
}
if (embed_widget && embed_widget->old_window_procedure)
return CallWindowProc(embed_widget->old_window_procedure,
hwnd, msg, wparam, lparam);
else
return 0;
}
static void
gtk_win32_embed_widget_realize (GtkWidget *widget)
{
GtkWindow *window;
GtkWin32EmbedWidget *embed_widget;
GdkWindowAttr attributes;
gint attributes_mask;
LONG_PTR styles;
g_return_if_fail (GTK_IS_WIN32_EMBED_WIDGET (widget));
window = GTK_WINDOW (widget);
embed_widget = GTK_WIN32_EMBED_WIDGET (widget);
/* ensure widget tree is properly size allocated */
if (widget->allocation.x == -1 &&
widget->allocation.y == -1 &&
widget->allocation.width == 1 &&
widget->allocation.height == 1)
{
GtkRequisition requisition;
GtkAllocation allocation = { 0, 0, 200, 200 };
gtk_widget_size_request (widget, &requisition);
if (requisition.width || requisition.height)
{
/* non-empty window */
allocation.width = requisition.width;
allocation.height = requisition.height;
}
gtk_widget_size_allocate (widget, &allocation);
_gtk_container_queue_resize (GTK_CONTAINER (widget));
g_return_if_fail (!GTK_WIDGET_REALIZED (widget));
}
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
attributes.window_type = GDK_WINDOW_CHILD;
attributes.title = window->title;
attributes.wmclass_name = window->wmclass_name;
attributes.wmclass_class = window->wmclass_class;
attributes.width = widget->allocation.width;
attributes.height = widget->allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
/* this isn't right - we should match our parent's visual/colormap.
* though that will require handling "foreign" colormaps */
attributes.visual = gtk_widget_get_visual (widget);
attributes.colormap = gtk_widget_get_colormap (widget);
attributes.event_mask = gtk_widget_get_events (widget);
attributes.event_mask |= (GDK_EXPOSURE_MASK |
GDK_KEY_PRESS_MASK |
GDK_KEY_RELEASE_MASK |
GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK |
GDK_STRUCTURE_MASK |
GDK_FOCUS_CHANGE_MASK);
attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
widget->window = gdk_window_new (embed_widget->parent_window,
&attributes, attributes_mask);
gdk_window_set_user_data (widget->window, window);
embed_widget->old_window_procedure = (gpointer)
SetWindowLongPtrW(GDK_WINDOW_HWND (widget->window),
GWLP_WNDPROC,
(LONG_PTR)gtk_win32_embed_widget_window_process);
/* Enable tab to focus the widget */
styles = GetWindowLongPtr(GDK_WINDOW_HWND (widget->window), GWL_STYLE);
SetWindowLongPtrW(GDK_WINDOW_HWND (widget->window), GWL_STYLE, styles | WS_TABSTOP);
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
}
static void
gtk_win32_embed_widget_show (GtkWidget *widget)
{
GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE);
gtk_widget_realize (widget);
gtk_container_check_resize (GTK_CONTAINER (widget));
gtk_widget_map (widget);
}
static void
gtk_win32_embed_widget_hide (GtkWidget *widget)
{
GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE);
gtk_widget_unmap (widget);
}
static void
gtk_win32_embed_widget_map (GtkWidget *widget)
{
GtkBin *bin = GTK_BIN (widget);
GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
if (bin->child &&
GTK_WIDGET_VISIBLE (bin->child) &&
!GTK_WIDGET_MAPPED (bin->child))
gtk_widget_map (bin->child);
gdk_window_show (widget->window);
}
static void
gtk_win32_embed_widget_unmap (GtkWidget *widget)
{
GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
gdk_window_hide (widget->window);
}
static void
gtk_win32_embed_widget_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkBin *bin = GTK_BIN (widget);
widget->allocation = *allocation;
if (GTK_WIDGET_REALIZED (widget))
gdk_window_move_resize (widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height);
if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
{
GtkAllocation child_allocation;
child_allocation.x = child_allocation.y = GTK_CONTAINER (widget)->border_width;
child_allocation.width =
MAX (1, (gint)allocation->width - child_allocation.x * 2);
child_allocation.height =
MAX (1, (gint)allocation->height - child_allocation.y * 2);
gtk_widget_size_allocate (bin->child, &child_allocation);
}
}
static void
gtk_win32_embed_widget_check_resize (GtkContainer *container)
{
GTK_CONTAINER_CLASS (bin_class)->check_resize (container);
}
static gboolean
gtk_win32_embed_widget_focus (GtkWidget *widget,
GtkDirectionType direction)
{
GtkBin *bin = GTK_BIN (widget);
GtkWin32EmbedWidget *embed_widget = GTK_WIN32_EMBED_WIDGET (widget);
GtkWindow *window = GTK_WINDOW (widget);
GtkContainer *container = GTK_CONTAINER (widget);
GtkWidget *old_focus_child = container->focus_child;
GtkWidget *parent;
/* We override GtkWindow's behavior, since we don't want wrapping here.
*/
if (old_focus_child)
{
if (gtk_widget_child_focus (old_focus_child, direction))
return TRUE;
if (window->focus_widget)
{
/* Wrapped off the end, clear the focus setting for the toplevel */
parent = window->focus_widget->parent;
while (parent)
{
gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
parent = GTK_WIDGET (parent)->parent;
}
gtk_window_set_focus (GTK_WINDOW (container), NULL);
}
}
else
{
/* Try to focus the first widget in the window */
if (bin->child && gtk_widget_child_focus (bin->child, direction))
return TRUE;
}
if (!GTK_CONTAINER (window)->focus_child)
{
int backwards = FALSE;
if (direction == GTK_DIR_TAB_BACKWARD ||
direction == GTK_DIR_LEFT)
backwards = TRUE;
PostMessage(GDK_WINDOW_HWND (embed_widget->parent_window),
WM_NEXTDLGCTL,
backwards, 0);
}
return FALSE;
}
static void
gtk_win32_embed_widget_set_focus (GtkWindow *window,
GtkWidget *focus)
{
GTK_WINDOW_CLASS (gtk_win32_embed_widget_parent_class)->set_focus (window, focus);
gdk_window_focus (GTK_WIDGET(window)->window, 0);
}
#define __GTK_WIN32_EMBED_WIDGET_C__
#include "gtkaliasdef.c"

75
gtk/gtkwin32embedwidget.h Normal file
View File

@ -0,0 +1,75 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-2006. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GTK_WIN32_EMBED_WIDGET_H__
#define __GTK_WIN32_EMBED_WIDGET_H__
#include <gdk/gdk.h>
#include <gtk/gtkwindow.h>
#include "win32/gdkwin32.h"
G_BEGIN_DECLS
#define GTK_TYPE_WIN32_EMBED_WIDGET (gtk_win32_embed_widget_get_type ())
#define GTK_WIN32_EMBED_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WIN32_EMBED_WIDGET, GtkWin32EmbedWidget))
#define GTK_WIN32_EMBED_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WIN32_EMBED_WIDGET, GtkWin32EmbedWidgetClass))
#define GTK_IS_WIN32_EMBED_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WIN32_EMBED_WIDGET))
#define GTK_IS_WIN32_EMBED_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WIN32_EMBED_WIDGET))
#define GTK_WIN32_EMBED_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WIN32_EMBED_WIDGET, GtkWin32EmbedWidgetClass))
typedef struct _GtkWin32EmbedWidget GtkWin32EmbedWidget;
typedef struct _GtkWin32EmbedWidgetClass GtkWin32EmbedWidgetClass;
struct _GtkWin32EmbedWidget
{
GtkWindow window;
GdkWindow *parent_window;
gpointer old_window_procedure;
};
struct _GtkWin32EmbedWidgetClass
{
GtkWindowClass parent_class;
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
};
GType gtk_win32_embed_widget_get_type (void) G_GNUC_CONST;
GtkWidget* _gtk_win32_embed_widget_new (GdkNativeWindow parent_id);
BOOL _gtk_win32_embed_widget_dialog_procedure (GtkWin32EmbedWidget *embed_widget,
HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
G_END_DECLS
#endif /* __GTK_WIN32_EMBED_WIDGET_H__ */

View File

@ -245,6 +245,8 @@ typedef struct {
char *text;
PangoLayout *layout;
GList *page_breaks;
GtkWidget *font_button;
char *font;
} PrintData;
static void
@ -265,7 +267,7 @@ begin_print (GtkPrintOperation *operation,
print_data->layout = gtk_print_context_create_layout (context);
desc = pango_font_description_from_string ("Sans 12");
desc = pango_font_description_from_string (print_data->font);
pango_layout_set_font_description (print_data->layout, desc);
pango_font_description_free (desc);
@ -391,6 +393,42 @@ status_changed_cb (GtkPrintOperation *op,
update_statusbar ();
}
static GtkWidget *
create_custom_widget (GtkPrintOperation *operation,
PrintData *data)
{
GtkWidget *vbox, *hbox, *font, *label;
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
hbox = gtk_hbox_new (FALSE, 8);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
label = gtk_label_new ("Font:");
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
font = gtk_font_button_new_with_font (data->font);
gtk_box_pack_start (GTK_BOX (hbox), font, FALSE, FALSE, 0);
gtk_widget_show (font);
data->font_button = font;
return vbox;
}
static void
custom_widget_apply (GtkPrintOperation *operation,
GtkWidget *widget,
PrintData *data)
{
const char *selected_font;
selected_font = gtk_font_button_get_font_name (GTK_FONT_BUTTON (data->font_button));
g_free (data->font);
data->font = g_strdup (selected_font);
}
static void
do_print (GtkAction *action)
{
@ -401,6 +439,7 @@ do_print (GtkAction *action)
GError *error;
print_data.text = get_text ();
print_data.font = g_strdup ("Sans 12");
print = gtk_print_operation_new ();
@ -414,7 +453,9 @@ do_print (GtkAction *action)
g_signal_connect (print, "begin_print", G_CALLBACK (begin_print), &print_data);
g_signal_connect (print, "draw_page", G_CALLBACK (draw_page), &print_data);
g_signal_connect (print, "create_custom_widget", G_CALLBACK (create_custom_widget), &print_data);
g_signal_connect (print, "custom_widget_apply", G_CALLBACK (custom_widget_apply), &print_data);
error = NULL;
res = gtk_print_operation_run (print, GTK_WINDOW (main_window), &error);
@ -447,8 +488,10 @@ do_print (GtkAction *action)
g_signal_connect (print, "status_changed",
G_CALLBACK (status_changed_cb), NULL);
}
g_object_unref (print);
g_free (print_data.text);
g_free (print_data.font);
}
static void
@ -671,6 +714,7 @@ create_window (void)
int
main (int argc, char **argv)
{
g_set_application_name ("Print editor");
gtk_init (&argc, &argv);
create_window ();