forked from AuroraMiddleware/gtk
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:
parent
fb3eeb8686
commit
d2cb6c6eb2
24
ChangeLog
24
ChangeLog
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@ NONE:INT,BOOL
|
||||
NONE:INT,INT
|
||||
NONE:NONE
|
||||
NONE:STRING,INT,POINTER
|
||||
POINTER:VOID
|
||||
STRING:DOUBLE
|
||||
VOID:DOUBLE
|
||||
VOID:BOOLEAN
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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
394
gtk/gtkwin32embedwidget.c
Normal 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
75
gtk/gtkwin32embedwidget.h
Normal 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__ */
|
@ -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 ();
|
||||
|
Loading…
Reference in New Issue
Block a user