]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkproperty-win32.c
Merge branch 'gdk-backend-wayland'
[~andy/gtk] / gdk / win32 / gdkproperty-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 1998-2002 Tor Lillqvist
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29 #include <string.h>
30 #include <stdlib.h>
31 #include <glib/gprintf.h>
32
33 #include "gdkscreen.h"
34 #include "gdkproperty.h"
35 #include "gdkselection.h"
36 #include "gdkprivate-win32.h"
37 #include "gdkwin32.h"
38
39 GdkAtom
40 _gdk_win32_display_manager_atom_intern (GdkDisplayManager *manager,
41                                         const gchar *atom_name,
42                                         gint         only_if_exists)
43 {
44   ATOM win32_atom;
45   GdkAtom retval;
46   static GHashTable *atom_hash = NULL;
47   
48   if (!atom_hash)
49     atom_hash = g_hash_table_new (g_str_hash, g_str_equal);
50
51   retval = g_hash_table_lookup (atom_hash, atom_name);
52   if (!retval)
53     {
54       if (strcmp (atom_name, "PRIMARY") == 0)
55         retval = GDK_SELECTION_PRIMARY;
56       else if (strcmp (atom_name, "SECONDARY") == 0)
57         retval = GDK_SELECTION_SECONDARY;
58       else if (strcmp (atom_name, "CLIPBOARD") == 0)
59         retval = GDK_SELECTION_CLIPBOARD;
60       else if (strcmp (atom_name, "ATOM") == 0)
61         retval = GDK_SELECTION_TYPE_ATOM;
62       else if (strcmp (atom_name, "BITMAP") == 0)
63         retval = GDK_SELECTION_TYPE_BITMAP;
64       else if (strcmp (atom_name, "COLORMAP") == 0)
65         retval = GDK_SELECTION_TYPE_COLORMAP;
66       else if (strcmp (atom_name, "DRAWABLE") == 0)
67         retval = GDK_SELECTION_TYPE_DRAWABLE;
68       else if (strcmp (atom_name, "INTEGER") == 0)
69         retval = GDK_SELECTION_TYPE_INTEGER;
70       else if (strcmp (atom_name, "PIXMAP") == 0)
71         retval = GDK_SELECTION_TYPE_PIXMAP;
72       else if (strcmp (atom_name, "WINDOW") == 0)
73         retval = GDK_SELECTION_TYPE_WINDOW;
74       else if (strcmp (atom_name, "STRING") == 0)
75         retval = GDK_SELECTION_TYPE_STRING;
76       else
77         {
78           win32_atom = GlobalAddAtom (atom_name);
79           retval = GUINT_TO_POINTER ((guint) win32_atom);
80         }
81       g_hash_table_insert (atom_hash, 
82                            g_strdup (atom_name), 
83                            retval);
84     }
85
86   return retval;
87 }
88
89 gchar *
90 _gdk_win32_display_manager_get_atom_name (GdkDisplayManager *manager, 
91                                           GdkAtom            atom)
92 {
93   ATOM win32_atom;
94   gchar name[256];
95
96   if (GDK_NONE == atom) return g_strdup ("<none>");
97   else if (GDK_SELECTION_PRIMARY == atom) return g_strdup ("PRIMARY");
98   else if (GDK_SELECTION_SECONDARY == atom) return g_strdup ("SECONDARY");
99   else if (GDK_SELECTION_CLIPBOARD == atom) return g_strdup ("CLIPBOARD");
100   else if (GDK_SELECTION_TYPE_ATOM == atom) return g_strdup ("ATOM");
101   else if (GDK_SELECTION_TYPE_BITMAP == atom) return g_strdup ("BITMAP");
102   else if (GDK_SELECTION_TYPE_COLORMAP == atom) return g_strdup ("COLORMAP");
103   else if (GDK_SELECTION_TYPE_DRAWABLE == atom) return g_strdup ("DRAWABLE");
104   else if (GDK_SELECTION_TYPE_INTEGER == atom) return g_strdup ("INTEGER");
105   else if (GDK_SELECTION_TYPE_PIXMAP == atom) return g_strdup ("PIXMAP");
106   else if (GDK_SELECTION_TYPE_WINDOW == atom) return g_strdup ("WINDOW");
107   else if (GDK_SELECTION_TYPE_STRING == atom) return g_strdup ("STRING");
108   
109   win32_atom = GPOINTER_TO_UINT (atom);
110   
111   if (win32_atom < 0xC000)
112     return g_strdup_printf ("#%p", atom);
113   else if (GlobalGetAtomName (win32_atom, name, sizeof (name)) == 0)
114     return NULL;
115   return g_strdup (name);
116 }
117
118 gint
119 _gdk_win32_window_get_property (GdkWindow   *window,
120                   GdkAtom      property,
121                   GdkAtom      type,
122                   gulong       offset,
123                   gulong       length,
124                   gint         pdelete,
125                   GdkAtom     *actual_property_type,
126                   gint        *actual_format_type,
127                   gint        *actual_length,
128                   guchar     **data)
129 {
130   g_return_val_if_fail (window != NULL, FALSE);
131   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
132
133   if (GDK_WINDOW_DESTROYED (window))
134     return FALSE;
135
136   g_warning ("gdk_property_get: Not implemented");
137
138   return FALSE;
139 }
140
141 void
142 _gdk_win32_window_change_property (GdkWindow    *window,
143                      GdkAtom       property,
144                      GdkAtom       type,
145                      gint          format,
146                      GdkPropMode   mode,
147                      const guchar *data,
148                      gint          nelements)
149 {
150   HGLOBAL hdata;
151   gint i, size;
152   guchar *ucptr, *buf = NULL;
153   wchar_t *wcptr, *p;
154   glong wclen;
155
156   g_return_if_fail (window != NULL);
157   g_return_if_fail (GDK_IS_WINDOW (window));
158
159   if (GDK_WINDOW_DESTROYED (window))
160     return;
161
162   GDK_NOTE (DND, {
163       gchar *prop_name = gdk_atom_name (property);
164       gchar *type_name = gdk_atom_name (type);
165       
166       g_print ("gdk_property_change: %p %s %s %s %d*%d bits: %s\n",
167                GDK_WINDOW_HWND (window),
168                prop_name,
169                type_name,
170                (mode == GDK_PROP_MODE_REPLACE ? "REPLACE" :
171                 (mode == GDK_PROP_MODE_PREPEND ? "PREPEND" :
172                  (mode == GDK_PROP_MODE_APPEND ? "APPEND" :
173                   "???"))),
174                format, nelements,
175                _gdk_win32_data_to_string (data, MIN (10, format*nelements/8)));
176       g_free (prop_name);
177       g_free (type_name);
178     });
179
180   /* We should never come here for these types */
181   g_return_if_fail (type != GDK_TARGET_STRING);
182   g_return_if_fail (type != _text);
183   g_return_if_fail (type != _compound_text);
184   g_return_if_fail (type != _save_targets);
185
186   if (property == _gdk_selection &&
187       format == 8 &&
188       mode == GDK_PROP_MODE_REPLACE)
189     {
190       if (type == _utf8_string)
191         {
192           if (!OpenClipboard (GDK_WINDOW_HWND (window)))
193             {
194               WIN32_API_FAILED ("OpenClipboard");
195               return;
196             }
197
198           wcptr = g_utf8_to_utf16 ((char *) data, nelements, NULL, &wclen, NULL);
199
200           wclen++;              /* Terminating 0 */
201           size = wclen * 2;
202           for (i = 0; i < wclen; i++)
203             if (wcptr[i] == '\n')
204               size += 2;
205           
206           if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, size)))
207             {
208               WIN32_API_FAILED ("GlobalAlloc");
209               if (!CloseClipboard ())
210                 WIN32_API_FAILED ("CloseClipboard");
211               g_free (buf);
212               return;
213             }
214
215           ucptr = GlobalLock (hdata);
216
217           p = (wchar_t *) ucptr;
218           for (i = 0; i < wclen; i++)
219             {
220               if (wcptr[i] == '\n')
221                 *p++ = '\r';
222               *p++ = wcptr[i];
223             }
224           g_free (wcptr);
225
226           GlobalUnlock (hdata);
227           GDK_NOTE (DND, g_print ("... SetClipboardData(CF_UNICODETEXT,%p)\n",
228                                   hdata));
229           if (!SetClipboardData (CF_UNICODETEXT, hdata))
230             WIN32_API_FAILED ("SetClipboardData");
231       
232           if (!CloseClipboard ())
233             WIN32_API_FAILED ("CloseClipboard");
234         }
235       else
236         {
237           /* We use delayed rendering for everything else than
238            * text. We can't assign hdata to the clipboard here as type
239            * may be "image/png", "image/jpg", etc. In this case
240            * there's a further conversion afterwards.
241            */
242           GDK_NOTE (DND, g_print ("... delayed rendering\n"));
243           _delayed_rendering_data = NULL;
244           if (!(hdata = GlobalAlloc (GMEM_MOVEABLE, nelements > 0 ? nelements : 1)))
245             {
246               WIN32_API_FAILED ("GlobalAlloc");
247               return;
248             }
249           ucptr = GlobalLock (hdata);
250           memcpy (ucptr, data, nelements);
251           GlobalUnlock (hdata);
252           _delayed_rendering_data = hdata;
253         }
254     }
255   else if (property == _gdk_ole2_dnd)
256     {
257       /* Will happen only if gdkdnd-win32.c has OLE2 dnd support compiled in */
258       _gdk_win32_ole2_dnd_property_change (type, format, data, nelements);
259     }
260   else
261     g_warning ("gdk_property_change: General case not implemented");
262 }
263
264 void
265 _gdk_win32_window_delete_property (GdkWindow *window,
266                                    GdkAtom    property)
267 {
268   gchar *prop_name;
269
270   g_return_if_fail (window != NULL);
271   g_return_if_fail (GDK_IS_WINDOW (window));
272
273   GDK_NOTE (DND, {
274       prop_name = gdk_atom_name (property);
275
276       g_print ("gdk_property_delete: %p %s\n",
277                GDK_WINDOW_HWND (window),
278                prop_name);
279       g_free (prop_name);
280     });
281
282   if (property == _gdk_selection)
283     _gdk_selection_property_delete (window);
284   else if (property == _wm_transient_for)
285     gdk_window_set_transient_for (window, _gdk_root);
286   else
287     {
288       prop_name = gdk_atom_name (property);
289       g_warning ("gdk_property_delete: General case (%s) not implemented",
290                  prop_name);
291       g_free (prop_name);
292     }
293 }
294
295 /*
296   For reference, from gdk/x11/gdksettings.c:
297
298   "Net/DoubleClickTime\0"     "gtk-double-click-time\0"
299   "Net/DoubleClickDistance\0" "gtk-double-click-distance\0"
300   "Net/DndDragThreshold\0"    "gtk-dnd-drag-threshold\0"
301   "Net/CursorBlink\0"         "gtk-cursor-blink\0"
302   "Net/CursorBlinkTime\0"     "gtk-cursor-blink-time\0"
303   "Net/ThemeName\0"           "gtk-theme-name\0"
304   "Net/IconThemeName\0"       "gtk-icon-theme-name\0"
305   "Gtk/CanChangeAccels\0"     "gtk-can-change-accels\0"
306   "Gtk/ColorPalette\0"        "gtk-color-palette\0"
307   "Gtk/FontName\0"            "gtk-font-name\0"
308   "Gtk/IconSizes\0"           "gtk-icon-sizes\0"
309   "Gtk/KeyThemeName\0"        "gtk-key-theme-name\0"
310   "Gtk/ToolbarStyle\0"        "gtk-toolbar-style\0"
311   "Gtk/ToolbarIconSize\0"     "gtk-toolbar-icon-size\0"
312   "Gtk/IMPreeditStyle\0"      "gtk-im-preedit-style\0"
313   "Gtk/IMStatusStyle\0"       "gtk-im-status-style\0"
314   "Gtk/Modules\0"             "gtk-modules\0"
315   "Gtk/FileChooserBackend\0"  "gtk-file-chooser-backend\0"
316   "Gtk/ButtonImages\0"        "gtk-button-images\0"
317   "Gtk/MenuImages\0"          "gtk-menu-images\0"
318   "Gtk/MenuBarAccel\0"        "gtk-menu-bar-accel\0"
319   "Gtk/CursorBlinkTimeout\0"  "gtk-cursor-blink-timeout\0"
320   "Gtk/CursorThemeName\0"     "gtk-cursor-theme-name\0"
321   "Gtk/CursorThemeSize\0"     "gtk-cursor-theme-size\0"
322   "Gtk/ShowInputMethodMenu\0" "gtk-show-input-method-menu\0"
323   "Gtk/ShowUnicodeMenu\0"     "gtk-show-unicode-menu\0"
324   "Gtk/TimeoutInitial\0"      "gtk-timeout-initial\0"
325   "Gtk/TimeoutRepeat\0"       "gtk-timeout-repeat\0"
326   "Gtk/ColorScheme\0"         "gtk-color-scheme\0"
327   "Gtk/EnableAnimations\0"    "gtk-enable-animations\0"
328   "Xft/Antialias\0"           "gtk-xft-antialias\0"
329   "Xft/Hinting\0"             "gtk-xft-hinting\0"
330   "Xft/HintStyle\0"           "gtk-xft-hintstyle\0"
331   "Xft/RGBA\0"                "gtk-xft-rgba\0"
332   "Xft/DPI\0"                 "gtk-xft-dpi\0"
333   "Net/FallbackIconTheme\0"   "gtk-fallback-icon-theme\0"
334   "Gtk/TouchscreenMode\0"     "gtk-touchscreen-mode\0"
335   "Gtk/EnableAccels\0"        "gtk-enable-accels\0"
336   "Gtk/EnableMnemonics\0"     "gtk-enable-mnemonics\0"
337   "Gtk/ScrolledWindowPlacement\0" "gtk-scrolled-window-placement\0"
338   "Gtk/IMModule\0"            "gtk-im-module\0"
339   "Fontconfig/Timestamp\0"    "gtk-fontconfig-timestamp\0"
340   "Net/SoundThemeName\0"      "gtk-sound-theme-name\0"
341   "Net/EnableInputFeedbackSounds\0" "gtk-enable-input-feedback-sounds\0"
342   "Net/EnableEventSounds\0"  "gtk-enable-event-sounds\0";
343
344   More, from various places in gtk sources:
345
346   gtk-entry-select-on-focus
347   gtk-split-cursor
348
349 */
350 gboolean
351 _gdk_win32_screen_get_setting (GdkScreen   *screen,
352                         const gchar *name,
353                         GValue      *value)
354 {
355   g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
356
357   /*
358    * XXX : if these values get changed through the Windoze UI the
359    *       respective gdk_events are not generated yet.
360    */
361   if (strcmp ("gtk-theme-name", name) == 0) 
362     {
363       g_value_set_string (value, "ms-windows");
364     }
365   else if (strcmp ("gtk-double-click-time", name) == 0)
366     {
367       gint i = GetDoubleClickTime ();
368       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
369       g_value_set_int (value, i);
370       return TRUE;
371     }
372   else if (strcmp ("gtk-double-click-distance", name) == 0)
373     {
374       gint i = MAX(GetSystemMetrics (SM_CXDOUBLECLK), GetSystemMetrics (SM_CYDOUBLECLK));
375       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
376       g_value_set_int (value, i);
377       return TRUE;
378     }
379   else if (strcmp ("gtk-dnd-drag-threshold", name) == 0)
380     {
381       gint i = MAX(GetSystemMetrics (SM_CXDRAG), GetSystemMetrics (SM_CYDRAG));
382       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %d\n", name, i));
383       g_value_set_int (value, i);
384       return TRUE;
385     }
386   else if (strcmp ("gtk-split-cursor", name) == 0)
387     {
388       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : FALSE\n", name));
389       g_value_set_boolean (value, FALSE);
390       return TRUE;
391     }
392   else if (strcmp ("gtk-alternative-button-order", name) == 0)
393     {
394       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : TRUE\n", name));
395       g_value_set_boolean (value, TRUE);
396       return TRUE;
397     }
398   else if (strcmp ("gtk-alternative-sort-arrows", name) == 0)
399     {
400       GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : TRUE\n", name));
401       g_value_set_boolean (value, TRUE);
402       return TRUE;
403     }
404 #if 0
405   /*
406    * With 'MS Sans Serif' as windows menu font (default on win98se) you'll get a 
407    * bunch of :
408    *   WARNING **: Couldn't load font "MS Sans Serif 8" falling back to "Sans 8"
409    * at least with testfilechooser (regardless of the bitmap check below)
410    * so just disabling this code seems to be the best we can do --hb
411    */
412   else if (strcmp ("gtk-font-name", name) == 0)
413     {
414       NONCLIENTMETRICS ncm;
415       ncm.cbSize = sizeof(NONCLIENTMETRICS);
416       if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, FALSE))
417         {
418           /* Pango finally uses GetDeviceCaps to scale, we use simple
419            * approximation here.
420            */
421           int nHeight = (0 > ncm.lfMenuFont.lfHeight ? -3*ncm.lfMenuFont.lfHeight/4 : 10);
422           if (OUT_STRING_PRECIS == ncm.lfMenuFont.lfOutPrecision)
423             GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : ignoring bitmap font '%s'\n", 
424                                    name, ncm.lfMenuFont.lfFaceName));
425           else if (ncm.lfMenuFont.lfFaceName && strlen(ncm.lfMenuFont.lfFaceName) > 0 &&
426                    /* Avoid issues like those described in bug #135098 */
427                    g_utf8_validate (ncm.lfMenuFont.lfFaceName, -1, NULL))
428             {
429               char* s = g_strdup_printf ("%s %d", ncm.lfMenuFont.lfFaceName, nHeight);
430               GDK_NOTE(MISC, g_print("gdk_screen_get_setting(%s) : %s\n", name, s));
431               g_value_set_string (value, s);
432
433               g_free(s);
434               return TRUE;
435             }
436         }
437     }
438 #endif
439
440   return FALSE;
441 }