diff --git a/legacy/ecore/src/bin/ecore_test.c b/legacy/ecore/src/bin/ecore_test.c index c2e400a10d..9973b2185f 100644 --- a/legacy/ecore/src/bin/ecore_test.c +++ b/legacy/ecore/src/bin/ecore_test.c @@ -435,7 +435,7 @@ setup_ecore_x_test(void) win = ecore_x_window_new(0, 0, 0, 120, 60); ecore_x_window_prop_title_set(win, "Ecore Test Program"); ecore_x_window_prop_name_class_set(win, "ecore_test", "main"); - ecore_x_window_prop_delete_request_set(win, 1); + ecore_x_window_prop_protocol_set(win, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, 1); ecore_x_window_show(win); ecore_x_flush(); diff --git a/legacy/ecore/src/lib/ecore_evas/ecore_evas_x.c b/legacy/ecore/src/lib/ecore_evas/ecore_evas_x.c index ecc5f3d0d5..56b2d67b1d 100644 --- a/legacy/ecore/src/lib/ecore_evas/ecore_evas_x.c +++ b/legacy/ecore/src/lib/ecore_evas/ecore_evas_x.c @@ -574,8 +574,8 @@ _ecore_evas_x_free(Ecore_Evas *ee) static void _ecore_evas_callback_delete_request_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) { - if (func) ecore_x_window_prop_delete_request_set(ee->engine.x.win_container, 1); - else ecore_x_window_prop_delete_request_set(ee->engine.x.win_container, 0); + if (func) ecore_x_window_prop_protocol_set(ee->engine.x.win_container, ECORE_X_WM_PROTOCOL_DELETE_REQUEST,1); + else ecore_x_window_prop_protocol_set(ee->engine.x.win_container, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, 0); ee->func.fn_delete_request = func; } @@ -887,7 +887,7 @@ _ecore_evas_override_set(Ecore_Evas *ee, int on) ecore_x_window_prop_title_set(ee->engine.x.win_container, ee->prop.title); ecore_x_window_prop_name_class_set(ee->engine.x.win_container, ee->prop.name, ee->prop.clas); if (ee->func.fn_delete_request) - ecore_x_window_prop_delete_request_set(ee->engine.x.win_container, 1); + ecore_x_window_prop_protocol_set(ee->engine.x.win_container, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, 1); ecore_x_window_prop_min_size_set(ee->engine.x.win_container, ee->prop.min.w, ee->prop.min.h); ecore_x_window_prop_max_size_set(ee->engine.x.win_container, ee->prop.max.w, ee->prop.max.h); ecore_x_window_prop_base_size_set(ee->engine.x.win_container, ee->prop.base.w, ee->prop.base.h); diff --git a/legacy/ecore/src/lib/ecore_x/Ecore_X.h b/legacy/ecore/src/lib/ecore_x/Ecore_X.h index 0f8844550f..838e0e0031 100644 --- a/legacy/ecore/src/lib/ecore_x/Ecore_X.h +++ b/legacy/ecore/src/lib/ecore_x/Ecore_X.h @@ -424,6 +424,40 @@ extern int ECORE_X_LOCK_SCROLL; extern int ECORE_X_LOCK_NUM; extern int ECORE_X_LOCK_CAPS; +#ifndef _ECORE_X_PRIVATE_H +typedef enum _Ecore_X_WM_Protocol { + /** + * If enabled the window manager will be asked to send a + * delete message instead of just closing (destroying) the window. + */ + ECORE_X_WM_PROTOCOL_DELETE_REQUEST, + + /** + * If enabled the window manager will be told that the window + * explicitly sets input focus. + */ + ECORE_X_WM_PROTOCOL_TAKE_FOCUS +} Ecore_X_WM_Protocol; +#endif + +typedef enum _Ecore_X_Window_Input_Mode { + /** The window can never be focused */ + ECORE_X_WINDOW_INPUT_MODE_NONE, + + /** The window can be focused by the WM but doesn't focus itself */ + ECORE_X_WINDOW_INPUT_MODE_PASSIVE, + + /** The window sets the focus itself if one of its sub-windows + * already is focused + */ + ECORE_X_WINDOW_INPUT_MODE_ACTIVE_LOCAL, + + /** The window sets the focus itself even if another window + * is currently focused + */ + ECORE_X_WINDOW_INPUT_MODE_ACTIVE_GLOBAL +} Ecore_X_Window_Input_Mode; + int ecore_x_init(const char *name); int ecore_x_shutdown(void); Ecore_X_Display *ecore_x_display_get(void); @@ -458,14 +492,16 @@ void ecore_x_window_prop_title_set(Ecore_X_Window win, const char *t char *ecore_x_window_prop_title_get(Ecore_X_Window win); void ecore_x_window_prop_name_class_set(Ecore_X_Window win, const char *n, const char *c); void ecore_x_window_prop_name_class_get(Ecore_X_Window win, char **n, char **c); -void ecore_x_window_prop_delete_request_set(Ecore_X_Window win, int on); +void ecore_x_window_prop_protocol_set(Ecore_X_Window win, Ecore_X_WM_Protocol protocol, int on); +void ecore_x_window_prop_sticky_set(Ecore_X_Window win, int on); +int ecore_x_window_prop_input_mode_set(Ecore_X_Window win, Ecore_X_Window_Input_Mode mode); void ecore_x_window_prop_min_size_set(Ecore_X_Window win, int w, int h); void ecore_x_window_prop_max_size_set(Ecore_X_Window win, int w, int h); void ecore_x_window_prop_base_size_set(Ecore_X_Window win, int w, int h); void ecore_x_window_prop_step_size_set(Ecore_X_Window win, int x, int y); void ecore_x_window_prop_xy_set(Ecore_X_Window win, int x, int y); void ecore_x_window_prop_borderless_set(Ecore_X_Window win, int borderless); -void ecore_x_window_prop_layer_set(Ecore_X_Window win, int layer); +int ecore_x_window_prop_layer_set(Ecore_X_Window win, int layer); void ecore_x_window_prop_withdrawn_set(Ecore_X_Window win, int withdrawn); void ecore_x_window_shape_mask_set(Ecore_X_Window win, Ecore_X_Pixmap mask); diff --git a/legacy/ecore/src/lib/ecore_x/ecore_x.c b/legacy/ecore/src/lib/ecore_x/ecore_x.c index 8945fe5cc4..0154112f21 100644 --- a/legacy/ecore/src/lib/ecore_x/ecore_x.c +++ b/legacy/ecore/src/lib/ecore_x/ecore_x.c @@ -25,11 +25,19 @@ int _ecore_x_event_last_root_x = 0; int _ecore_x_event_last_root_y = 0; Atom _ecore_x_atom_wm_delete_window = 0; +Atom _ecore_x_atom_wm_take_focus = 0; Atom _ecore_x_atom_wm_protocols = 0; Atom _ecore_x_atom_wm_class = 0; Atom _ecore_x_atom_wm_name = 0; Atom _ecore_x_atom_motif_wm_hints = 0; Atom _ecore_x_atom_win_layer = 0; +Atom _ecore_x_atom_net_wm_desktop = 0; +Atom _ecore_x_atom_net_current_desktop = 0; +Atom _ecore_x_atom_net_wm_state = 0; +Atom _ecore_x_atom_net_wm_state_above = 0; +Atom _ecore_x_atom_net_wm_state_below = 0; + +Atom _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM] = {0}; int ECORE_X_EVENT_KEY_DOWN = 0; int ECORE_X_EVENT_KEY_UP = 0; @@ -214,12 +222,22 @@ ecore_x_init(const char *name) return 0; } _ecore_x_filter_handler = ecore_event_filter_add(_ecore_x_event_filter_start, _ecore_x_event_filter_filter, _ecore_x_event_filter_end, NULL); - _ecore_x_atom_wm_delete_window = XInternAtom(_ecore_x_disp, "WM_DELETE_WINDOW", False); - _ecore_x_atom_wm_protocols = XInternAtom(_ecore_x_disp, "WM_PROTOCOLS", False); - _ecore_x_atom_wm_class = XInternAtom(_ecore_x_disp, "WM_CLASS", False); - _ecore_x_atom_wm_name = XInternAtom(_ecore_x_disp, "WM_NAME", False); - _ecore_x_atom_motif_wm_hints = XInternAtom(_ecore_x_disp, "_MOTIF_WM_HINTS", False); - _ecore_x_atom_win_layer = XInternAtom(_ecore_x_disp, "_WIN_LAYER", False); + _ecore_x_atom_wm_delete_window = XInternAtom(_ecore_x_disp, "WM_DELETE_WINDOW", False); + _ecore_x_atom_wm_take_focus = XInternAtom(_ecore_x_disp, "WM_TAKE_FOCUS", False); + _ecore_x_atom_wm_protocols = XInternAtom(_ecore_x_disp, "WM_PROTOCOLS", False); + _ecore_x_atom_wm_class = XInternAtom(_ecore_x_disp, "WM_CLASS", False); + _ecore_x_atom_wm_name = XInternAtom(_ecore_x_disp, "WM_NAME", False); + _ecore_x_atom_motif_wm_hints = XInternAtom(_ecore_x_disp, "_MOTIF_WM_HINTS", False); + _ecore_x_atom_win_layer = XInternAtom(_ecore_x_disp, "_WIN_LAYER", False); + _ecore_x_atom_net_wm_desktop = XInternAtom(_ecore_x_disp, "_NET_WM_DESKTOP", False); + _ecore_x_atom_net_current_desktop = XInternAtom(_ecore_x_disp, "_NET_CURRENT_DESKTOP", False); + _ecore_x_atom_net_wm_state = XInternAtom(_ecore_x_disp, "_NET_WM_STATE", False); + _ecore_x_atom_net_wm_state_above = XInternAtom(_ecore_x_disp, "_NET_WM_STATE_ABOVE", False); + _ecore_x_atom_net_wm_state_below = XInternAtom(_ecore_x_disp, "_NET_WM_STATE_BELOW", False); + + _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] = _ecore_x_atom_wm_delete_window; + _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] = _ecore_x_atom_wm_take_focus; + _ecore_x_init_count++; return _ecore_x_init_count; } diff --git a/legacy/ecore/src/lib/ecore_x/ecore_x_private.h b/legacy/ecore/src/lib/ecore_x/ecore_x_private.h index 4c43ecce7f..f373b0ac7f 100644 --- a/legacy/ecore/src/lib/ecore_x/ecore_x_private.h +++ b/legacy/ecore/src/lib/ecore_x/ecore_x_private.h @@ -29,6 +29,21 @@ struct _Ecore_X_Reply void *data; }; +typedef enum _Ecore_X_WM_Protocol { + /** + * If enabled the window manager will be asked to send a + * delete message instead of just closing (destroying) the window. + */ + ECORE_X_WM_PROTOCOL_DELETE_REQUEST, + + /** + * If enabled the window manager will be told that the window + * explicitly sets input focus. + */ + ECORE_X_WM_PROTOCOL_TAKE_FOCUS, + ECORE_X_WM_PROTOCOL_NUM +} Ecore_X_WM_Protocol; + extern Display *_ecore_x_disp; extern double _ecore_x_double_click_time; extern Time _ecore_x_event_last_time; @@ -37,11 +52,19 @@ extern int _ecore_x_event_last_root_x; extern int _ecore_x_event_last_root_y; extern Atom _ecore_x_atom_wm_delete_window; +extern Atom _ecore_x_atom_wm_take_focus; extern Atom _ecore_x_atom_wm_protocols; extern Atom _ecore_x_atom_wm_class; extern Atom _ecore_x_atom_wm_name; extern Atom _ecore_x_atom_motif_wm_hints; extern Atom _ecore_x_atom_win_layer; +extern Atom _ecore_x_atom_net_wm_desktop; +extern Atom _ecore_x_atom_net_current_desktop; +extern Atom _ecore_x_atom_net_wm_state; +extern Atom _ecore_x_atom_net_wm_state_above; +extern Atom _ecore_x_atom_net_wm_state_below; + +extern Atom _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM]; void _ecore_x_error_handler_init(void); void _ecore_x_event_handle_key_press(XEvent *xevent); diff --git a/legacy/ecore/src/lib/ecore_x/ecore_x_window_prop.c b/legacy/ecore/src/lib/ecore_x/ecore_x_window_prop.c index 03793e6344..444526ee68 100644 --- a/legacy/ecore/src/lib/ecore_x/ecore_x_window_prop.c +++ b/legacy/ecore/src/lib/ecore_x/ecore_x_window_prop.c @@ -1,6 +1,8 @@ #include "Ecore.h" #include "ecore_x_private.h" #include "Ecore_X.h" +#include +#include /** * To be documented. @@ -31,6 +33,57 @@ ecore_x_window_prop_property_set(Ecore_X_Window win, Ecore_X_Atom type, Ecore_X_ } } +/** + * To be documented. + * + * FIXME: To be fixed. + *
















