2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
5 * Various ICCCM related functions.
7 * This is ALL the code involving anything ICCCM related. for both WM and
11 #include "ecore_x_private.h"
13 #include "Ecore_X_Atoms.h"
17 ecore_x_icccm_init(void)
22 ecore_x_icccm_state_set(Ecore_X_Window win, Ecore_X_Window_State_Hint state)
26 if (state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
27 c[0] = WithdrawnState;
28 else if (state == ECORE_X_WINDOW_STATE_HINT_NORMAL)
30 else if (state == ECORE_X_WINDOW_STATE_HINT_ICONIC)
33 XChangeProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_STATE,
34 ECORE_X_ATOM_WM_STATE, 32, PropModeReplace,
35 (unsigned char *)c, 2);
38 EAPI Ecore_X_Window_State_Hint
39 ecore_x_icccm_state_get(Ecore_X_Window win)
41 unsigned char *prop_ret = NULL;
43 unsigned long bytes_after, num_ret;
45 Ecore_X_Window_State_Hint hint;
47 hint = ECORE_X_WINDOW_STATE_HINT_NONE;
48 XGetWindowProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_STATE,
49 0, 0x7fffffff, False, ECORE_X_ATOM_WM_STATE,
50 &type_ret, &format_ret, &num_ret, &bytes_after,
52 if ((prop_ret) && (num_ret == 2))
54 if (prop_ret[0] == WithdrawnState)
55 hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
56 else if (prop_ret[0] == NormalState)
57 hint = ECORE_X_WINDOW_STATE_HINT_NORMAL;
58 else if (prop_ret[0] == IconicState)
59 hint = ECORE_X_WINDOW_STATE_HINT_ICONIC;
69 ecore_x_icccm_delete_window_send(Ecore_X_Window win, Ecore_X_Time t)
71 ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
72 ECORE_X_EVENT_MASK_NONE,
73 ECORE_X_ATOM_WM_DELETE_WINDOW,
78 ecore_x_icccm_take_focus_send(Ecore_X_Window win, Ecore_X_Time t)
80 ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
81 ECORE_X_EVENT_MASK_NONE,
82 ECORE_X_ATOM_WM_TAKE_FOCUS,
87 ecore_x_icccm_save_yourself_send(Ecore_X_Window win, Ecore_X_Time t)
89 ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS,
90 ECORE_X_EVENT_MASK_NONE,
91 ECORE_X_ATOM_WM_SAVE_YOURSELF,
96 ecore_x_icccm_move_resize_send(Ecore_X_Window win, int x, int y, int w, int h)
100 ev.type = ConfigureNotify;
101 ev.xconfigure.display = _ecore_x_disp;
102 ev.xconfigure.event = win;
103 ev.xconfigure.window = win;
106 ev.xconfigure.width = w;
107 ev.xconfigure.height = h;
108 ev.xconfigure.border_width = 0;
109 ev.xconfigure.above = None;
110 ev.xconfigure.override_redirect = False;
111 XSendEvent(_ecore_x_disp, win, False, StructureNotifyMask, &ev);
115 ecore_x_icccm_hints_set(Ecore_X_Window win,
117 Ecore_X_Window_State_Hint initial_state,
118 Ecore_X_Pixmap icon_pixmap,
119 Ecore_X_Pixmap icon_mask,
120 Ecore_X_Window icon_window,
121 Ecore_X_Window window_group, int is_urgent)
125 hints = XAllocWMHints();
129 hints->flags = InputHint | StateHint;
130 hints->input = accepts_focus;
131 if (initial_state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
132 hints->initial_state = WithdrawnState;
133 else if (initial_state == ECORE_X_WINDOW_STATE_HINT_NORMAL)
134 hints->initial_state = NormalState;
135 else if (initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC)
136 hints->initial_state = IconicState;
137 if (icon_pixmap != 0)
139 hints->icon_pixmap = icon_pixmap;
140 hints->flags |= IconPixmapHint;
144 hints->icon_mask = icon_mask;
145 hints->flags |= IconMaskHint;
147 if (icon_window != 0)
149 hints->icon_window = icon_window;
150 hints->flags |= IconWindowHint;
152 if (window_group != 0)
154 hints->window_group = window_group;
155 hints->flags |= WindowGroupHint;
158 hints->flags |= XUrgencyHint;
159 XSetWMHints(_ecore_x_disp, win, hints);
164 ecore_x_icccm_hints_get(Ecore_X_Window win,
166 Ecore_X_Window_State_Hint *initial_state,
167 Ecore_X_Pixmap *icon_pixmap,
168 Ecore_X_Pixmap *icon_mask,
169 Ecore_X_Window *icon_window,
170 Ecore_X_Window *window_group, int *is_urgent)
177 *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
188 hints = XGetWMHints(_ecore_x_disp, win);
191 if ((hints->flags & InputHint) && (accepts_focus))
198 if ((hints->flags & StateHint) && (initial_state))
200 if (hints->initial_state == WithdrawnState)
201 *initial_state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN;
202 else if (hints->initial_state == NormalState)
203 *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
204 else if (hints->initial_state == IconicState)
205 *initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
207 if ((hints->flags & IconPixmapHint) && (icon_pixmap))
209 *icon_pixmap = hints->icon_pixmap;
211 if ((hints->flags & IconMaskHint) && (icon_mask))
213 *icon_mask = hints->icon_mask;
215 if ((hints->flags & IconWindowHint) && (icon_window))
217 *icon_window = hints->icon_window;
219 if ((hints->flags & WindowGroupHint) && (window_group))
221 *window_group = hints->window_group;
223 if ((hints->flags & XUrgencyHint) && (is_urgent))
234 ecore_x_icccm_size_pos_hints_set(Ecore_X_Window win,
236 Ecore_X_Gravity gravity,
237 int min_w, int min_h,
238 int max_w, int max_h,
239 int base_w, int base_h,
240 int step_x, int step_y,
241 double min_aspect, double max_aspect)
246 if (!XGetWMNormalHints(_ecore_x_disp, win, &hint, &mask))
248 memset(&hint, 0, sizeof(XSizeHints));
254 hint.flags |= USPosition;
256 if (gravity != ECORE_X_GRAVITY_NW)
258 hint.flags |= PWinGravity;
259 hint.win_gravity = gravity;
261 if ((min_w > 0) || (min_h > 0))
263 hint.flags |= PMinSize;
264 hint.min_width = min_w;
265 hint.min_height = min_h;
267 if ((max_w > 0) || (max_h > 0))
269 hint.flags |= PMaxSize;
270 hint.max_width = max_w;
271 hint.max_height = max_h;
273 if ((base_w > 0) || (base_h > 0))
275 hint.flags |= PBaseSize;
276 hint.base_width = base_w;
277 hint.base_height = base_h;
279 if ((step_x > 1) || (step_y > 1))
281 hint.flags |= PResizeInc;
282 hint.width_inc = step_x;
283 hint.height_inc = step_y;
285 if ((min_aspect > 0.0) || (max_aspect > 0.0))
287 hint.flags |= PAspect;
288 hint.min_aspect.x = min_aspect * 10000;
289 hint.min_aspect.y = 10000;
290 hint.max_aspect.x = max_aspect * 10000;
291 hint.max_aspect.y = 10000;
293 XSetWMNormalHints(_ecore_x_disp, win, &hint);
297 ecore_x_icccm_size_pos_hints_get(Ecore_X_Window win,
299 Ecore_X_Gravity *gravity,
300 int *min_w, int *min_h,
301 int *max_w, int *max_h,
302 int *base_w, int *base_h,
303 int *step_x, int *step_y,
304 double *min_aspect, double *max_aspect)
309 int minw = 0, minh = 0;
310 int maxw = 32767, maxh = 32767;
311 int basew = -1, baseh = -1;
312 int stepx = -1, stepy = -1;
313 double mina = 0.0, maxa = 0.0;
315 if (!XGetWMNormalHints(_ecore_x_disp, win, &hint, &mask))
318 if ((hint.flags & USPosition) || ((hint.flags & PPosition)))
328 if (hint.flags & PWinGravity)
331 *gravity = hint.win_gravity;
336 *gravity = ECORE_X_GRAVITY_NW;
338 if (hint.flags & PMinSize)
340 minw = hint.min_width;
341 minh = hint.min_height;
343 if (hint.flags & PMaxSize)
345 maxw = hint.max_width;
346 maxh = hint.max_height;
352 if (hint.flags & PBaseSize)
354 basew = hint.base_width;
355 baseh = hint.base_height;
361 if (hint.flags & PResizeInc)
363 stepx = hint.width_inc;
364 stepy = hint.height_inc;
370 if (hint.flags & PAspect)
372 if (hint.min_aspect.y > 0)
373 mina = ((double)hint.min_aspect.x) / ((double)hint.min_aspect.y);
374 if (hint.max_aspect.y > 0)
375 maxa = ((double)hint.max_aspect.x) / ((double)hint.max_aspect.y);
401 ecore_x_icccm_title_set(Ecore_X_Window win, const char *t)
408 #ifdef X_HAVE_UTF8_STRING
411 Xutf8TextListToTextProperty(_ecore_x_disp, list, 1, XUTF8StringStyle,
416 XmbTextListToTextProperty(_ecore_x_disp, list, 1, XStdICCTextStyle,
421 XSetWMName(_ecore_x_disp, win, &xprop);
422 if (xprop.value) XFree(xprop.value);
426 if (XStringListToTextProperty(list, 1, &xprop) >= Success)
428 XSetWMName(_ecore_x_disp, win, &xprop);
429 if (xprop.value) XFree(xprop.value);
436 ecore_x_icccm_title_get(Ecore_X_Window win)
441 if (XGetWMName(_ecore_x_disp, win, &xprop) >= Success)
450 if (xprop.encoding == ECORE_X_ATOM_UTF8_STRING)
452 t = strdup((char *)xprop.value);
457 /* convert to utf8 */
458 #ifdef X_HAVE_UTF8_STRING
459 ret = Xutf8TextPropertyToTextList(_ecore_x_disp, &xprop,
462 ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop,
466 if ((ret == XLocaleNotSupported) ||
467 (ret == XNoMemory) || (ret == XConverterNotFound))
469 t = strdup((char *)xprop.value);
471 else if ((ret >= Success) && (num > 0))
476 XFreeStringList(list);
479 if (xprop.value) XFree(xprop.value);
487 * Set or unset a wm protocol property.
488 * @param win The Window
489 * @param protocol The protocol to enable/disable
493 ecore_x_icccm_protocol_set(Ecore_X_Window win,
494 Ecore_X_WM_Protocol protocol, int on)
498 int protos_count = 0;
502 /* Check for invalid values */
503 if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
506 proto = _ecore_x_atoms_wm_protocols[protocol];
508 if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count))
514 for (i = 0; i < protos_count; i++)
516 if (protos[i] == proto)
525 Atom *new_protos = NULL;
529 new_protos = malloc((protos_count + 1) * sizeof(Atom));
532 for (i = 0; i < protos_count; i++)
533 new_protos[i] = protos[i];
534 new_protos[protos_count] = proto;
535 XSetWMProtocols(_ecore_x_disp, win, new_protos, protos_count + 1);
542 for (i = 0; i < protos_count; i++)
544 if (protos[i] == proto)
548 for (j = i + 1; j < protos_count; j++)
549 protos[j - 1] = protos[j];
550 if (protos_count > 1)
551 XSetWMProtocols(_ecore_x_disp, win, protos,
554 XDeleteProperty(_ecore_x_disp, win,
555 ECORE_X_ATOM_WM_PROTOCOLS);
568 * Determines whether a protocol is set for a window.
569 * @param win The Window
570 * @param protocol The protocol to query
571 * @return 1 if the protocol is set, else 0.
574 ecore_x_icccm_protocol_isset(Ecore_X_Window win, Ecore_X_WM_Protocol protocol)
576 Atom proto, *protos = NULL;
577 int i, ret = 0, protos_count = 0;
579 /* check for invalid values */
580 if (protocol >= ECORE_X_WM_PROTOCOL_NUM)
583 proto = _ecore_x_atoms_wm_protocols[protocol];
585 if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count))
588 for (i = 0; i < protos_count; i++)
589 if (protos[i] == proto)
595 if (protos) XFree(protos);
601 * Set a window name & class.
602 * @param win The window
603 * @param n The name string
604 * @param c The class string
606 * Set a window name * class
609 ecore_x_icccm_name_class_set(Ecore_X_Window win, const char *n, const char *c)
613 xch = XAllocClassHint();
616 xch->res_name = (char *)n;
617 xch->res_class = (char *)c;
618 XSetClassHint(_ecore_x_disp, win, xch);
623 * Get a window name & class.
624 * @param win The window
625 * @param n The name string
626 * @param c The class string
628 * Get a window name * class
631 ecore_x_icccm_name_class_get(Ecore_X_Window win, char **n, char **c)
638 xch.res_class = NULL;
639 if (XGetClassHint(_ecore_x_disp, win, &xch))
643 if (xch.res_name) *n = strdup(xch.res_name);
647 if (xch.res_class) *c = strdup(xch.res_class);
650 XFree(xch.res_class);
655 * Get a window client machine string.
656 * @param win The window
657 * @return The windows client machine string
659 * Return the client machine of a window. String must be free'd when done with.
662 ecore_x_icccm_client_machine_get(Ecore_X_Window win)
666 name = ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_CLIENT_MACHINE);
671 * Sets the WM_COMMAND property for @a win.
673 * @param win The window.
674 * @param argc Number of arguments.
675 * @param argv Arguments.
678 ecore_x_icccm_command_set(Ecore_X_Window win, int argc, char **argv)
680 XSetCommand(_ecore_x_disp, win, argv, argc);
684 * Get the WM_COMMAND property for @a win.
686 * Return the command of a window. String must be free'd when done with.
688 * @param win The window.
689 * @param argc Number of arguments.
690 * @param argv Arguments.
693 ecore_x_icccm_command_get(Ecore_X_Window win, int *argc, char ***argv)
699 if (argv) *argv = NULL;
701 if (!XGetCommand(_ecore_x_disp, win, &v, &c))
713 (*argv) = malloc(c * sizeof(char *));
720 for (i = 0; i < c; i++)
723 (*argv)[i] = strdup(v[i]);
725 (*argv)[i] = strdup("");
732 * Set a window icon name.
733 * @param win The window
734 * @param t The icon name string
736 * Set a window icon name
739 ecore_x_icccm_icon_name_set(Ecore_X_Window win, const char *t)
746 #ifdef X_HAVE_UTF8_STRING
748 ret = Xutf8TextListToTextProperty(_ecore_x_disp, list, 1,
749 XUTF8StringStyle, &xprop);
752 ret = XmbTextListToTextProperty(_ecore_x_disp, list, 1,
753 XStdICCTextStyle, &xprop);
757 XSetWMIconName(_ecore_x_disp, win, &xprop);
758 if (xprop.value) XFree(xprop.value);
762 if (XStringListToTextProperty(list, 1, &xprop) >= Success)
764 XSetWMIconName(_ecore_x_disp, win, &xprop);
765 if (xprop.value) XFree(xprop.value);
772 * Get a window icon name.
773 * @param win The window
774 * @return The windows icon name string
776 * Return the icon name of a window. String must be free'd when done with.
779 ecore_x_icccm_icon_name_get(Ecore_X_Window win)
784 if (XGetWMIconName(_ecore_x_disp, win, &xprop) >= Success)
793 if (xprop.encoding == ECORE_X_ATOM_UTF8_STRING)
795 t = strdup((char *)xprop.value);
800 /* convert to utf8 */
801 #ifdef X_HAVE_UTF8_STRING
802 ret = Xutf8TextPropertyToTextList(_ecore_x_disp, &xprop,
805 ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop,
809 if ((ret == XLocaleNotSupported) ||
810 (ret == XNoMemory) || (ret == XConverterNotFound))
812 t = strdup((char *)xprop.value);
814 else if (ret >= Success)
816 if ((num >= 1) && (list))
821 XFreeStringList(list);
825 if (xprop.value) XFree(xprop.value);
833 * Add a subwindow to the list of windows that need a different colormap installed.
834 * @param win The toplevel window
835 * @param subwin The subwindow to be added to the colormap windows list
838 ecore_x_icccm_colormap_window_set(Ecore_X_Window win, Ecore_X_Window subwin)
841 unsigned char *old_data = NULL;
842 unsigned char *data = NULL;
843 Window *oldset = NULL;
844 Window *newset = NULL;
846 if (!ecore_x_window_prop_property_get(win,
847 ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
848 XA_WINDOW, 32, &old_data, &num))
850 newset = calloc(1, sizeof(Window));
855 data = (unsigned char *)newset;
859 newset = calloc(num + 1, sizeof(Window));
860 oldset = (Window *) old_data;
863 for (i = 0; i < num; ++i)
865 if (oldset[i] == subwin)
867 if (old_data) XFree(old_data);
873 newset[i] = oldset[i];
876 newset[num++] = subwin;
877 if (old_data) XFree(old_data);
878 data = (unsigned char *)newset;
881 ecore_x_window_prop_property_set(win,
882 ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
883 XA_WINDOW, 32, data, num);
888 * Remove a window from the list of colormap windows.
889 * @param win The toplevel window
890 * @param subwin The window to be removed from the colormap window list.
893 ecore_x_icccm_colormap_window_unset(Ecore_X_Window win, Ecore_X_Window subwin)
895 int num = 0, i, j, k = 0;
896 unsigned char *old_data = NULL;
897 unsigned char *data = NULL;
898 Window *oldset = NULL;
899 Window *newset = NULL;
901 if (!ecore_x_window_prop_property_get(win,
902 ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
903 XA_WINDOW, 32, &old_data, &num))
906 oldset = (Window *) old_data;
907 for (i = 0; i < num; i++)
909 if (oldset[i] == subwin)
913 XDeleteProperty(_ecore_x_disp,
914 win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS);
915 if (old_data) XFree(old_data);
921 newset = calloc(num - 1, sizeof(Window));
922 data = (unsigned char *)newset;
923 for (j = 0; j < num; ++j)
924 if (oldset[j] != subwin)
925 newset[k++] = oldset[j];
926 ecore_x_window_prop_property_set(win,
927 ECORE_X_ATOM_WM_COLORMAP_WINDOWS,
928 XA_WINDOW, 32, data, k);
929 if (old_data) XFree(old_data);
937 if (old_data) XFree(old_data);
941 * Specify that a window is transient for another top-level window and should be handled accordingly.
942 * @param win the transient window
943 * @param forwin the toplevel window
946 ecore_x_icccm_transient_for_set(Ecore_X_Window win, Ecore_X_Window forwin)
948 XSetTransientForHint(_ecore_x_disp, win, forwin);
952 * Remove the transient_for setting from a window.
956 ecore_x_icccm_transient_for_unset(Ecore_X_Window win)
958 XDeleteProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_TRANSIENT_FOR);
962 * Get the window this window is transient for, if any.
963 * @param win The window to check
964 * @return The window ID of the top-level window, or 0 if the property does not exist.
967 ecore_x_icccm_transient_for_get(Ecore_X_Window win)
971 if (XGetTransientForHint(_ecore_x_disp, win, &forwin))
972 return (Ecore_X_Window) forwin;
979 * Set the window role hint.
980 * @param win The window
981 * @param role The role string
984 ecore_x_icccm_window_role_set(Ecore_X_Window win, const char *role)
986 ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_WINDOW_ROLE,
991 * Get the window role.
992 * @param win The window
993 * @return The window's role string.
996 ecore_x_icccm_window_role_get(Ecore_X_Window win)
998 return ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_WINDOW_ROLE);
1002 * Set the window's client leader.
1003 * @param win The window
1004 * @param l The client leader window
1006 * All non-transient top-level windows created by an app other than
1007 * the main window must have this property set to the app's main window.
1010 ecore_x_icccm_client_leader_set(Ecore_X_Window win, Ecore_X_Window l)
1012 ecore_x_window_prop_window_set(win, ECORE_X_ATOM_WM_CLIENT_LEADER,
1017 * Get the window's client leader.
1018 * @param win The window
1019 * @return The window's client leader window, or 0 if unset */
1021 ecore_x_icccm_client_leader_get(Ecore_X_Window win)
1025 if (ecore_x_window_prop_window_get(win, ECORE_X_ATOM_WM_CLIENT_LEADER,
1032 ecore_x_icccm_iconic_request_send(Ecore_X_Window win, Ecore_X_Window root)
1037 if (!root) root = DefaultRootWindow(_ecore_x_disp);
1039 xev.xclient.type = ClientMessage;
1040 xev.xclient.serial = 0;
1041 xev.xclient.send_event = True;
1042 xev.xclient.display = _ecore_x_disp;
1043 xev.xclient.window = win;
1044 xev.xclient.format = 32;
1045 xev.xclient.message_type = ECORE_X_ATOM_WM_CHANGE_STATE;
1046 xev.xclient.data.l[0] = IconicState;
1048 XSendEvent(_ecore_x_disp, root, False,
1049 SubstructureNotifyMask | SubstructureRedirectMask, &xev);
1052 /* FIXME: there are older E hints, gnome hints and mwm hints and new netwm */
1053 /* hints. each should go in their own file/section so we know which */
1054 /* is which. also older kde hints too. we should try support as much */
1055 /* as makese sense to support */