forked from AuroraMiddleware/gtk
6b9e481e38
... and gdk_screen_get_window_stack().
Those functions were originally added in
5afb4f0f11
but do not seem to be used as
they are not implemented anywhere but in X.
As GDK is not meant to fulfill window management functionality I'm going
to remove these functions without replacements.
544 lines
15 KiB
C
544 lines
15 KiB
C
/* GDK - The GIMP Drawing Kit
|
|
* Copyright (C) 2002 Hans Breuer
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "gdk.h"
|
|
#include "gdkprivate-win32.h"
|
|
#include "gdkscreenprivate.h"
|
|
#include "gdkwin32screen.h"
|
|
#include "gdkdisplayprivate.h"
|
|
#include "gdkvisualprivate.h"
|
|
#include "gdkdisplay-win32.h"
|
|
#include "gdkmonitor-win32.h"
|
|
|
|
#include <dwmapi.h>
|
|
|
|
struct _GdkWin32Screen
|
|
{
|
|
GdkScreen parent_instance;
|
|
|
|
GdkVisual *system_visual;
|
|
GdkVisual *rgba_visual;
|
|
gint available_visual_depths[1];
|
|
GdkVisualType available_visual_types[1];
|
|
|
|
GdkWindow *root_window;
|
|
|
|
gint always_composited : 1;
|
|
};
|
|
|
|
struct _GdkWin32ScreenClass
|
|
{
|
|
GdkScreenClass parent_class;
|
|
};
|
|
|
|
G_DEFINE_TYPE (GdkWin32Screen, gdk_win32_screen, GDK_TYPE_SCREEN)
|
|
|
|
static gint
|
|
get_color_precision (gulong mask)
|
|
{
|
|
gint p = 0;
|
|
|
|
while (mask & 0x1)
|
|
{
|
|
p++;
|
|
mask >>= 1;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
static GdkVisual *
|
|
init_visual (GdkScreen *screen,
|
|
gboolean is_rgba)
|
|
{
|
|
GdkVisual *visual;
|
|
struct
|
|
{
|
|
BITMAPINFOHEADER bi;
|
|
union
|
|
{
|
|
RGBQUAD colors[256];
|
|
DWORD fields[256];
|
|
} u;
|
|
} bmi;
|
|
HBITMAP hbm;
|
|
|
|
const gint rastercaps = GetDeviceCaps (_gdk_display_hdc, RASTERCAPS);
|
|
const int numcolors = GetDeviceCaps (_gdk_display_hdc, NUMCOLORS);
|
|
gint bitspixel = GetDeviceCaps (_gdk_display_hdc, BITSPIXEL);
|
|
gint map_entries = 0;
|
|
|
|
visual = g_object_new (GDK_TYPE_VISUAL, NULL);
|
|
visual->screen = screen;
|
|
|
|
if (rastercaps & RC_PALETTE)
|
|
{
|
|
const int sizepalette = GetDeviceCaps (_gdk_display_hdc, SIZEPALETTE);
|
|
gchar *max_colors = getenv ("GDK_WIN32_MAX_COLORS");
|
|
visual->type = GDK_VISUAL_PSEUDO_COLOR;
|
|
|
|
g_assert (sizepalette == 256);
|
|
|
|
if (max_colors != NULL)
|
|
_gdk_max_colors = atoi (max_colors);
|
|
|
|
map_entries = _gdk_max_colors;
|
|
|
|
if (map_entries >= 16 && map_entries < sizepalette)
|
|
{
|
|
if (map_entries < 32)
|
|
{
|
|
map_entries = 16;
|
|
visual->type = GDK_VISUAL_STATIC_COLOR;
|
|
bitspixel = 4;
|
|
}
|
|
else if (map_entries < 64)
|
|
{
|
|
map_entries = 32;
|
|
bitspixel = 5;
|
|
}
|
|
else if (map_entries < 128)
|
|
{
|
|
map_entries = 64;
|
|
bitspixel = 6;
|
|
}
|
|
else if (map_entries < 256)
|
|
{
|
|
map_entries = 128;
|
|
bitspixel = 7;
|
|
}
|
|
else
|
|
g_assert_not_reached ();
|
|
}
|
|
else
|
|
map_entries = sizepalette;
|
|
}
|
|
else if (bitspixel == 1 && numcolors == 16)
|
|
{
|
|
bitspixel = 4;
|
|
visual->type = GDK_VISUAL_STATIC_COLOR;
|
|
map_entries = 16;
|
|
}
|
|
else if (bitspixel == 1)
|
|
{
|
|
visual->type = GDK_VISUAL_STATIC_GRAY;
|
|
map_entries = 2;
|
|
}
|
|
else if (bitspixel == 4)
|
|
{
|
|
visual->type = GDK_VISUAL_STATIC_COLOR;
|
|
map_entries = 16;
|
|
}
|
|
else if (bitspixel == 8)
|
|
{
|
|
visual->type = GDK_VISUAL_STATIC_COLOR;
|
|
map_entries = 256;
|
|
}
|
|
else if (bitspixel == 16)
|
|
{
|
|
visual->type = GDK_VISUAL_TRUE_COLOR;
|
|
#if 1
|
|
/* This code by Mike Enright,
|
|
* see http://www.users.cts.com/sd/m/menright/display.html
|
|
*/
|
|
memset (&bmi, 0, sizeof (bmi));
|
|
bmi.bi.biSize = sizeof (bmi.bi);
|
|
|
|
hbm = CreateCompatibleBitmap (_gdk_display_hdc, 1, 1);
|
|
GetDIBits (_gdk_display_hdc, hbm, 0, 1, NULL,
|
|
(BITMAPINFO *) &bmi, DIB_RGB_COLORS);
|
|
GetDIBits (_gdk_display_hdc, hbm, 0, 1, NULL,
|
|
(BITMAPINFO *) &bmi, DIB_RGB_COLORS);
|
|
DeleteObject (hbm);
|
|
|
|
if (bmi.bi.biCompression != BI_BITFIELDS)
|
|
{
|
|
/* Either BI_RGB or BI_RLE_something
|
|
* .... or perhaps (!!) something else.
|
|
* Theoretically biCompression might be
|
|
* mmioFourCC('c','v','i','d') but I doubt it.
|
|
*/
|
|
if (bmi.bi.biCompression == BI_RGB)
|
|
{
|
|
/* It's 555 */
|
|
bitspixel = 15;
|
|
visual->red_mask = 0x00007C00;
|
|
visual->green_mask = 0x000003E0;
|
|
visual->blue_mask = 0x0000001F;
|
|
}
|
|
else
|
|
{
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DWORD allmasks =
|
|
bmi.u.fields[0] | bmi.u.fields[1] | bmi.u.fields[2];
|
|
int k = 0;
|
|
while (allmasks)
|
|
{
|
|
if (allmasks&1)
|
|
k++;
|
|
allmasks/=2;
|
|
}
|
|
bitspixel = k;
|
|
visual->red_mask = bmi.u.fields[0];
|
|
visual->green_mask = bmi.u.fields[1];
|
|
visual->blue_mask = bmi.u.fields[2];
|
|
}
|
|
#else
|
|
/* Old, incorrect (but still working) code. */
|
|
#if 0
|
|
visual->red_mask = 0x0000F800;
|
|
visual->green_mask = 0x000007E0;
|
|
visual->blue_mask = 0x0000001F;
|
|
#else
|
|
visual->red_mask = 0x00007C00;
|
|
visual->green_mask = 0x000003E0;
|
|
visual->blue_mask = 0x0000001F;
|
|
#endif
|
|
#endif
|
|
}
|
|
else if (bitspixel == 24 || bitspixel == 32)
|
|
{
|
|
if (!is_rgba)
|
|
bitspixel = 24;
|
|
visual->type = GDK_VISUAL_TRUE_COLOR;
|
|
visual->red_mask = 0x00FF0000;
|
|
visual->green_mask = 0x0000FF00;
|
|
visual->blue_mask = 0x000000FF;
|
|
}
|
|
else
|
|
g_error ("_gdk_visual_init: unsupported BITSPIXEL: %d\n", bitspixel);
|
|
|
|
visual->depth = bitspixel;
|
|
visual->byte_order = GDK_LSB_FIRST;
|
|
visual->bits_per_rgb = 42; /* Not used? */
|
|
|
|
if ((visual->type != GDK_VISUAL_TRUE_COLOR) &&
|
|
(visual->type != GDK_VISUAL_DIRECT_COLOR))
|
|
{
|
|
visual->red_mask = 0;
|
|
visual->green_mask = 0;
|
|
visual->blue_mask = 0;
|
|
}
|
|
else
|
|
map_entries = 1 << (MAX (get_color_precision (visual->red_mask),
|
|
MAX (get_color_precision (visual->green_mask),
|
|
get_color_precision (visual->blue_mask))));
|
|
|
|
visual->colormap_size = map_entries;
|
|
|
|
return visual;
|
|
}
|
|
|
|
static gboolean
|
|
init_root_window_size (GdkWin32Screen *screen)
|
|
{
|
|
GdkRectangle result;
|
|
int i;
|
|
GdkDisplay *display = _gdk_display;
|
|
int monitor_count;
|
|
GdkMonitor *monitor;
|
|
gboolean changed;
|
|
|
|
monitor_count = gdk_display_get_n_monitors (display);
|
|
monitor = gdk_display_get_monitor (display, 0);
|
|
gdk_monitor_get_geometry (monitor, &result);
|
|
|
|
for (i = 1; i < monitor_count; i++)
|
|
{
|
|
GdkRectangle rect;
|
|
|
|
monitor = gdk_display_get_monitor (display, i);
|
|
gdk_monitor_get_geometry (monitor, &rect);
|
|
gdk_rectangle_union (&result, &rect, &result);
|
|
}
|
|
|
|
changed = screen->root_window->width != result.width ||
|
|
screen->root_window->height != result.height;
|
|
screen->root_window->width = result.width;
|
|
screen->root_window->height = result.height;
|
|
|
|
return changed;
|
|
}
|
|
|
|
static gboolean
|
|
init_root_window (GdkWin32Screen *screen_win32)
|
|
{
|
|
GdkScreen *screen;
|
|
GdkWindow *window;
|
|
GdkWindowImplWin32 *impl_win32;
|
|
gboolean changed;
|
|
|
|
screen = GDK_SCREEN (screen_win32);
|
|
|
|
g_assert (screen_win32->root_window == NULL);
|
|
|
|
window = _gdk_display_create_window (_gdk_display);
|
|
window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WIN32, NULL);
|
|
impl_win32 = GDK_WINDOW_IMPL_WIN32 (window->impl);
|
|
impl_win32->wrapper = window;
|
|
|
|
window->impl_window = window;
|
|
window->visual = gdk_screen_get_system_visual (screen);
|
|
|
|
window->window_type = GDK_WINDOW_ROOT;
|
|
window->depth = window->visual->depth;
|
|
|
|
screen_win32->root_window = window;
|
|
|
|
changed = init_root_window_size (screen_win32);
|
|
|
|
window->x = 0;
|
|
window->y = 0;
|
|
window->abs_x = 0;
|
|
window->abs_y = 0;
|
|
/* width and height already initialised in init_root_window_size() */
|
|
window->viewable = TRUE;
|
|
|
|
gdk_win32_handle_table_insert ((HANDLE *) &impl_win32->handle, window);
|
|
|
|
GDK_NOTE (MISC, g_print ("screen->root_window=%p\n", window));
|
|
|
|
return changed;
|
|
}
|
|
|
|
static void
|
|
gdk_win32_screen_init (GdkWin32Screen *win32_screen)
|
|
{
|
|
GdkScreen *screen = GDK_SCREEN (win32_screen);
|
|
HDC screen_dc;
|
|
int logpixelsx = -1;
|
|
const gchar *font_resolution;
|
|
|
|
screen_dc = GetDC (NULL);
|
|
|
|
if (screen_dc)
|
|
{
|
|
logpixelsx = GetDeviceCaps(screen_dc, LOGPIXELSX);
|
|
ReleaseDC (NULL, screen_dc);
|
|
}
|
|
|
|
font_resolution = g_getenv ("GDK_WIN32_FONT_RESOLUTION");
|
|
if (font_resolution)
|
|
{
|
|
int env_logpixelsx = atol (font_resolution);
|
|
if (env_logpixelsx > 0)
|
|
logpixelsx = env_logpixelsx;
|
|
}
|
|
|
|
if (logpixelsx > 0)
|
|
_gdk_screen_set_resolution (screen, logpixelsx);
|
|
|
|
win32_screen->system_visual = init_visual (screen, FALSE);
|
|
win32_screen->rgba_visual = init_visual (screen, TRUE);
|
|
|
|
win32_screen->available_visual_depths[0] = win32_screen->rgba_visual->depth;
|
|
win32_screen->available_visual_types[0] = win32_screen->rgba_visual->type;
|
|
|
|
_gdk_win32_display_init_monitors (GDK_WIN32_DISPLAY (_gdk_display));
|
|
init_root_window (win32_screen);
|
|
|
|
/* On Windows 8 and later, DWM (composition) is always enabled */
|
|
win32_screen->always_composited = g_win32_check_windows_version (6, 2, 0, G_WIN32_OS_ANY);
|
|
}
|
|
|
|
void
|
|
_gdk_win32_screen_on_displaychange_event (GdkWin32Screen *screen)
|
|
{
|
|
gboolean monitors_changed;
|
|
|
|
monitors_changed = _gdk_win32_display_init_monitors (GDK_WIN32_DISPLAY (_gdk_display));
|
|
|
|
if (init_root_window_size (screen))
|
|
g_signal_emit_by_name (screen, "size-changed");
|
|
|
|
if (monitors_changed)
|
|
g_signal_emit_by_name (screen, "monitors-changed");
|
|
}
|
|
|
|
static GdkDisplay *
|
|
gdk_win32_screen_get_display (GdkScreen *screen)
|
|
{
|
|
return _gdk_display;
|
|
}
|
|
|
|
static GdkWindow *
|
|
gdk_win32_screen_get_root_window (GdkScreen *screen)
|
|
{
|
|
return GDK_WIN32_SCREEN (screen)->root_window;
|
|
}
|
|
|
|
static gchar *
|
|
gdk_win32_screen_make_display_name (GdkScreen *screen)
|
|
{
|
|
return g_strdup (gdk_display_get_name (_gdk_display));
|
|
}
|
|
|
|
static gboolean
|
|
gdk_win32_screen_is_composited (GdkScreen *screen)
|
|
{
|
|
if (GDK_WIN32_SCREEN (screen)->always_composited)
|
|
return TRUE;
|
|
else
|
|
{
|
|
gboolean is_composited;
|
|
|
|
if (DwmIsCompositionEnabled (&is_composited) != S_OK)
|
|
return FALSE;
|
|
return is_composited;
|
|
}
|
|
}
|
|
|
|
static gint
|
|
gdk_win32_screen_visual_get_best_depth (GdkScreen *screen)
|
|
{
|
|
return GDK_WIN32_SCREEN (screen)->available_visual_depths[0];
|
|
}
|
|
|
|
static GdkVisualType
|
|
gdk_win32_screen_visual_get_best_type (GdkScreen *screen)
|
|
{
|
|
return GDK_WIN32_SCREEN (screen)->available_visual_types[0];
|
|
}
|
|
|
|
static GdkVisual *
|
|
gdk_win32_screen_get_system_visual (GdkScreen *screen)
|
|
{
|
|
return GDK_WIN32_SCREEN (screen)->system_visual;
|
|
}
|
|
|
|
static GdkVisual *
|
|
gdk_win32_screen_get_rgba_visual (GdkScreen *screen)
|
|
{
|
|
return GDK_WIN32_SCREEN (screen)->rgba_visual;
|
|
}
|
|
|
|
static GdkVisual*
|
|
gdk_win32_screen_visual_get_best (GdkScreen *screen)
|
|
{
|
|
return GDK_WIN32_SCREEN (screen)->rgba_visual;
|
|
}
|
|
|
|
static GdkVisual *
|
|
gdk_win32_screen_visual_get_best_with_depth (GdkScreen *screen,
|
|
gint depth)
|
|
{
|
|
GdkWin32Screen *win32_screen = GDK_WIN32_SCREEN (screen);
|
|
|
|
if (depth == win32_screen->rgba_visual->depth)
|
|
return win32_screen->rgba_visual;
|
|
else if (depth == win32_screen->system_visual->depth)
|
|
return win32_screen->system_visual;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static GdkVisual *
|
|
gdk_win32_screen_visual_get_best_with_type (GdkScreen *screen,
|
|
GdkVisualType visual_type)
|
|
{
|
|
GdkWin32Screen *win32_screen = GDK_WIN32_SCREEN (screen);
|
|
|
|
if (visual_type == win32_screen->rgba_visual->type)
|
|
return win32_screen->rgba_visual;
|
|
else if (visual_type == win32_screen->system_visual->type)
|
|
return win32_screen->system_visual;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static GdkVisual *
|
|
gdk_win32_screen_visual_get_best_with_both (GdkScreen *screen,
|
|
gint depth,
|
|
GdkVisualType visual_type)
|
|
{
|
|
GdkWin32Screen *win32_screen = GDK_WIN32_SCREEN (screen);
|
|
|
|
if ((depth == win32_screen->rgba_visual->depth) && (visual_type == win32_screen->rgba_visual->type))
|
|
return win32_screen->rgba_visual;
|
|
else if ((depth == win32_screen->system_visual->depth) && (visual_type == win32_screen->system_visual->type))
|
|
return win32_screen->system_visual;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
gdk_win32_screen_query_depths (GdkScreen *screen,
|
|
gint **depths,
|
|
gint *count)
|
|
{
|
|
*count = 1;
|
|
*depths = GDK_WIN32_SCREEN (screen)->available_visual_depths;
|
|
}
|
|
|
|
static void
|
|
gdk_win32_screen_query_visual_types (GdkScreen *screen,
|
|
GdkVisualType **visual_types,
|
|
gint *count)
|
|
{
|
|
*count = 1;
|
|
*visual_types = GDK_WIN32_SCREEN (screen)->available_visual_types;
|
|
}
|
|
|
|
static GList *
|
|
gdk_win32_screen_list_visuals (GdkScreen *screen)
|
|
{
|
|
GdkWin32Screen *win32_screen = GDK_WIN32_SCREEN (screen);
|
|
GList *result = NULL;
|
|
|
|
result = g_list_append (result, win32_screen->rgba_visual);
|
|
result = g_list_append (result, win32_screen->system_visual);
|
|
|
|
return result;
|
|
}
|
|
|
|
static void
|
|
gdk_win32_screen_finalize (GObject *object)
|
|
{
|
|
G_OBJECT_CLASS (gdk_win32_screen_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gdk_win32_screen_class_init (GdkWin32ScreenClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GdkScreenClass *screen_class = GDK_SCREEN_CLASS (klass);
|
|
|
|
object_class->finalize = gdk_win32_screen_finalize;
|
|
|
|
screen_class->get_display = gdk_win32_screen_get_display;
|
|
screen_class->get_root_window = gdk_win32_screen_get_root_window;
|
|
screen_class->is_composited = gdk_win32_screen_is_composited;
|
|
screen_class->make_display_name = gdk_win32_screen_make_display_name;
|
|
screen_class->get_setting = _gdk_win32_screen_get_setting;
|
|
screen_class->get_system_visual = gdk_win32_screen_get_system_visual;
|
|
screen_class->get_rgba_visual = gdk_win32_screen_get_rgba_visual;
|
|
screen_class->visual_get_best_depth = gdk_win32_screen_visual_get_best_depth;
|
|
screen_class->visual_get_best_type = gdk_win32_screen_visual_get_best_type;
|
|
screen_class->visual_get_best = gdk_win32_screen_visual_get_best;
|
|
screen_class->visual_get_best_with_depth = gdk_win32_screen_visual_get_best_with_depth;
|
|
screen_class->visual_get_best_with_type = gdk_win32_screen_visual_get_best_with_type;
|
|
screen_class->visual_get_best_with_both = gdk_win32_screen_visual_get_best_with_both;
|
|
screen_class->query_depths = gdk_win32_screen_query_depths;
|
|
screen_class->query_visual_types = gdk_win32_screen_query_visual_types;
|
|
screen_class->list_visuals = gdk_win32_screen_list_visuals;
|
|
}
|