mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-28 06:21:14 +00:00
7405177690
2004-08-06 Hans Breuer <hans@breuer.org> * gdk/win32/gdkwindow-win32.c : make it compile and more similar to the X11 implementation [backward compatibility for GDK_WINDOW_TEMP, GDK_INPUT_ONLY (fixes bug #148702), use the *screen* function variants, dont reparent already destroyed] (get_visible_region) : take the win32 part into account (_gdk_windowing_window_destroy) : remove from handle table * gdk/win32/gdkdisplay-win32.c : added gdk_display_(request|supports)_selection_notification () with a currently mostly pointless implementation ;-) * gtk/gtkfilesystemwin32.c (*_to_path) : same changes as on *NIX, plugs memory leak (gtk_file_system_win32_render_icon) : use new GTK_STOCK_DIRECTORY * gtk/makefile.msc.in demos/gtk-demo/makefile.msc.in gtk/stock-icons/makefile.msc tests/makefile.msc : updated * gdk/gdk.def gtk/gtk.def : updated externals * tests/testiconview.c : remove unneeded dirent.h inclusion
372 lines
9.9 KiB
C
372 lines
9.9 KiB
C
/* GDK - The GIMP Drawing Kit
|
|
* Copyright (C) 2002 Hans Breuer
|
|
* Copyright (C) 2003 Tor Lillqvist
|
|
*
|
|
* 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., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include "gdk.h"
|
|
#include "gdkprivate-win32.h"
|
|
|
|
#define HAVE_MONITOR_INFO
|
|
|
|
#if defined(_MSC_VER) && (WINVER < 0x500) && (WINVER > 0x0400)
|
|
#include <multimon.h>
|
|
#elif defined(_MSC_VER) && (WINVER <= 0x0400)
|
|
#undef HAVE_MONITOR_INFO
|
|
#endif
|
|
|
|
#ifdef HAVE_MONITOR_INFO
|
|
typedef BOOL (WINAPI *t_EnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
|
|
typedef BOOL (WINAPI *t_GetMonitorInfoA)(HMONITOR, LPMONITORINFO);
|
|
|
|
static t_EnumDisplayMonitors p_EnumDisplayMonitors = NULL;
|
|
static t_GetMonitorInfoA p_GetMonitorInfoA = NULL;
|
|
#endif
|
|
|
|
void
|
|
_gdk_windowing_set_default_display (GdkDisplay *display)
|
|
{
|
|
g_assert (_gdk_display == display);
|
|
}
|
|
|
|
#ifdef HAVE_MONITOR_INFO
|
|
static BOOL CALLBACK
|
|
count_monitor (HMONITOR hmonitor,
|
|
HDC hdc,
|
|
LPRECT rect,
|
|
LPARAM data)
|
|
{
|
|
gint *n = (gint *) data;
|
|
|
|
(*n)++;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL CALLBACK
|
|
enum_monitor (HMONITOR hmonitor,
|
|
HDC hdc,
|
|
LPRECT rect,
|
|
LPARAM data)
|
|
{
|
|
MONITORINFOEX monitor_info;
|
|
|
|
gint *index = (gint *) data;
|
|
GdkRectangle *monitor;
|
|
|
|
g_assert (*index < _gdk_num_monitors);
|
|
|
|
monitor = _gdk_monitors + *index;
|
|
|
|
monitor_info.cbSize = sizeof (MONITORINFOEX);
|
|
(*p_GetMonitorInfoA) (hmonitor, (MONITORINFO *) &monitor_info);
|
|
|
|
#ifndef MONITORINFOF_PRIMARY
|
|
#define MONITORINFOF_PRIMARY 1
|
|
#endif
|
|
|
|
if (monitor_info.dwFlags & MONITORINFOF_PRIMARY)
|
|
{
|
|
/* For the primary monitor, use SPI_GETWORKAREA */
|
|
RECT rect;
|
|
|
|
SystemParametersInfo (SPI_GETWORKAREA, 0, &rect, 0);
|
|
monitor->x = rect.left;
|
|
monitor->y = rect.top;
|
|
monitor->width = rect.right - rect.left;
|
|
monitor->height = rect.bottom - rect.top;
|
|
|
|
/* Put primary monitor at index 0, just in case somebody needs
|
|
* to know which one is the primary.
|
|
*/
|
|
if (*index != 0)
|
|
{
|
|
GdkRectangle temp = *monitor;
|
|
*monitor = _gdk_monitors[0];
|
|
_gdk_monitors[0] = temp;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
monitor->x = monitor_info.rcMonitor.left;
|
|
monitor->y = monitor_info.rcMonitor.top;
|
|
monitor->width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
|
|
monitor->height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
|
|
}
|
|
|
|
(*index)++;
|
|
|
|
return TRUE;
|
|
}
|
|
#endif /* HAVE_MONITOR_INFO */
|
|
|
|
GdkDisplay *
|
|
gdk_display_open (const gchar *display_name)
|
|
{
|
|
HMODULE user32;
|
|
|
|
if (_gdk_display != NULL)
|
|
return NULL; /* single display only */
|
|
|
|
_gdk_display = g_object_new (GDK_TYPE_DISPLAY, NULL);
|
|
_gdk_screen = g_object_new (GDK_TYPE_SCREEN, NULL);
|
|
|
|
#ifdef HAVE_MONITOR_INFO
|
|
user32 = GetModuleHandle ("user32.dll");
|
|
g_assert (user32 != NULL);
|
|
|
|
p_EnumDisplayMonitors = (t_EnumDisplayMonitors) GetProcAddress (user32, "EnumDisplayMonitors");
|
|
p_GetMonitorInfoA = (t_GetMonitorInfoA) GetProcAddress (user32, "GetMonitorInfoA");
|
|
|
|
if (p_EnumDisplayMonitors != NULL && p_GetMonitorInfoA != NULL)
|
|
{
|
|
gint i, index;
|
|
|
|
_gdk_num_monitors = 0;
|
|
|
|
(*p_EnumDisplayMonitors) (NULL, NULL, count_monitor, (LPARAM) &_gdk_num_monitors);
|
|
|
|
_gdk_monitors = g_new (GdkRectangle, _gdk_num_monitors);
|
|
index = 0;
|
|
(*p_EnumDisplayMonitors) (NULL, NULL, enum_monitor, (LPARAM) &index);
|
|
#if 1
|
|
_gdk_offset_x = G_MININT;
|
|
_gdk_offset_y = G_MININT;
|
|
|
|
/* Calculate offset */
|
|
for (i = 0; i < _gdk_num_monitors; i++)
|
|
{
|
|
_gdk_offset_x = MAX (_gdk_offset_x, -_gdk_monitors[i].x);
|
|
_gdk_offset_y = MAX (_gdk_offset_y, -_gdk_monitors[i].y);
|
|
}
|
|
GDK_NOTE (MISC, g_print ("Multi-monitor offset: (%d,%d)\n",
|
|
_gdk_offset_x, _gdk_offset_y));
|
|
|
|
/* Translate monitor coords into GDK coordinate space */
|
|
for (i = 0; i < _gdk_num_monitors; i++)
|
|
{
|
|
_gdk_monitors[i].x += _gdk_offset_x;
|
|
_gdk_monitors[i].y += _gdk_offset_y;
|
|
GDK_NOTE (MISC, g_print ("Monitor %d: %dx%d@+%d+%d\n",
|
|
i, _gdk_monitors[i].width,
|
|
_gdk_monitors[i].height,
|
|
_gdk_monitors[i].x, _gdk_monitors[i].y));
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
#endif /* HAVE_MONITOR_INFO */
|
|
{
|
|
RECT rect;
|
|
|
|
_gdk_num_monitors = 1;
|
|
_gdk_monitors = g_new (GdkRectangle, 1);
|
|
SystemParametersInfo (SPI_GETWORKAREA, 0, &rect, 0);
|
|
_gdk_monitors[0].x = rect.left;
|
|
_gdk_monitors[0].y = rect.top;
|
|
_gdk_monitors[0].width = rect.right - rect.left;
|
|
_gdk_monitors[0].height = rect.bottom - rect.top;
|
|
_gdk_offset_x = 0;
|
|
_gdk_offset_y = 0;
|
|
}
|
|
|
|
_gdk_visual_init ();
|
|
gdk_screen_set_default_colormap (_gdk_screen,
|
|
gdk_screen_get_system_colormap (_gdk_screen));
|
|
_gdk_windowing_window_init ();
|
|
_gdk_windowing_image_init ();
|
|
_gdk_events_init ();
|
|
_gdk_input_init (_gdk_display);
|
|
_gdk_dnd_init ();
|
|
|
|
g_signal_emit_by_name (gdk_display_manager_get (),
|
|
"display_opened", _gdk_display);
|
|
|
|
return _gdk_display;
|
|
}
|
|
|
|
G_CONST_RETURN gchar *
|
|
gdk_display_get_name (GdkDisplay *display)
|
|
{
|
|
return gdk_get_display_arg_name ();
|
|
}
|
|
|
|
gint
|
|
gdk_display_get_n_screens (GdkDisplay *display)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
GdkScreen *
|
|
gdk_display_get_screen (GdkDisplay *display,
|
|
gint screen_num)
|
|
{
|
|
return _gdk_screen;
|
|
}
|
|
|
|
GdkScreen *
|
|
gdk_display_get_default_screen (GdkDisplay *display)
|
|
{
|
|
return _gdk_screen;
|
|
}
|
|
|
|
GdkWindow *
|
|
gdk_display_get_default_group (GdkDisplay *display)
|
|
{
|
|
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
|
|
|
g_warning ("gdk_display_get_default_group not yet implemented");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
gboolean
|
|
gdk_display_supports_selection_notification (GdkDisplay *display)
|
|
{
|
|
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static HWND _hwnd_next_viewer = NULL;
|
|
|
|
/*
|
|
* maybe this should be integrated with the default message loop - or maybe not ;-)
|
|
*/
|
|
static LRESULT CALLBACK
|
|
_win32_on_clipboard_change (HWND hwnd,
|
|
UINT message,
|
|
WPARAM wparam,
|
|
LPARAM lparam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_DESTROY : /* remove us from chain */
|
|
{
|
|
ChangeClipboardChain (hwnd, _hwnd_next_viewer);
|
|
return 0;
|
|
}
|
|
case WM_CHANGECBCHAIN :
|
|
{
|
|
HWND hwndRemove = (HWND) wparam; /* handle of window being removed */
|
|
HWND hwndNext = (HWND) lparam; /* handle of next window in chain */
|
|
if (hwndRemove == _hwnd_next_viewer)
|
|
_hwnd_next_viewer = hwndNext == hwnd ? NULL : hwndNext;
|
|
return 0;
|
|
}
|
|
case WM_DRAWCLIPBOARD :
|
|
{
|
|
/* create the appropriate gdk events */
|
|
HWND hwndOwner = GetClipboardOwner ();
|
|
UINT nFormat = 0;
|
|
int n = 0;
|
|
|
|
if (OpenClipboard (hwnd))
|
|
{
|
|
for (; 0 != (nFormat = EnumClipboardFormats (nFormat)); )
|
|
{
|
|
char sFormat[80];
|
|
if (GetClipboardFormatName (nFormat, sFormat, 80) > 0)
|
|
g_print ("%s ", sFormat);
|
|
n++; /* do something useful ? */
|
|
}
|
|
GDK_NOTE (DND,
|
|
g_print ("WM_DRAWCLIPBOARD : formats %d owner %#lx\n", n, hwndOwner));
|
|
|
|
CloseClipboard ();
|
|
}
|
|
/* XXX: generate the apropriate GdkEventOwnerChange ... */
|
|
|
|
/* don't break the chain */
|
|
return PostMessage (_hwnd_next_viewer, message, wparam, lparam);
|
|
}
|
|
default :
|
|
return DefWindowProc (hwnd, message, wparam, lparam);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Creates a hidden window and adds it to the clipboard chain
|
|
*/
|
|
HWND
|
|
_gdk_win32_register_clipboard_notification (void)
|
|
{
|
|
WNDCLASS wclass;
|
|
HWND hwnd;
|
|
ATOM klass;
|
|
|
|
memset (&wclass, 0, sizeof(WNDCLASS));
|
|
wclass.lpszClassName = "GdkClipboardNotification";
|
|
wclass.lpfnWndProc = _win32_on_clipboard_change;
|
|
wclass.hInstance = _gdk_app_hmodule;
|
|
|
|
klass = RegisterClass (&wclass);
|
|
if (!klass)
|
|
return NULL;
|
|
|
|
hwnd = CreateWindow (MAKEINTRESOURCE(klass),
|
|
NULL, WS_POPUP,
|
|
0, 0, 0, 0, NULL, NULL,
|
|
_gdk_app_hmodule, NULL);
|
|
if (!hwnd)
|
|
{
|
|
UnregisterClass (MAKEINTRESOURCE(klass), _gdk_app_hmodule);
|
|
return NULL;
|
|
}
|
|
_hwnd_next_viewer = SetClipboardViewer (hwnd);
|
|
return hwnd;
|
|
}
|
|
|
|
/*
|
|
* The whole function would only make sense if the gdk/win32 clipboard
|
|
* model is rewritten to do delayed rendering. Currently this is only
|
|
* testcode and as noted in
|
|
* http://mail.gnome.org/archives/gtk-devel-list/2004-May/msg00113.html
|
|
* probably not worth bothering ;)
|
|
*/
|
|
gboolean
|
|
gdk_display_request_selection_notification (GdkDisplay *display,
|
|
GdkAtom selection)
|
|
|
|
{
|
|
static HWND hwndViewer = NULL;
|
|
gboolean ret = FALSE;
|
|
|
|
GDK_NOTE (DND,
|
|
g_print ("gdk_display_request_selection_notification (..., %s)",
|
|
gdk_atom_name (selection)));
|
|
|
|
if (GDK_SELECTION_CLIPBOARD == selection)
|
|
{
|
|
if (!hwndViewer)
|
|
{
|
|
hwndViewer = _gdk_win32_register_clipboard_notification ();
|
|
GDK_NOTE (DND, g_print (" registered"));
|
|
}
|
|
ret = (hwndViewer != NULL);
|
|
}
|
|
else if (GDK_SELECTION_PRIMARY == selection)
|
|
{
|
|
/* seems to work by default ? */
|
|
GDK_NOTE (DND, g_print (" by default"));
|
|
ret = TRUE;
|
|
}
|
|
GDK_NOTE (DND, g_print (" -> %s\n", ret ? "TRUE" : "FALSE"));
|
|
return ret;
|
|
}
|