Mirror of Awesome WM window manager
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

selection.c 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * selection.c - Selection handling
  3. *
  4. * Copyright © 2009 Julien Danjou <julien@danjou.info>
  5. * Copyright © 2009 Gregor Best <farhaven@googlemail.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. */
  22. /** awesome selection (clipboard) API
  23. * @author Julien Danjou &lt;julien@danjou.info&gt;
  24. * @copyright 2008-2009 Julien Danjou
  25. * @module selection
  26. */
  27. #include "selection.h"
  28. #include "globalconf.h"
  29. #include "common/atoms.h"
  30. #include "event.h"
  31. #include "xwindow.h"
  32. #include <xcb/xcb_atom.h>
  33. #include <xcb/xcb_event.h>
  34. /** Get the selection (clipboard) content.
  35. *
  36. * @return A string with the selection (clipboard) content.
  37. * @staticfct selection
  38. */
  39. static xcb_window_t selection_window = XCB_NONE;
  40. /** Get the current X selection buffer.
  41. * \param L The Lua VM state.
  42. * \return The number of elements pushed on stack.
  43. * \luastack
  44. * \lreturn A string with the current X selection buffer.
  45. */
  46. static int
  47. luaA_selection_get(lua_State *L)
  48. {
  49. luaA_deprecate(L, "selection.getter(\"PRIMARY\", \"UTF8_STRING\")");
  50. if(selection_window == XCB_NONE)
  51. {
  52. xcb_screen_t *screen = globalconf.screen;
  53. uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
  54. uint32_t values[] = { screen->black_pixel, 1, XCB_EVENT_MASK_PROPERTY_CHANGE };
  55. selection_window = xcb_generate_id(globalconf.connection);
  56. xcb_create_window(globalconf.connection, screen->root_depth, selection_window, screen->root,
  57. 0, 0, 1, 1, 0, XCB_COPY_FROM_PARENT, screen->root_visual,
  58. mask, values);
  59. xwindow_set_class_instance(selection_window);
  60. xwindow_set_name_static(selection_window, "Awesome selection window");
  61. }
  62. xcb_convert_selection(globalconf.connection, selection_window,
  63. XCB_ATOM_PRIMARY, UTF8_STRING, XSEL_DATA, globalconf.timestamp);
  64. xcb_flush(globalconf.connection);
  65. xcb_generic_event_t *event;
  66. while(true)
  67. {
  68. event = xcb_wait_for_event(globalconf.connection);
  69. if(!event)
  70. return 0;
  71. if(XCB_EVENT_RESPONSE_TYPE(event) != XCB_SELECTION_NOTIFY)
  72. {
  73. /* \todo Eventually, this may be rewritten with adding a static
  74. * buffer, then a event handler for XCB_SELECTION_NOTIFY, then call
  75. * xcb_event_poll_for_event_loop() and awesome_refresh(),
  76. * then check if some static buffer has been filled with data.
  77. * If yes, that'd be the xsel data, otherwise, re-loop.
  78. * Anyway that's still brakes the socket or D-Bus, so maybe using
  79. * ev_loop() would be even better.
  80. */
  81. event_handle(event);
  82. p_delete(&event);
  83. awesome_refresh();
  84. continue;
  85. }
  86. xcb_selection_notify_event_t *event_notify =
  87. (xcb_selection_notify_event_t *) event;
  88. if(event_notify->selection == XCB_ATOM_PRIMARY
  89. && event_notify->property != XCB_NONE)
  90. {
  91. xcb_icccm_get_text_property_reply_t prop;
  92. xcb_get_property_cookie_t cookie =
  93. xcb_icccm_get_text_property(globalconf.connection,
  94. event_notify->requestor,
  95. event_notify->property);
  96. if(xcb_icccm_get_text_property_reply(globalconf.connection,
  97. cookie, &prop, NULL))
  98. {
  99. lua_pushlstring(L, prop.name, prop.name_len);
  100. xcb_icccm_get_text_property_reply_wipe(&prop);
  101. xcb_delete_property(globalconf.connection,
  102. event_notify->requestor,
  103. event_notify->property);
  104. p_delete(&event);
  105. return 1;
  106. }
  107. else
  108. break;
  109. }
  110. }
  111. p_delete(&event);
  112. return 0;
  113. }
  114. static void
  115. move_global_to_table(lua_State *L, int index, const char *global_name, const char *local_name)
  116. {
  117. index = luaA_absindex(L, index);
  118. /* Get the global */
  119. lua_getglobal(L, global_name);
  120. assert(!lua_isnil(L, -1));
  121. /* Save it locally */
  122. lua_setfield(L, index, local_name);
  123. /* Set the global to nil */
  124. lua_pushnil(L);
  125. lua_setglobal(L, global_name);
  126. }
  127. void
  128. selection_setup(lua_State *L)
  129. {
  130. /* This table will be the "selection" global */
  131. lua_newtable(L);
  132. /* Setup a metatable */
  133. lua_newtable(L);
  134. /* metatable.__index = metatable */
  135. lua_pushvalue(L, -1);
  136. lua_setfield(L, -2, "__index");
  137. /* Set some more fields */
  138. lua_pushcfunction(L, luaA_selection_get);
  139. lua_setfield(L, -2, "__call");
  140. move_global_to_table(L, -2, "selection_acquire", "acquire");
  141. move_global_to_table(L, -2, "selection_getter", "getter");
  142. move_global_to_table(L, -2, "selection_watcher", "watcher");
  143. /* Set the metatable */
  144. lua_setmetatable(L, -2);
  145. /* Set the "selection" global */
  146. lua_setglobal(L, "selection");
  147. }
  148. // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80