gtk/gdk/win32/gdkwindow.c
Tor Lillqvist c9b2958b6c Don't draw anything if width or height is zero. Don't print a warning if
* gdk/win32/gdkdraw.c (gdk_draw_arc): Don't draw anything if width
 	or height is zero. Don't print a warning if Pie or Arc fails, they
	always fail (?) for very narrow ellipses.

	* gdk/win32/gdkdraw.c (gdk_draw_pixmap): Call InvalidateRgn for
 	the part or the destination window corresponding to source area
 	outside of the source drawable's boundary.

	* gdk/win32/gdkdraw.c (gdk_draw_lines, gdk_draw_polygon): Don't do
 	anything if less than two points.

	* gdk/win32/gdkselection.c (gdk_selection_owner_get): Always
 	return NULL. Gtk cut-and-paste inside a single program works
 	better this way. (It always gets the clipboard contents from
 	Windows, not from its own copy, which is cleared anyway. I can't
 	say I fully understand what happens... Emulating the X selection
 	and property stuff is a bit of a mess.)

	* gdk/win32/gdkevents.c
	* gdk/win32/gdkproperty.c: A bít more verbose logging.

	* gdk/win32/gdkregion.c: Fix some memory leaks (temporary regions
 	that never got deleted). Revamp gdk_region_shrink.

	* gdk/win32/gdkregion.c: Fix memory leak, delete temporary regions
 	after use.

	* gtk/gtk.def: Add some missing entry points.

	* gtk/gtkrc.c: Strip trailing directory separator from pixmap path
 	component.
1999-07-10 00:26:54 +00:00

2570 lines
64 KiB
C