+ */ +int +ecore_x_window_prop_property_get(Ecore_X_Window win, Ecore_X_Atom type, Ecore_X_Atom format, int size, unsigned char **data, int *num) +{ + Atom type_ret = 0; + int ret, size_ret = 0; + unsigned long num_ret = 0, bytes = 0, i; + unsigned char *prop_ret = NULL; + + if (!win) + win = DefaultRootWindow(_ecore_x_disp); + + ret = XGetWindowProperty(_ecore_x_disp, win, type, 0, LONG_MAX, False, format, &type_ret, &size_ret, &num_ret, &bytes, &prop_ret); + if (ret != Success) { + *data = NULL; + return 0; + } + + if (size != size_ret || !num_ret) { + XFree(prop_ret); + *data = NULL; + return 0; + } + + if (!(*data = malloc(num_ret * size / 8))) { + XFree(prop_ret); + return 0; + } + + for (i = 0; i < num_ret; i++) + switch (size) { + case 8: + *data[i] = prop_ret[i]; + break; + case 16: + ((uint16_t *) *data)[i] = ((uint16_t *) prop_ret)[i]; + break; + case 32: + ((uint32_t *) *data)[i] = ((uint32_t *) prop_ret)[i]; + break; + } + + *num = num_ret; + return 1; +} + /** * Set a window title. * @param win The window @@ -139,21 +192,24 @@ ecore_x_window_prop_name_class_get(Ecore_X_Window win, char **n, char **c) } /** - * Set a window property to get message for close. - * @param win The window + * Set or unset a wm protocol property. + * @param win The Window + * @param protocol The protocol to enable/disable * @param on On/Off * - * Set a window porperty to let a window manager send a delete message instead - * of just closing (destroying) the window. *
















*/ void -ecore_x_window_prop_delete_request_set(Ecore_X_Window win, int on) +ecore_x_window_prop_protocol_set(Ecore_X_Window win, + Ecore_X_WM_Protocol protocol, int on) { Atom *protos = NULL; + Atom proto; int protos_count = 0; int already_set = 0; int i; + + proto = _ecore_x_atoms_wm_protocols[protocol]; if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count)) { @@ -162,7 +218,7 @@ ecore_x_window_prop_delete_request_set(Ecore_X_Window win, int on) } for (i = 0; i < protos_count; i++) { - if (protos[i] == _ecore_x_atom_wm_delete_window) + if (protos[i] == proto) { already_set = 1; break; @@ -177,7 +233,7 @@ ecore_x_window_prop_delete_request_set(Ecore_X_Window win, int on) if (!new_protos) goto leave; for (i = 0; i < protos_count; i++) new_protos[i] = protos[i]; - new_protos[protos_count] = _ecore_x_atom_wm_delete_window; + new_protos[protos_count] = proto; XSetWMProtocols(_ecore_x_disp, win, new_protos, protos_count + 1); free(new_protos); } @@ -186,7 +242,7 @@ ecore_x_window_prop_delete_request_set(Ecore_X_Window win, int on) if (!already_set) goto leave; for (i = 0; i < protos_count; i++) { - if (protos[i] == _ecore_x_atom_wm_delete_window) + if (protos[i] == proto) { int j; @@ -306,6 +362,63 @@ ecore_x_window_prop_xy_set(Ecore_X_Window win, int x, int y) XSetWMNormalHints(_ecore_x_disp, win, &hints); } +/** + * Sets the sticky state for @win + * @param win The window + * @param on Boolean representing the sticky state + */ +void +ecore_x_window_prop_sticky_set(Ecore_X_Window win, int on) +{ + unsigned long val = 0xffffffff; + int ret, num = 0; + unsigned char *data = NULL; + + if (on) { + ecore_x_window_prop_property_set(win, _ecore_x_atom_net_wm_desktop, + XA_CARDINAL, 32, &val, 1); + return; + } + + ret = ecore_x_window_prop_property_get(0, _ecore_x_atom_net_current_desktop, + XA_CARDINAL, 32, &data, &num); + if (!ret || !num) + return; + + ecore_x_window_prop_property_set(win, _ecore_x_atom_net_wm_desktop, + XA_CARDINAL, 32, data, 1); + free(data); +} + +/** + * Sets the input mode for @win + * @param win The Window + * @param mode The input mode. See the description of + * @Ecore_X_Window_Input_Mode for details + * @return 1 if the input mode could be set, else 0 + */ +int +ecore_x_window_prop_input_mode_set(Ecore_X_Window win, Ecore_X_Window_Input_Mode mode) +{ + XWMHints *hints; + + if (!(hints = XGetWMHints(_ecore_x_disp, win))) + if (!(hints = XAllocWMHints())) + return 0; + + hints->flags |= InputHint; + hints->input = (mode == ECORE_X_WINDOW_INPUT_MODE_PASSIVE + || mode == ECORE_X_WINDOW_INPUT_MODE_ACTIVE_LOCAL); + XSetWMHints(_ecore_x_disp, win, hints); + XFree(hints); + + ecore_x_window_prop_protocol_set(win, ECORE_X_WM_PROTOCOL_TAKE_FOCUS, + (mode == ECORE_X_WINDOW_INPUT_MODE_ACTIVE_LOCAL + || mode == ECORE_X_WINDOW_INPUT_MODE_ACTIVE_GLOBAL)); + + return 1; +} + /** * To be documented. * @@ -330,16 +443,56 @@ ecore_x_window_prop_borderless_set(Ecore_X_Window win, int borderless) } /** - * To be documented. - * - * FIXME: To be fixed. + * Puts @win in the desired layer. This currently works with + * windowmanagers that are Gnome-compliant or support NetWM. + * + * @param win + * @param layer If < 0, @win will be put below all other windows. + * If > 0, @win will be "always-on-top" + * If = 0, @win will be put in the default layer. + * @return 1 if the state could be set else 0 + * *
















*/ -void +int ecore_x_window_prop_layer_set(Ecore_X_Window win, int layer) { + Ecore_X_Atom atom = 0; + unsigned char *data = NULL; + int i, val = 4, num = 0; /* normal layer */ + + if (layer < 0) { /* below */ + atom = _ecore_x_atom_net_wm_state_below; + val = 2; + } else if (layer > 0) { /* above */ + atom = _ecore_x_atom_net_wm_state_above; + val = 6; + } + + /* set the NetWM atoms + * get the atoms that are already set + */ + if (ecore_x_window_prop_property_get(win, _ecore_x_atom_net_wm_state, + XA_ATOM, 32, &data, &num)) { + /* and set the ones we're interested in */ + for (i = 0; i < num; i++) + if (data[i] == _ecore_x_atom_net_wm_state_below) + data[i] = (layer < 0); + else if (data[i] == _ecore_x_atom_net_wm_state_above) + data[i] = (layer > 0); + + ecore_x_window_prop_property_set(win, _ecore_x_atom_net_wm_state, + XA_ATOM, 32, data, num); + free(data); + } else + ecore_x_window_prop_property_set(win, _ecore_x_atom_net_wm_state, + XA_ATOM, 32, &atom, 1); + + /* set the gnome atom */ ecore_x_window_prop_property_set(win, _ecore_x_atom_win_layer, - XA_CARDINAL, 32, &layer, 1); + XA_CARDINAL, 32, &val, 1); + + return 1; } /** @@ -356,7 +509,7 @@ ecore_x_window_prop_withdrawn_set(Ecore_X_Window win, int withdrawn) long ret; memset(&hints, 0, sizeof(XWMHints)); - XGetWMNormalHints(_ecore_x_disp, win, &hints, &ret); + XGetWMNormalHints(_ecore_x_disp, win, (XSizeHints *) &hints, &ret); if (!withdrawn) hints.initial_state &= ~WithdrawnState; @@ -365,6 +518,6 @@ ecore_x_window_prop_withdrawn_set(Ecore_X_Window win, int withdrawn) hints.flags = WindowGroupHint | StateHint; XSetWMHints(_ecore_x_disp, win, &hints); - XSetWMNormalHints(_ecore_x_disp, win, &hints); + XSetWMNormalHints(_ecore_x_disp, win, (XSizeHints *) &hints); }