/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-1999 Tor Lillqvist
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-1999. 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 <stdlib.h>
#include <stdio.h>
#include <gdk/gdk.h>
#include "gdkprivate.h"
#include "gdkinput.h"
/* The Win API function AdjustWindowRect may return negative values
* resulting in obscured title bars. This helper function is coreccting it.
*/
BOOL
SafeAdjustWindowRectEx (RECT* lpRect,
DWORD dwStyle,
BOOL bMenu,
DWORD dwExStyle)
{
if (!AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle))
return FALSE;
if (lpRect->left < 0)
{
lpRect->right -= lpRect->left;
lpRect->left = 0;
}
if (lpRect->top < 0)
{
lpRect->bottom -= lpRect->top;
lpRect->top = 0;
}
return TRUE;
}
/* Forward declarations */
static gboolean gdk_window_gravity_works (void);
static void gdk_window_set_static_win_gravity (GdkWindow *window,
gboolean on);
/*
* The following fucntion by The Rasterman <raster@redhat.com>
* This function returns the X Window ID in which the x y location is in
* (x and y being relative to the root window), excluding any windows listed
* in the GList excludes (this is a list of X Window ID's - gpointer being
* the Window ID).
*
* This is primarily designed for internal gdk use - for DND for example
* when using a shaped icon window as the drag object - you exclude the
* X Window ID of the "icon" (perhaps more if excludes may be needed) and
* You can get back an X Window ID as to what X Window ID is infact under
* those X,Y co-ordinates.
*/
HWND
gdk_window_xid_at_coords (gint x,
gint y,
GList *excludes,
gboolean excl_child)
{
POINT pt;
gboolean warned = FALSE;
pt.x = x;
pt.y = y;
/* This is probably not correct, just a quick hack */
if (!warned)
{
g_warning ("gdk_window_xid_at_coords probably not implemented correctly");
warned = TRUE;
}
/* XXX */
return WindowFromPoint (pt);
}
void
gdk_window_init (void)
{
unsigned int width;
unsigned int height;
#if 0
width = GetSystemMetrics (SM_CXSCREEN);
height = GetSystemMetrics (SM_CYSCREEN);
#else
{ RECT r; /* //HB: don't obscure tray window (task bar) */
SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
width = r.right - r.left;
height = r.bottom - r.top;
}
#endif
gdk_root_parent.xwindow = gdk_root_window;
gdk_root_parent.window_type = GDK_WINDOW_ROOT;
gdk_root_parent.window.user_data = NULL;
gdk_root_parent.width = width;
gdk_root_parent.height = height;
gdk_root_parent.children = NULL;
gdk_root_parent.colormap = NULL;
gdk_root_parent.ref_count = 1;
gdk_xid_table_insert (&gdk_root_window, &gdk_root_parent);
}
GdkWindow*
gdk_window_new (GdkWindow *parent,
GdkWindowAttr *attributes,
gint attributes_mask)
{
GdkWindow *window;
GdkWindowPrivate *private;
GdkWindowPrivate *parent_private;
GdkVisual *visual;
HANDLE xparent;
Visual *xvisual;
#ifdef MULTIPLE_WINDOW_CLASSES
WNDCLASSEX wcl;
ATOM klass;
char wcl_name_buf[20];
static int wcl_cnt = 0;
#else
static WNDCLASSEX wcl;
static ATOM klass = 0;
#endif
static HICON hAppIcon = NULL;
DWORD dwStyle, dwExStyle;
RECT rect;
int width, height;
int x, y;
char *title;
g_return_val_if_fail (attributes != NULL, NULL);
if (!parent)
parent = (GdkWindow*) &gdk_root_parent;
parent_private = (GdkWindowPrivate*) parent;
if (parent_private->destroyed)
return NULL;
xparent = parent_private->xwindow;
private = g_new (GdkWindowPrivate, 1);
window = (GdkWindow*) private;
private->parent = parent;
private->destroyed = FALSE;
private->mapped = FALSE;
private->guffaw_gravity = FALSE;
private->resize_count = 0;
private->ref_count = 1;
private->x = (attributes_mask & GDK_WA_X) ? attributes->x : 0;
private->y = (attributes_mask & GDK_WA_Y) ? attributes->y : 0;
private->width = (attributes->width > 1) ? (attributes->width) : (1);
private->height = (attributes->height > 1) ? (attributes->height) : (1);
private->window_type = attributes->window_type;
private->extension_events = 0;
private->extension_events_selected = FALSE;
private->filters = NULL;
private->children = NULL;
window->user_data = NULL;
if (attributes_mask & GDK_WA_VISUAL)
visual = attributes->visual;
else
visual = gdk_visual_get_system ();
xvisual = ((GdkVisualPrivate*) visual)->xvisual;
if (attributes_mask & GDK_WA_TITLE)
title = attributes->title;
else
title = g_get_prgname ();
private->event_mask = GDK_STRUCTURE_MASK | attributes->event_mask;
private->bg_type = GDK_WIN32_BG_NORMAL;
private->hint_flags = 0;
#ifndef MULTIPLE_WINDOW_CLASSES
if (klass == 0)
{
#endif
wcl.cbSize = sizeof (WNDCLASSEX);
#if 1
wcl.style = CS_HREDRAW | CS_VREDRAW;
#else
wcl.style = 0;
#endif
wcl.lpfnWndProc = gdk_WindowProc;
wcl.cbClsExtra = 0;
wcl.cbWndExtra = 0;
wcl.hInstance = gdk_ProgInstance;
wcl.hCursor = LoadCursor (NULL, IDC_ARROW);
#if 0 /* tml: orig -> generates SetClassLong errors in set background */
wcl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wcl.hbrBackground = NULL;
#else
/* initialize once! */
if (0 == hAppIcon)
{
gchar sLoc [_MAX_PATH+1];
HINSTANCE hInst = GetModuleHandle(NULL);
if (0 != GetModuleFileName(hInst, sLoc, _MAX_PATH))
{
hAppIcon = ExtractIcon(hInst, sLoc, 0);
if (0 == hAppIcon)
{
char *gdklibname = g_strdup_printf ("gdk-%s.dll", GDK_VERSION);
hAppIcon = ExtractIcon(hInst, gdklibname, 0);
g_free (gdklibname);
}
if (0 == hAppIcon)
hAppIcon = LoadIcon (NULL, IDI_APPLICATION);
}
}
wcl.hIcon = CopyIcon (hAppIcon);
wcl.hIconSm = CopyIcon (hAppIcon);
/* HB: starting with black to have something to release ... */
wcl.hbrBackground = CreateSolidBrush( RGB(0,0,0));
#endif
wcl.lpszMenuName = NULL;
#ifdef MULTIPLE_WINDOW_CLASSES
sprintf (wcl_name_buf, "gdk-wcl-%d", wcl_cnt++);
wcl.lpszClassName = g_strdup (wcl_name_buf);
/* wcl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); */
#else
wcl.lpszClassName = "GDK-window-class";
klass = RegisterClassEx (&wcl);
if (!klass)
g_error ("RegisterClassEx failed");
}
private->xcursor = NULL;
#endif
if (parent_private && parent_private->guffaw_gravity)
{
/* XXX ??? */
}
if (attributes->wclass == GDK_INPUT_OUTPUT)
{
dwExStyle = 0;
if (attributes_mask & GDK_WA_COLORMAP)
private->colormap = attributes->colormap;
else
private->colormap = gdk_colormap_get_system ();
}
else
{
dwExStyle = WS_EX_TRANSPARENT;
private->colormap = NULL;
private->bg_type = GDK_WIN32_BG_TRANSPARENT;
private->bg_pixmap = NULL;
}
if (attributes_mask & GDK_WA_X)
x = attributes->x;
else
x = CW_USEDEFAULT;
if (attributes_mask & GDK_WA_Y)
y = attributes->y;
else if (attributes_mask & GDK_WA_X)
y = 100; /* ??? We must put it somewhere... */
else
y = 500; /* x is CW_USEDEFAULT, y doesn't matter then */
if (parent_private)
parent_private->children = g_list_prepend (parent_private->children, window);
switch (private->window_type)
{
case GDK_WINDOW_TOPLEVEL:
dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN;
xparent = gdk_root_window;
break;
case GDK_WINDOW_CHILD:
dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
break;
case GDK_WINDOW_DIALOG:
dwStyle = WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION | WS_THICKFRAME | WS_CLIPCHILDREN;
xparent = gdk_root_window;
break;
case GDK_WINDOW_TEMP:
dwStyle = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
#ifdef MULTIPLE_WINDOW_CLASSES
wcl.style |= CS_SAVEBITS;
#endif
dwExStyle |= WS_EX_TOOLWINDOW;
break;
case GDK_WINDOW_ROOT:
g_error ("cannot make windows of type GDK_WINDOW_ROOT");
break;
case GDK_WINDOW_PIXMAP:
g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
break;
}
#ifdef MULTIPLE_WINDOW_CLASSES
klass = RegisterClassEx (&wcl);
if (!klass)
g_error ("RegisterClassEx failed");
#endif
if (private->window_type != GDK_WINDOW_CHILD)
{
if (x == CW_USEDEFAULT)
{
rect.left = 100;
rect.top = 100;
}
else
{
rect.left = x;
rect.top = y;
}
rect.right = rect.left + private->width;
rect.bottom = rect.top + private->height;
if (!SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
g_warning ("gdk_window_new: AdjustWindowRectEx failed");
if (x != CW_USEDEFAULT)
{
x = rect.left;
y = rect.top;
}
width = rect.right - rect.left;
height = rect.bottom - rect.top;
}
else
{
width = private->width;
height = private->height;
}
private->xwindow =
CreateWindowEx (dwExStyle,
wcl.lpszClassName,
title,
dwStyle,
x, y,
width, height,
xparent,
NULL,
gdk_ProgInstance,
NULL);
GDK_NOTE (MISC,
g_print ("gdk_window_create: %s %s %#x %#x %dx%d@+%d+%d %#x = %#x\n",
(private->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
(private->window_type == GDK_WINDOW_CHILD ? "CHILD" :
(private->window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
(private->window_type == GDK_WINDOW_TEMP ? "TEMP" :
"???")))),
title,
dwStyle,
private->event_mask,
width, height, (x == CW_USEDEFAULT ? -9999 : x), y,
xparent,
private->xwindow));
gdk_window_ref (window);
gdk_xid_table_insert (&private->xwindow, window);
if (private->colormap)
gdk_colormap_ref (private->colormap);
gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
(attributes->cursor) :
NULL));
return window;
}
GdkWindow *
gdk_window_foreign_new (guint32 anid)
{
GdkWindow *window;
GdkWindowPrivate *private;
GdkWindowPrivate *parent_private;
HANDLE parent;
RECT rect;
POINT point;
private = g_new (GdkWindowPrivate, 1);
window = (GdkWindow*) private;
parent = GetParent ((HWND) anid);
private->parent = gdk_xid_table_lookup (parent);
parent_private = (GdkWindowPrivate *)private->parent;
if (parent_private)
parent_private->children = g_list_prepend (parent_private->children, window);
private->xwindow = (HWND) anid;
GetClientRect ((HWND) anid, &rect);
point.x = rect.left;
point.y = rect.right;
ClientToScreen ((HWND) anid, &point);
if (parent != HWND_DESKTOP)
ScreenToClient (parent, &point);
private->x = point.x;
private->y = point.y;
private->width = rect.right - rect.left;
private->height = rect.bottom - rect.top;
private->resize_count = 0;
private->ref_count = 1;
private->window_type = GDK_WINDOW_FOREIGN;
private->destroyed = FALSE;
private->mapped = IsWindowVisible (private->xwindow);
private->guffaw_gravity = FALSE;
private->extension_events = 0;
private->extension_events_selected = FALSE;
private->colormap = NULL;
private->filters = NULL;
private->children = NULL;
window->user_data = NULL;
gdk_window_ref (window);
gdk_xid_table_insert (&private->xwindow, window);
return window;
}
/* Call this function when you want a window and all its children to
* disappear. When xdestroy is true, a request to destroy the XWindow
* is sent out. When it is false, it is assumed that the XWindow has
* been or will be destroyed by destroying some ancestor of this
* window.
*/
static void
gdk_window_internal_destroy (GdkWindow *window,
gboolean xdestroy,
gboolean our_destroy)
{
GdkWindowPrivate *private;
GdkWindowPrivate *temp_private;
GdkWindow *temp_window;
GList *children;
GList *tmp;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
GDK_NOTE (MISC, g_print ("gdk_window_internal_destroy %#x\n",
private->xwindow));
switch (private->window_type)
{
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_CHILD:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
case GDK_WINDOW_FOREIGN:
if (!private->destroyed)
{
if (private->parent)
{
GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
if (parent_private->children)
parent_private->children = g_list_remove (parent_private->children, window);
}
if (private->window_type != GDK_WINDOW_FOREIGN)
{
children = tmp = private->children;
private->children = NULL;
while (tmp)
{
temp_window = tmp->data;
tmp = tmp->next;
temp_private = (GdkWindowPrivate*) temp_window;
if (temp_private)
gdk_window_internal_destroy (temp_window, FALSE,
our_destroy);
}
g_list_free (children);
}
if (private->extension_events != 0)
gdk_input_window_destroy (window);
if (private->filters)
{
tmp = private->filters;
while (tmp)
{
g_free (tmp->data);
tmp = tmp->next;
}
g_list_free (private->filters);
private->filters = NULL;
}
if (private->window_type == GDK_WINDOW_FOREIGN)
{
if (our_destroy && (private->parent != NULL))
{
/* It's somebody elses window, but in our hierarchy,
* so reparent it to the root window, and then send
* it a delete event, as if we were a WM
*/
gdk_window_hide (window);
gdk_window_reparent (window, NULL, 0, 0);
/* Is this too drastic? Many (most?) applications
* quit if any window receives WM_QUIT I think.
* OTOH, I don't think foreign windows are much
* used, so the question is maybe academic.
*/
PostMessage (private->xwindow, WM_QUIT, 0, 0);
}
}
else if (xdestroy)
DestroyWindow (private->xwindow);
if (private->colormap)
gdk_colormap_unref (private->colormap);
private->mapped = FALSE;
private->destroyed = TRUE;
}
break;
case GDK_WINDOW_ROOT:
g_error ("attempted to destroy root window");
break;
case GDK_WINDOW_PIXMAP:
g_error ("called gdk_window_destroy on a pixmap (use gdk_pixmap_unref)");
break;
}
}
/* Like internal_destroy, but also destroys the reference created by
gdk_window_new. */
void
gdk_window_destroy (GdkWindow *window)
{
gdk_window_internal_destroy (window, TRUE, TRUE);
gdk_window_unref (window);
}
/* This function is called when the XWindow is really gone. */
void
gdk_window_destroy_notify (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
GDK_NOTE (EVENTS, g_print ("gdk_window_destroy_notify: %#x %d\n",
private->xwindow, private->destroyed));
if (!private->destroyed)
{
if (private->window_type == GDK_WINDOW_FOREIGN)
gdk_window_internal_destroy (window, FALSE, FALSE);
else
g_warning ("GdkWindow %#lx unexpectedly destroyed", private->xwindow);
}
gdk_xid_table_remove (private->xwindow);
gdk_window_unref (window);
}
GdkWindow*
gdk_window_ref (GdkWindow *window)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
g_return_val_if_fail (window != NULL, NULL);
private->ref_count += 1;
GDK_NOTE (MISC, g_print ("gdk_window_ref %#x %d\n",
private->xwindow, private->ref_count));
return window;
}
void
gdk_window_unref (GdkWindow *window)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
g_return_if_fail (window != NULL);
private->ref_count -= 1;
GDK_NOTE (MISC, g_print ("gdk_window_unref %#x %d%s\n",
private->xwindow, private->ref_count,
(private->ref_count == 0 ? " freeing" : "")));
if (private->ref_count == 0)
{
if (private->bg_type == GDK_WIN32_BG_PIXMAP && private->bg_pixmap != NULL)
gdk_pixmap_unref (private->bg_pixmap);
if (!private->destroyed)
{
if (private->window_type == GDK_WINDOW_FOREIGN)
gdk_xid_table_remove (private->xwindow);
else
g_warning ("losing last reference to undestroyed window");
}
g_dataset_destroy (window);
g_free (window);
}
}
void
gdk_window_show (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
GDK_NOTE (MISC, g_print ("gdk_window_show: %#x\n", private->xwindow));
private->mapped = TRUE;
if (private->window_type == GDK_WINDOW_TEMP)
{
ShowWindow (private->xwindow, SW_SHOWNOACTIVATE);
SetWindowPos (private->xwindow, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
#if 0
ShowWindow (private->xwindow, SW_HIDE); /* Don't put on toolbar */
#endif
}
else
{
ShowWindow (private->xwindow, SW_SHOWNORMAL);
ShowWindow (private->xwindow, SW_RESTORE);
SetForegroundWindow (private->xwindow);
#if 0
ShowOwnedPopups (private->xwindow, TRUE);
#endif
}
}
}
void
gdk_window_hide (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
GDK_NOTE (MISC, g_print ("gdk_window_hide: %#x\n", private->xwindow));
private->mapped = FALSE;
if (private->window_type == GDK_WINDOW_TOPLEVEL)
ShowOwnedPopups (private->xwindow, FALSE);
#if 1
ShowWindow (private->xwindow, SW_HIDE);
#elif 0
ShowWindow (private->xwindow, SW_MINIMIZE);
#else
CloseWindow (private->xwindow);
#endif
}
}
void
gdk_window_withdraw (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
GDK_NOTE (MISC, g_print ("gdk_window_withdraw: %#x\n", private->xwindow));
gdk_window_hide (window); /* XXX */
}
}
void
gdk_window_move (GdkWindow *window,
gint x,
gint y)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
RECT rect;
GDK_NOTE (MISC, g_print ("gdk_window_move: %#x +%d+%d\n",
private->xwindow, x, y));
GetClientRect (private->xwindow, &rect);
if (private->window_type != GDK_WINDOW_CHILD)
{
POINT ptTL, ptBR;
DWORD dwStyle;
DWORD dwExStyle;
ptTL.x = 0;
ptTL.y = 0;
ClientToScreen (private->xwindow, &ptTL);
rect.left = x;
rect.top = y;
ptBR.x = rect.right;
ptBR.y = rect.bottom;
ClientToScreen (private->xwindow, &ptBR);
rect.right = x + ptBR.x - ptTL.x;
rect.bottom = y + ptBR.y - ptTL.y;
dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
if (!SafeAdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
g_warning ("gdk_window_move: AdjustWindowRectEx failed");
x = rect.left;
y = rect.top;
}
else
{
private->x = x;
private->y = y;
}
GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
private->xwindow,
rect.right - rect.left, rect.bottom - rect.top,
x, y));
if (!MoveWindow (private->xwindow,
x, y, rect.right - rect.left, rect.bottom - rect.top,
TRUE))
g_warning ("gdk_window_move: MoveWindow failed");
}
}
void
gdk_window_resize (GdkWindow *window,
gint width,
gint height)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
if ((gint16) width < 1)
width = 1;
if ((gint16) height < 1)
height = 1;
private = (GdkWindowPrivate*) window;
if (!private->destroyed &&
((private->resize_count > 0) ||
(private->width != (guint16) width) ||
(private->height != (guint16) height)))
{
int x, y;
GDK_NOTE (MISC, g_print ("gdk_window_resize: %#x %dx%d\n",
private->xwindow, width, height));
if (private->window_type != GDK_WINDOW_CHILD)
{
POINT pt;
RECT rect;
DWORD dwStyle;
DWORD dwExStyle;
pt.x = 0;
pt.y = 0;
ClientToScreen (private->xwindow, &pt);
rect.left = pt.x;
rect.top = pt.y;
rect.right = pt.x + width;
rect.bottom = pt.y + height;
dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
g_warning ("gdk_window_resize: AdjustWindowRectEx failed");
x = rect.left;
y = rect.top;
width = rect.right - rect.left;
height = rect.bottom - rect.top;
}
else
{
x = private->x;
y = private->y;
private->width = width;
private->height = height;
}
private->resize_count += 1;
GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
private->xwindow, width, height, x, y));
if (!MoveWindow (private->xwindow,
x, y, width, height,
TRUE))
g_warning ("gdk_window_resize: MoveWindow failed");
}
}
void
gdk_window_move_resize (GdkWindow *window,
gint x,
gint y,
gint width,
gint height)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
if ((gint16) width < 1)
width = 1;
if ((gint16) height < 1)
height = 1;
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
RECT rect;
DWORD dwStyle;
DWORD dwExStyle;
GDK_NOTE (MISC, g_print ("gdk_window_move_resize: %#x %dx%d@+%d+%d\n",
private->xwindow, width, height, x, y));
rect.left = x;
rect.top = y;
rect.right = x + width;
rect.bottom = y + height;
dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
if (!AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle))
g_warning ("gdk_window_move_resize: AdjustWindowRectEx failed");
if (private->window_type == GDK_WINDOW_CHILD)
{
private->x = x;
private->y = y;
private->width = width;
private->height = height;
}
GDK_NOTE (MISC, g_print ("...MoveWindow(%#x,%dx%d@+%d+%d)\n",
private->xwindow,
rect.right - rect.left, rect.bottom - rect.top,
rect.left, rect.top));
if (!MoveWindow (private->xwindow,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
TRUE))
g_warning ("gdk_window_move_resize: MoveWindow failed");
if (private->guffaw_gravity)
{
GList *tmp_list = private->children;
while (tmp_list)
{
GdkWindowPrivate *child_private = tmp_list->data;
child_private->x -= x - private->x;
child_private->y -= y - private->y;
tmp_list = tmp_list->next;
}
}
}
}
void
gdk_window_reparent (GdkWindow *window,
GdkWindow *new_parent,
gint x,
gint y)
{
GdkWindowPrivate *window_private;
GdkWindowPrivate *parent_private;
GdkWindowPrivate *old_parent_private;
g_return_if_fail (window != NULL);
if (!new_parent)
new_parent = (GdkWindow*) &gdk_root_parent;
window_private = (GdkWindowPrivate*) window;
old_parent_private = (GdkWindowPrivate*)window_private->parent;
parent_private = (GdkWindowPrivate*) new_parent;
if (!window_private->destroyed && !parent_private->destroyed)
{
GDK_NOTE (MISC, g_print ("gdk_window_reparent: %#x %#x\n",
window_private->xwindow,
parent_private->xwindow));
if (!SetParent (window_private->xwindow, parent_private->xwindow))
g_warning ("gdk_window_reparent: SetParent failed");
if (!MoveWindow (window_private->xwindow,
x, y,
window_private->width, window_private->height,
TRUE))
g_warning ("gdk_window_reparent: MoveWindow failed");
}
window_private->parent = new_parent;
if (old_parent_private)
old_parent_private->children = g_list_remove (old_parent_private->children, window);
if ((old_parent_private &&
(!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
(!old_parent_private && parent_private->guffaw_gravity))
gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
parent_private->children = g_list_prepend (parent_private->children, window);
}
void
gdk_window_clear (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
gdk_window_clear_area (window, 0, 0, private->width, private->height);
}
}
void
gdk_window_clear_area (GdkWindow *window,
gint x,
gint y,
gint width,
gint height)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
HDC hdc;
if (width == -1)
width = G_MAXSHORT/2; /* Yeah, right */
if (height == -1)
height = G_MAXSHORT/2;
GDK_NOTE (MISC, g_print ("gdk_window_clear_area: %#x %dx%d@+%d+%d\n",
private->xwindow, width, height, x, y));
hdc = GetDC (private->xwindow);
IntersectClipRect (hdc, x, y, x + width, y + height);
SendMessage (private->xwindow, WM_ERASEBKGND, (WPARAM) hdc, 0);
ReleaseDC (private->xwindow, hdc);
}
}
void
gdk_window_clear_area_e (GdkWindow *window,
gint x,
gint y,
gint width,
gint height)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
RECT rect;
GDK_NOTE (MISC, g_print ("gdk_window_clear_area_e: %#x %dx%d@+%d+%d\n",
private->xwindow, width, height, x, y));
rect.left = x;
rect.right = x + width;
rect.top = y;
rect.bottom = y + height;
if (!InvalidateRect (private->xwindow, &rect, TRUE))
g_warning ("gdk_window_clear_area_e: InvalidateRect failed");
UpdateWindow (private->xwindow);
}
}
void
gdk_window_copy_area (GdkWindow *window,
GdkGC *gc,
gint x,
gint y,
GdkWindow *source_window,
gint source_x,
gint source_y,
gint width,
gint height)
{
GdkWindowPrivate *src_private;
GdkWindowPrivate *dest_private;
GdkGCPrivate *gc_private;
g_return_if_fail (window != NULL);
g_return_if_fail (gc != NULL);
if (source_window == NULL)
source_window = window;
src_private = (GdkWindowPrivate*) source_window;
dest_private = (GdkWindowPrivate*) window;
gc_private = (GdkGCPrivate*) gc;
if (!src_private->destroyed && !dest_private->destroyed)
{
HDC hdcDest, hdcSrc;
if ((hdcDest = GetDC (dest_private->xwindow)) == NULL)
g_warning ("gdk_window_copy_area: GetDC failed");
if ((hdcSrc = GetDC (src_private->xwindow)) == NULL)
g_warning ("gdk_window_copy_area: GetDC failed");
if (!BitBlt (hdcDest, x, y, width, height, hdcSrc, source_x, source_y, SRCCOPY))
g_warning ("gdk_window_copy_area: BitBlt failed");
ReleaseDC (dest_private->xwindow, hdcDest);
ReleaseDC (src_private->xwindow, hdcSrc);
}
}
void
gdk_window_raise (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
GDK_NOTE (MISC, g_print ("gdk_window_raise: %#x\n", private->xwindow));
if (!BringWindowToTop (private->xwindow))
g_warning ("gdk_window_raise: BringWindowToTop failed");
}
}
void
gdk_window_lower (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
GDK_NOTE (MISC, g_print ("gdk_window_lower: %#x\n", private->xwindow));
if (!SetWindowPos (private->xwindow, HWND_BOTTOM, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE))
g_warning ("gdk_window_lower: SetWindowPos failed");
}
}
void
gdk_window_set_user_data (GdkWindow *window,
gpointer user_data)
{
g_return_if_fail (window != NULL);
window->user_data = user_data;
}
void
gdk_window_set_hints (GdkWindow *window,
gint x,
gint y,
gint min_width,
gint min_height,
gint max_width,
gint max_height,
gint flags)
{
GdkWindowPrivate *private;
WINDOWPLACEMENT size_hints;
RECT rect;
DWORD dwStyle;
DWORD dwExStyle;
int diff;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (private->destroyed)
return;
GDK_NOTE (MISC, g_print ("gdk_window_set_hints: %#x %dx%d..%dx%d @+%d+%d\n",
private->xwindow,
min_width, min_height, max_width, max_height,
x, y));
private->hint_flags = flags;
size_hints.length = sizeof (size_hints);
if (flags)
{
if (flags & GDK_HINT_POS)
if (!GetWindowPlacement (private->xwindow, &size_hints))
g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
else
{
GDK_NOTE (MISC, g_print ("...rcNormalPosition:"
" (%d,%d)--(%d,%d)\n",
size_hints.rcNormalPosition.left,
size_hints.rcNormalPosition.top,
size_hints.rcNormalPosition.right,
size_hints.rcNormalPosition.bottom));
/* What are the corresponding window coordinates for client
* area coordinates x, y
*/
rect.left = x;
rect.top = y;
rect.right = rect.left + 200; /* dummy */
rect.bottom = rect.top + 200;
dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
size_hints.flags = 0;
size_hints.showCmd = SW_SHOWNA;
/* Set the normal position hint to that location, with unchanged
* width and height.
*/
diff = size_hints.rcNormalPosition.left - rect.left;
size_hints.rcNormalPosition.left = rect.left;
size_hints.rcNormalPosition.right -= diff;
diff = size_hints.rcNormalPosition.top - rect.top;
size_hints.rcNormalPosition.top = rect.top;
size_hints.rcNormalPosition.bottom -= diff;
GDK_NOTE (MISC, g_print ("...setting: (%d,%d)--(%d,%d)\n",
size_hints.rcNormalPosition.left,
size_hints.rcNormalPosition.top,
size_hints.rcNormalPosition.right,
size_hints.rcNormalPosition.bottom));
if (!SetWindowPlacement (private->xwindow, &size_hints))
g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
private->hint_x = rect.left;
private->hint_y = rect.top;
}
if (flags & GDK_HINT_MIN_SIZE)
{
rect.left = 0;
rect.top = 0;
rect.right = min_width;
rect.bottom = min_height;
dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
private->hint_min_width = rect.right - rect.left;
private->hint_min_height = rect.bottom - rect.top;
/* Also chek if he current size of the window is in bounds. */
GetClientRect (private->xwindow, &rect);
if (rect.right < min_width && rect.bottom < min_height)
gdk_window_resize (window, min_width, min_height);
else if (rect.right < min_width)
gdk_window_resize (window, min_width, rect.bottom);
else if (rect.bottom < min_height)
gdk_window_resize (window, rect.right, min_height);
}
if (flags & GDK_HINT_MAX_SIZE)
{
rect.left = 0;
rect.top = 0;
rect.right = max_width;
rect.bottom = max_height;
dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
private->hint_max_width = rect.right - rect.left;
private->hint_max_height = rect.bottom - rect.top;
/* Again, check if the window is too large currently. */
GetClientRect (private->xwindow, &rect);
if (rect.right > max_width && rect.bottom > max_height)
gdk_window_resize (window, max_width, max_height);
else if (rect.right > max_width)
gdk_window_resize (window, max_width, rect.bottom);
else if (rect.bottom > max_height)
gdk_window_resize (window, rect.right, max_height);
}
}
}
void
gdk_window_set_geometry_hints (GdkWindow *window,
GdkGeometry *geometry,
GdkWindowHints geom_mask)
{
GdkWindowPrivate *private;
WINDOWPLACEMENT size_hints;
RECT rect;
DWORD dwStyle;
DWORD dwExStyle;
int diff;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (private->destroyed)
return;
size_hints.length = sizeof (size_hints);
private->hint_flags = geom_mask;
if (geom_mask & GDK_HINT_POS)
; /* XXX */
if (geom_mask & GDK_HINT_MIN_SIZE)
{
rect.left = 0;
rect.top = 0;
rect.right = geometry->min_width;
rect.bottom = geometry->min_height;
dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
private->hint_min_width = rect.right - rect.left;
private->hint_min_height = rect.bottom - rect.top;
/* Also check if he current size of the window is in bounds */
GetClientRect (private->xwindow, &rect);
if (rect.right < geometry->min_width
&& rect.bottom < geometry->min_height)
gdk_window_resize (window, geometry->min_width, geometry->min_height);
else if (rect.right < geometry->min_width)
gdk_window_resize (window, geometry->min_width, rect.bottom);
else if (rect.bottom < geometry->min_height)
gdk_window_resize (window, rect.right, geometry->min_height);
}
if (geom_mask & GDK_HINT_MAX_SIZE)
{
rect.left = 0;
rect.top = 0;
rect.right = geometry->max_width;
rect.bottom = geometry->max_height;
dwStyle = GetWindowLong (private->xwindow, GWL_STYLE);
dwExStyle = GetWindowLong (private->xwindow, GWL_EXSTYLE);
AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
private->hint_max_width = rect.right - rect.left;
private->hint_max_height = rect.bottom - rect.top;
/* Again, check if the window is too large currently. */
GetClientRect (private->xwindow, &rect);
if (rect.right > geometry->max_width
&& rect.bottom > geometry->max_height)
gdk_window_resize (window, geometry->max_width, geometry->max_height);
else if (rect.right > geometry->max_width)
gdk_window_resize (window, geometry->max_width, rect.bottom);
else if (rect.bottom > geometry->max_height)
gdk_window_resize (window, rect.right, geometry->max_height);
}
/* I don't know what to do when called with zero base_width and height. */
if (geom_mask & GDK_HINT_BASE_SIZE
&& geometry->base_width > 0
&& geometry->base_height > 0)
if (!GetWindowPlacement (private->xwindow, &size_hints))
g_warning ("gdk_window_set_hints: GetWindowPlacement failed");
else
{
GDK_NOTE (MISC, g_print ("gdk_window_set_geometry_hints:"
" rcNormalPosition: (%d,%d)--(%d,%d)\n",
size_hints.rcNormalPosition.left,
size_hints.rcNormalPosition.top,
size_hints.rcNormalPosition.right,
size_hints.rcNormalPosition.bottom));
size_hints.rcNormalPosition.right =
size_hints.rcNormalPosition.left + geometry->base_width;
size_hints.rcNormalPosition.bottom =
size_hints.rcNormalPosition.top + geometry->base_height;
GDK_NOTE (MISC, g_print ("...setting: rcNormal: (%d,%d)--(%d,%d)\n",
size_hints.rcNormalPosition.left,
size_hints.rcNormalPosition.top,
size_hints.rcNormalPosition.right,
size_hints.rcNormalPosition.bottom));
if (!SetWindowPlacement (private->xwindow, &size_hints))
g_warning ("gdk_window_set_hints: SetWindowPlacement failed");
}
if (geom_mask & GDK_HINT_RESIZE_INC)
{
/* XXX */
}
if (geom_mask & GDK_HINT_ASPECT)
{
/* XXX */
}
}
void
gdk_window_set_title (GdkWindow *window,
const gchar *title)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
if (!SetWindowText (private->xwindow, title))
g_warning ("gdk_window_set_title: SetWindowText failed");
}
}
void
gdk_window_set_role (GdkWindow *window,
const gchar *role)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
GDK_NOTE (MISC, g_print ("gdk_window_set_role: %#x %s\n",
private->xwindow, (role ? role : "NULL")));
/* XXX */
}
void
gdk_window_set_transient_for (GdkWindow *window,
GdkWindow *parent)
{
GdkWindowPrivate *private;
GdkWindowPrivate *parent_private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
parent_private = (GdkWindowPrivate*) parent;
GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %#x %#x\n",
private->xwindow, parent_private->xwindow));
/* XXX */
}
void
gdk_window_set_background (GdkWindow *window,
GdkColor *color)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
GdkColormapPrivate *colormap_private =
(GdkColormapPrivate *) private->colormap;
GDK_NOTE (MISC, g_print ("gdk_window_set_background: %#x %s\n",
private->xwindow,
gdk_color_to_string (color)));
if (private->bg_type == GDK_WIN32_BG_PIXMAP)
{
if (private->bg_pixmap != NULL)
{
gdk_pixmap_unref (private->bg_pixmap);
private->bg_pixmap = NULL;
}
private->bg_type = GDK_WIN32_BG_NORMAL;
}
#ifdef MULTIPLE_WINDOW_CLASSES
if (colormap_private != NULL
&& colormap_private->xcolormap->rc_palette)
{
/* If we are on a palettized display we can't use the window
* class background brush, but must handle WM_ERASEBKGND.
* At least, I think so.
*/
#endif
private->bg_type = GDK_WIN32_BG_PIXEL;
private->bg_pixel = *color;
#ifdef MULTIPLE_WINDOW_CLASSES
}
else
{
/* Non-palettized display; just set the window class background
brush. */
HBRUSH hbr;
HGDIOBJ oldbrush;
COLORREF background;
background = RGB (color->red >> 8,
color->green >> 8,
color->blue >> 8);
if ((hbr = CreateSolidBrush (GetNearestColor (gdk_DC,
background))) == NULL)
{
g_warning ("gdk_window_set_background: CreateSolidBrush failed");
return;
}
oldbrush = (HGDIOBJ) GetClassLong (private->xwindow,
GCL_HBRBACKGROUND);
if (SetClassLong (private->xwindow, GCL_HBRBACKGROUND,
(LONG) hbr) == 0)
g_warning ("gdk_window_set_background: SetClassLong failed");
if (!DeleteObject (oldbrush))
g_warning ("gdk_window_set_background: DeleteObject failed");
}
#endif
}
}
void
gdk_window_set_back_pixmap (GdkWindow *window,
GdkPixmap *pixmap,
gint parent_relative)
{
GdkWindowPrivate *window_private;
#ifdef MULTIPLE_WINDOW_CLASSES
GdkPixmapPrivate *pixmap_private;
#endif
g_return_if_fail (window != NULL);
window_private = (GdkWindowPrivate*) window;
#ifdef MULTIPLE_WINDOW_CLASSES
pixmap_private = (GdkPixmapPrivate*) pixmap;
#endif
if (!window_private->destroyed)
{
GdkColormapPrivate *colormap_private =
(GdkColormapPrivate *) window_private->colormap;
if (window_private->bg_type == GDK_WIN32_BG_PIXMAP)
{
if (window_private->bg_pixmap != NULL)
{
gdk_pixmap_unref (window_private->bg_pixmap);
window_private->bg_pixmap = NULL;
}
window_private->bg_type = GDK_WIN32_BG_NORMAL;
}
if (parent_relative)
{
window_private->bg_type = GDK_WIN32_BG_PARENT_RELATIVE;
}
else if (!pixmap)
{
#ifdef MULTIPLE_WINDOW_CLASSES
SetClassLong (window_private->xwindow, GCL_HBRBACKGROUND,
(LONG) GetStockObject (BLACK_BRUSH));
#endif
}
#ifdef MULTIPLE_WINDOW_CLASSES
else if (colormap_private->xcolormap->rc_palette)
{
/* Must do the background painting in the
* WM_ERASEBKGND handler.
*/
window_private->bg_type = GDK_WIN32_BG_PIXMAP;
window_private->bg_pixmap = pixmap;
gdk_pixmap_ref (pixmap);
}
else if (pixmap_private->width <= 8
&& pixmap_private->height <= 8)
{
/* We can use small pixmaps directly as background brush */
SetClassLong (window_private->xwindow, GCL_HBRBACKGROUND,
(LONG) CreatePatternBrush (pixmap_private->xwindow));
}
#endif
else
{
/* We must cache the pixmap in the WindowPrivate and
* paint it each time we get WM_ERASEBKGND
*/
window_private->bg_type = GDK_WIN32_BG_PIXMAP;
window_private->bg_pixmap = pixmap;
gdk_pixmap_ref (pixmap);
}
}
}
void
gdk_window_set_cursor (GdkWindow *window,
GdkCursor *cursor)
{
GdkWindowPrivate *window_private;
GdkCursorPrivate *cursor_private;
HCURSOR xcursor;
g_return_if_fail (window != NULL);
window_private = (GdkWindowPrivate*) window;
cursor_private = (GdkCursorPrivate*) cursor;
if (!window_private->destroyed)
{
if (!cursor)
xcursor = LoadCursor (NULL, IDC_ARROW);
else
xcursor = cursor_private->xcursor;
GDK_NOTE (MISC, g_print ("gdk_window_set_cursor: %#x %#x\n",
window_private->xwindow, xcursor));
#ifdef MULTIPLE_WINDOW_CLASSES
if (!SetClassLong (window_private->xwindow, GCL_HCURSOR, (LONG) xcursor))
g_warning ("gdk_window_set_cursor: SetClassLong failed");
#else
window_private->xcursor = xcursor;
#endif
SetCursor (xcursor);
}
}
void
gdk_window_set_colormap (GdkWindow *window,
GdkColormap *colormap)
{
GdkWindowPrivate *window_private;
GdkColormapPrivate *colormap_private;
g_return_if_fail (window != NULL);
g_return_if_fail (colormap != NULL);
window_private = (GdkWindowPrivate*) window;
colormap_private = (GdkColormapPrivate*) colormap;
if (!window_private->destroyed)
{
/* XXX ??? */
GDK_NOTE (MISC, g_print ("gdk_window_set_colormap: %#x %#x\n",
window_private->xwindow,
colormap_private->xcolormap));
if (window_private->colormap)
gdk_colormap_unref (window_private->colormap);
window_private->colormap = colormap;
gdk_colormap_ref (window_private->colormap);
if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
gdk_window_add_colormap_windows (window);
}
}
void
gdk_window_get_user_data (GdkWindow *window,
gpointer *data)
{
g_return_if_fail (window != NULL);
*data = window->user_data;
}
void
gdk_window_get_geometry (GdkWindow *window,
gint *x,
gint *y,
gint *width,
gint *height,
gint *depth)
{
GdkWindowPrivate *window_private;
if (!window)
window = (GdkWindow*) &gdk_root_parent;
window_private = (GdkWindowPrivate*) window;
if (!window_private->destroyed)
{
RECT rect;
if (!GetClientRect (window_private->xwindow, &rect))
g_warning ("gdk_window_get_geometry: GetClientRect failed");
if (x)
*x = rect.left;
if (y)
*y = rect.top;
if (width)
*width = rect.right - rect.left;
if (height)
*height = rect.bottom - rect.top;
if (depth)
*depth = gdk_window_get_visual (window)->depth;
}
}
void
gdk_window_get_position (GdkWindow *window,
gint *x,
gint *y)
{
GdkWindowPrivate *window_private;
g_return_if_fail (window != NULL);
window_private = (GdkWindowPrivate*) window;
if (x)
*x = window_private->x;
if (y)
*y = window_private->y;
}
void
gdk_window_get_size (GdkWindow *window,
gint *width,
gint *height)
{
GdkWindowPrivate *window_private;
g_return_if_fail (window != NULL);
window_private = (GdkWindowPrivate*) window;
if (width)
*width = window_private->width;
if (height)
*height = window_private->height;
}
GdkVisual*
gdk_window_get_visual (GdkWindow *window)
{
GdkWindowPrivate *window_private;
g_return_val_if_fail (window != NULL, NULL);
window_private = (GdkWindowPrivate*) window;
/* Huh? ->parent is never set for a pixmap. We should just return
* null immeditately. Well, do it then!
*/
if (window_private->window_type == GDK_WINDOW_PIXMAP)
return NULL;
if (!window_private->destroyed)
{
if (window_private->colormap == NULL)
return gdk_visual_get_system (); /* XXX ??? */
else
return ((GdkColormapPrivate *)window_private->colormap)->visual;
}
return NULL;
}
GdkColormap*
gdk_window_get_colormap (GdkWindow *window)
{
GdkWindowPrivate *window_private;
g_return_val_if_fail (window != NULL, NULL);
window_private = (GdkWindowPrivate*) window;
g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
if (!window_private->destroyed)
{
if (window_private->colormap == NULL)
return gdk_colormap_get_system (); /* XXX ??? */
else
return window_private->colormap;
}
return NULL;
}
GdkWindowType
gdk_window_get_type (GdkWindow *window)
{
GdkWindowPrivate *window_private;
g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
window_private = (GdkWindowPrivate*) window;
return window_private->window_type;
}
gint
gdk_window_get_origin (GdkWindow *window,
gint *x,
gint *y)
{
GdkWindowPrivate *private;
gint return_val;
gint tx = 0;
gint ty = 0;
g_return_val_if_fail (window != NULL, 0);
private = (GdkWindowPrivate*) window;
if (!private->destroyed)
{
POINT pt;
pt.x = 0;
pt.y = 0;
ClientToScreen (private->xwindow, &pt);
tx = pt.x;
ty = pt.y;
return_val = 1;
}
else
return_val = 0;
if (x)
*x = tx;
if (y)
*y = ty;
GDK_NOTE (MISC, g_print ("gdk_window_get_origin: %#x: +%d+%d\n",
private->xwindow, tx, ty));
return return_val;
}
gboolean
gdk_window_get_deskrelative_origin (GdkWindow *window,
gint *x,
gint *y)
{
return gdk_window_get_origin (window, x, y);
}
void
gdk_window_get_root_origin (GdkWindow *window,
gint *x,
gint *y)
{
GdkWindowPrivate *private;
POINT pt;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (x)
*x = 0;
if (y)
*y = 0;
if (private->destroyed)
return;
while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
private = (GdkWindowPrivate*) private->parent;
if (private->destroyed)
return;
pt.x = 0;
pt.y = 0;
ClientToScreen (private->xwindow, &pt);
if (x)
*x = pt.x;
if (y)
*y = pt.y;
GDK_NOTE (MISC, g_print ("gdk_window_get_root_origin: %#x: (%#x) +%d+%d\n",
((GdkWindowPrivate *) window)->xwindow,
private->xwindow, pt.x, pt.y));
}
GdkWindow*
gdk_window_get_pointer (GdkWindow *window,
gint *x,
gint *y,
GdkModifierType *mask)
{
GdkWindowPrivate *private;
GdkWindow *return_val;
POINT pointc, point;
HWND hwnd, hwndc;
if (!window)
window = (GdkWindow*) &gdk_root_parent;
private = (GdkWindowPrivate*) window;
return_val = NULL;
GetCursorPos (&pointc);
point = pointc;
ScreenToClient (private->xwindow, &point);
if (x)
*x = point.x;
if (y)
*y = point.y;
hwnd = WindowFromPoint (point);
point = pointc;
ScreenToClient (hwnd, &point);
do {
hwndc = ChildWindowFromPoint (hwnd, point);
ClientToScreen (hwnd, &point);
ScreenToClient (hwndc, &point);
} while (hwndc != hwnd && (hwnd = hwndc, 1)); /* Ouch! */
return_val = gdk_window_lookup (hwnd);
if (mask)
{
BYTE kbd[256];
GetKeyboardState (kbd);
*mask = 0;
if (kbd[VK_SHIFT] & 0x80)
*mask |= GDK_SHIFT_MASK;
if (kbd[VK_CAPITAL] & 0x80)
*mask |= GDK_LOCK_MASK;
if (kbd[VK_CONTROL] & 0x80)
*mask |= GDK_CONTROL_MASK;
if (kbd[VK_MENU] & 0x80)
*mask |= GDK_MOD1_MASK;
if (kbd[VK_LBUTTON] & 0x80)
*mask |= GDK_BUTTON1_MASK;
if (kbd[VK_MBUTTON] & 0x80)
*mask |= GDK_BUTTON2_MASK;
if (kbd[VK_RBUTTON] & 0x80)
*mask |= GDK_BUTTON3_MASK;
}
return return_val;
}
GdkWindow*
gdk_window_at_pointer (gint *win_x,
gint *win_y)
{
GdkWindowPrivate *private;
GdkWindow *window;
POINT point, pointc;
HWND hwnd, hwndc;
RECT rect;
private = &gdk_root_parent;
GetCursorPos (&pointc);
point = pointc;
hwnd = WindowFromPoint (point);
if (hwnd == NULL)
{
window = (GdkWindow *) &gdk_root_parent;
if (win_x)
*win_x = pointc.x;
if (win_y)
*win_y = pointc.y;
return window;
}
ScreenToClient (hwnd, &point);
do {
hwndc = ChildWindowFromPoint (hwnd, point);
ClientToScreen (hwnd, &point);
ScreenToClient (hwndc, &point);
} while (hwndc != hwnd && (hwnd = hwndc, 1));
window = gdk_window_lookup (hwnd);
if (window && (win_x || win_y))
{
GetClientRect (hwnd, &rect);
if (win_x)
*win_x = point.x - rect.left;
if (win_y)
*win_y = point.y - rect.top;
}
GDK_NOTE (MISC, g_print ("gdk_window_at_pointer: +%d+%d %#x%s\n",
point.x, point.y, hwnd,
(window == NULL ? " NULL" : "")));
return window;
}
GdkWindow*
gdk_window_get_parent (GdkWindow *window)
{
g_return_val_if_fail (window != NULL, NULL);
return ((GdkWindowPrivate*) window)->parent;
}
GdkWindow*
gdk_window_get_toplevel (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_val_if_fail (window != NULL, NULL);
private = (GdkWindowPrivate*) window;
while (private->window_type == GDK_WINDOW_CHILD)
{
window = ((GdkWindowPrivate*) window)->parent;
private = (GdkWindowPrivate*) window;
}
return window;
}
GList*
gdk_window_get_children (GdkWindow *window)
{
GdkWindowPrivate *private;
GList *children;
g_return_val_if_fail (window != NULL, NULL);
private = (GdkWindowPrivate*) window;
if (private->destroyed)
return NULL;
/* XXX ??? */
g_warning ("gdk_window_get_children ???");
children = NULL;
return children;
}
GdkEventMask
gdk_window_get_events (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_val_if_fail (window != NULL, 0);
private = (GdkWindowPrivate*) window;
if (private->destroyed)
return 0;
return private->event_mask;
}
void
gdk_window_set_events (GdkWindow *window,
GdkEventMask event_mask)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (private->destroyed)
return;
private->event_mask = event_mask;
}
void
gdk_window_add_colormap_windows (GdkWindow *window)
{
g_warning ("gdk_window_add_colormap_windows not implemented"); /* XXX */
}
/*
* This needs the X11 shape extension.
* If not available, shaped windows will look
* ugly, but programs still work. Stefan Wille
*/
void
gdk_window_shape_combine_mask (GdkWindow *window,
GdkBitmap *mask,
gint x, gint y)
{
GdkWindowPrivate *window_private;
g_return_if_fail (window != NULL);
window_private = (GdkWindowPrivate*) window;
if (!mask)
{
GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x none\n",
window_private->xwindow));
SetWindowRgn (window_private->xwindow, NULL, TRUE);
}
else
{
GdkPixmapPrivate *pixmap_private;
HRGN hrgn;
DWORD dwStyle;
DWORD dwExStyle;
RECT rect;
/* Convert mask bitmap to region */
pixmap_private = (GdkPixmapPrivate*) mask;
hrgn = BitmapToRegion (pixmap_private->xwindow);
GDK_NOTE (MISC, g_print ("gdk_window_shape_combine_mask: %#x %#x\n",
window_private->xwindow,
pixmap_private->xwindow));
/* SetWindowRgn wants window (not client) coordinates */
dwStyle = GetWindowLong (window_private->xwindow, GWL_STYLE);
dwExStyle = GetWindowLong (window_private->xwindow, GWL_EXSTYLE);
GetClientRect (window_private->xwindow, &rect);
AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
OffsetRgn (hrgn, -rect.left, -rect.top);
OffsetRgn (hrgn, x, y);
/* If this is a top-level window, add the title bar to the region */
if (window_private->window_type == GDK_WINDOW_TOPLEVEL)
{
CombineRgn (hrgn, hrgn,
CreateRectRgn (0, 0, rect.right - rect.left, -rect.top),
RGN_OR);
}
SetWindowRgn (window_private->xwindow, hrgn, TRUE);
}
}
void
gdk_window_add_filter (GdkWindow *window,
GdkFilterFunc function,
gpointer data)
{
GdkWindowPrivate *private;
GList *tmp_list;
GdkEventFilter *filter;
private = (GdkWindowPrivate*) window;
if (private && private->destroyed)
return;
if (private)
tmp_list = private->filters;
else
tmp_list = gdk_default_filters;
while (tmp_list)
{
filter = (GdkEventFilter *)tmp_list->data;
if ((filter->function == function) && (filter->data == data))
return;
tmp_list = tmp_list->next;
}
filter = g_new (GdkEventFilter, 1);
filter->function = function;
filter->data = data;
if (private)
private->filters = g_list_append (private->filters, filter);
else
gdk_default_filters = g_list_append (gdk_default_filters, filter);
}
void
gdk_window_remove_filter (GdkWindow *window,
GdkFilterFunc function,
gpointer data)
{
GdkWindowPrivate *private;
GList *tmp_list, *node;
GdkEventFilter *filter;
private = (GdkWindowPrivate*) window;
if(private)
tmp_list = private->filters;
else
tmp_list = gdk_default_filters;
while (tmp_list)
{
filter = (GdkEventFilter *)tmp_list->data;
node = tmp_list;
tmp_list = tmp_list->next;
if ((filter->function == function) && (filter->data == data))
{
if(private)
private->filters = g_list_remove_link (private->filters, node);
else
gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list);
g_list_free_1 (node);
g_free (filter);
return;
}
}
}
void
gdk_window_set_override_redirect (GdkWindow *window,
gboolean override_redirect)
{
g_warning ("gdk_window_set_override_redirect not implemented"); /* XXX */
}
void
gdk_window_set_icon (GdkWindow *window,
GdkWindow *icon_window,
GdkPixmap *pixmap,
GdkBitmap *mask)
{
g_warning ("gdk_window_set_icon not implemented"); /* XXX */
}
void
gdk_window_set_icon_name (GdkWindow *window,
gchar *name)
{
GdkWindowPrivate *window_private;
g_return_if_fail (window != NULL);
window_private = (GdkWindowPrivate*) window;
if (window_private->destroyed)
return;
if (!SetWindowText (window_private->xwindow, name))
g_warning ("gdk_window_set_icon_name: SetWindowText failed");
}
void
gdk_window_set_group (GdkWindow *window,
GdkWindow *leader)
{
g_warning ("gdk_window_set_group not implemented"); /* XXX */
}
void
gdk_window_set_decorations (GdkWindow *window,
GdkWMDecoration decorations)
{
GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
LONG style, exstyle;
style = GetWindowLong (window_private->xwindow, GWL_STYLE);
exstyle = GetWindowLong (window_private->xwindow, GWL_EXSTYLE);
style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE);
exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
if (decorations & GDK_DECOR_ALL)
style |= (WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
if (decorations & GDK_DECOR_BORDER)
style |= (WS_BORDER);
if (decorations & GDK_DECOR_RESIZEH)
style |= (WS_THICKFRAME);
if (decorations & GDK_DECOR_TITLE)
style |= (WS_CAPTION);
if (decorations & GDK_DECOR_MENU)
style |= (WS_SYSMENU);
if (decorations & GDK_DECOR_MINIMIZE)
style |= (WS_MINIMIZEBOX);
if (decorations & GDK_DECOR_MAXIMIZE)
style |= (WS_MAXIMIZEBOX);
SetWindowLong (window_private->xwindow, GWL_STYLE, style);
}
void
gdk_window_set_functions (GdkWindow *window,
GdkWMFunction functions)
{
GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
LONG style, exstyle;
style = GetWindowLong (window_private->xwindow, GWL_STYLE);
exstyle = GetWindowLong (window_private->xwindow, GWL_EXSTYLE);
style &= (WS_OVERLAPPED|WS_POPUP|WS_CHILD|WS_MINIMIZE|WS_VISIBLE|WS_DISABLED
|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZE|WS_CAPTION|WS_BORDER
|WS_SYSMENU);
exstyle &= (WS_EX_TOPMOST|WS_EX_TRANSPARENT);
if (functions & GDK_FUNC_ALL)
style |= (WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
if (functions & GDK_FUNC_RESIZE)
style |= (WS_THICKFRAME);
if (functions & GDK_FUNC_MOVE)
style |= (WS_THICKFRAME);
if (functions & GDK_FUNC_MINIMIZE)
style |= (WS_MINIMIZEBOX);
if (functions & GDK_FUNC_MAXIMIZE)
style |= (WS_MAXIMIZEBOX);
SetWindowLong (window_private->xwindow, GWL_STYLE, style);
}
GList *
gdk_window_get_toplevels (void)
{
GList *new_list = NULL;
GList *tmp_list;
tmp_list = gdk_root_parent.children;
while (tmp_list)
{
new_list = g_list_prepend (new_list, tmp_list->data);
tmp_list = tmp_list->next;
}
return new_list;
}
/*
* propagate the shapes from all child windows of a GDK window to the parent
* window. Shamelessly ripped from Enlightenment's code
*
* - Raster
*/
static void
QueryTree (HWND hwnd,
HWND **children,
gint *nchildren)
{
guint i, n;
HWND child;
n = 0;
do {
if (n == 0)
child = GetWindow (hwnd, GW_CHILD);
else
child = GetWindow (child, GW_HWNDNEXT);
if (child != NULL)
n++;
} while (child != NULL);
if (n > 0)
{
*children = g_new (HWND, n);
for (i = 0; i < n; i++)
{
if (i == 0)
child = GetWindow (hwnd, GW_CHILD);
else
child = GetWindow (child, GW_HWNDNEXT);
*children[i] = child;
}
}
}
static void
gdk_propagate_shapes (HANDLE win,
gboolean merge)
{
RECT emptyRect;
HRGN region, childRegion;
RECT rect;
HWND *list = NULL;
gint i, num;
SetRectEmpty (&emptyRect);
region = CreateRectRgnIndirect (&emptyRect);
if (merge)
GetWindowRgn (win, region);
QueryTree (win, &list, &num);
if (list != NULL)
{
WINDOWPLACEMENT placement;
placement.length = sizeof (WINDOWPLACEMENT);
/* go through all child windows and combine regions */
for (i = 0; i < num; i++)
{
GetWindowPlacement (list[i], &placement);
if (placement.showCmd = SW_SHOWNORMAL)
{
childRegion = CreateRectRgnIndirect (&emptyRect);
GetWindowRgn (list[i], childRegion);
CombineRgn (region, region, childRegion, RGN_OR);
DeleteObject (childRegion);
}
}
SetWindowRgn (win, region, TRUE);
}
else
DeleteObject (region);
}
void
gdk_window_set_child_shapes (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (private->destroyed)
return;
gdk_propagate_shapes ( private->xwindow, FALSE);
}
void
gdk_window_merge_child_shapes (GdkWindow *window)
{
GdkWindowPrivate *private;
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
if (private->destroyed)
return;
gdk_propagate_shapes (private->xwindow, TRUE);
}
/*************************************************************
* gdk_window_is_visible:
* Check if the given window is mapped.
* arguments:
* window:
* results:
* is the window mapped
*************************************************************/
gboolean
gdk_window_is_visible (GdkWindow *window)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
g_return_val_if_fail (window != NULL, FALSE);
return private->mapped;
}
/*************************************************************
* gdk_window_is_viewable:
* Check if the window and all ancestors of the window
* are mapped. (This is not necessarily "viewable" in
* the X sense, since we only check as far as we have
* GDK window parents, not to the root window)
* arguments:
* window:
* results:
* is the window viewable
*************************************************************/
gboolean
gdk_window_is_viewable (GdkWindow *window)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
g_return_val_if_fail (window != NULL, FALSE);
while (private &&
(private != &gdk_root_parent) &&
(private->window_type != GDK_WINDOW_FOREIGN))
{
if (!private->mapped)
return FALSE;
private = (GdkWindowPrivate *)private->parent;
}
return TRUE;
}
void
gdk_drawable_set_data (GdkDrawable *drawable,
const gchar *key,
gpointer data,
GDestroyNotify destroy_func)
{
g_dataset_set_data_full (drawable, key, data, destroy_func);
}
/* Support for windows that can be guffaw-scrolled
* (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
*/
static gboolean
gdk_window_gravity_works (void)
{
enum { UNKNOWN, NO, YES };
static gint gravity_works = UNKNOWN;
if (gravity_works == UNKNOWN)
{
GdkWindowAttr attr;
GdkWindow *parent;
GdkWindow *child;
gint y;
attr.window_type = GDK_WINDOW_TEMP;
attr.wclass = GDK_INPUT_OUTPUT;
attr.x = 0;
attr.y = 0;
attr.width = 100;
attr.height = 100;
attr.event_mask = 0;
parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
attr.window_type = GDK_WINDOW_CHILD;
child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
gdk_window_set_static_win_gravity (child, TRUE);
gdk_window_resize (parent, 100, 110);
gdk_window_move (parent, 0, -10);
gdk_window_move_resize (parent, 0, 0, 100, 100);
gdk_window_resize (parent, 100, 110);
gdk_window_move (parent, 0, -10);
gdk_window_move_resize (parent, 0, 0, 100, 100);
gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
gdk_window_destroy (parent);
gdk_window_destroy (child);
gravity_works = ((y == -20) ? YES : NO);
}
return (gravity_works == YES);
}
static void
gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
g_return_if_fail (window != NULL);
GDK_NOTE (MISC,
g_print ("gdk_window_set_static_bit_gravity: Not implemented\n"));
}
static void
gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
g_return_if_fail (window != NULL);
GDK_NOTE (MISC,
g_print ("gdk_window_set_static_win_gravity: Not implemented\n"));
}
/*************************************************************
* gdk_window_set_static_gravities:
* Set the bit gravity of the given window to static,
* and flag it so all children get static subwindow
* gravity.
* arguments:
* window: window for which to set static gravity
* use_static: Whether to turn static gravity on or off.
* results:
* Does the XServer support static gravity?
*************************************************************/
gboolean
gdk_window_set_static_gravities (GdkWindow *window,
gboolean use_static)
{
GdkWindowPrivate *private = (GdkWindowPrivate *)window;
GList *tmp_list;
g_return_val_if_fail (window != NULL, FALSE);
if (!use_static == !private->guffaw_gravity)
return TRUE;
if (use_static && !gdk_window_gravity_works ())
return FALSE;
private->guffaw_gravity = use_static;
gdk_window_set_static_bit_gravity (window, use_static);
tmp_list = private->children;
while (tmp_list)
{
gdk_window_set_static_win_gravity (window, use_static);
tmp_list = tmp_list->next;
}
return TRUE;
}