~kokoto-java/kazam/depencie-and-stuff

« back to all changes in this revision

Viewing changes to kazam/frontend/window_area.py

  • Committer: David Klasinc
  • Date: 2012-11-11 19:36:05 UTC
  • mfrom: (193.2.82 unstable)
  • Revision ID: bigwhale@lubica.net-20121111193605-vh3fxglxwfhyh8ne
Merged from unstable branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
#
 
3
#       window_select.py
 
4
#
 
5
#       Copyright 2012 David Klasinc <bigwhale@lubica.net>
 
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 3 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
 
18
#       along with this program; if not, write to the Free Software
 
19
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
20
#       MA 02110-1301, USA.
 
21
 
 
22
import time
 
23
import cairo
 
24
import logging
 
25
logger = logging.getLogger("Window Select")
 
26
 
 
27
from gettext import gettext as _
 
28
 
 
29
from gi.repository import Gtk, GObject, Gdk, Wnck, GdkX11
 
30
 
 
31
from kazam.backend.constants import *
 
32
class AreaWindow(GObject.GObject):
 
33
 
 
34
    __gsignals__ = {
 
35
        "area-selected" : (GObject.SIGNAL_RUN_LAST,
 
36
                             None,
 
37
                               (),
 
38
                                ),
 
39
        "area-canceled" : (GObject.SIGNAL_RUN_LAST,
 
40
                             None,
 
41
                               (),
 
42
                                ),
 
43
    }
 
44
 
 
45
    def __init__(self):
 
46
        super(AreaWindow, self).__init__()
 
47
        logger.debug("Initializing select window.")
 
48
 
 
49
        self.startx = 0
 
50
        self.starty = 0
 
51
        self.endx = 0
 
52
        self.endy = 0
 
53
        self.height = 0
 
54
        self.width = 0
 
55
 
 
56
        self.window = Gtk.Window()
 
57
        self.box = Gtk.Box()
 
58
        self.drawing = Gtk.DrawingArea()
 
59
        self.box.pack_start(self.drawing, True, True, 0)
 
60
        self.drawing.set_size_request(500, 500)
 
61
        self.window.add(self.box)
 
62
 
 
63
        self.window.connect("delete-event", Gtk.main_quit)
 
64
        self.window.connect("key-press-event", self.cb_keypress_event)
 
65
 
 
66
        self.drawing.connect("draw", self.cb_draw)
 
67
        self.drawing.connect("motion-notify-event", self.cb_draw_motion_notify_event)
 
68
        self.drawing.connect("button-press-event", self.cb_draw_button_press_event)
 
69
        self.drawing.connect("leave-notify-event", self.cb_leave_notify_event)
 
70
        self.drawing.add_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_HINT_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK)
 
71
 
 
72
        self.window.set_border_width(0)
 
73
        self.window.set_app_paintable(True)
 
74
        self.window.set_has_resize_grip(False)
 
75
        self.window.set_resizable(True)
 
76
        self.window.set_decorated(False)
 
77
        self.window.set_property("skip-taskbar-hint", True)
 
78
        self.window.set_keep_above(True)
 
79
        self.screen = self.window.get_screen()
 
80
        self.visual = self.screen.get_rgba_visual()
 
81
 
 
82
        self.disp = GdkX11.X11Display.get_default()
 
83
        self.dm = Gdk.Display.get_device_manager(self.disp)
 
84
        self.pntr_device = self.dm.get_client_pointer()
 
85
 
 
86
        if self.visual is not None and self.screen.is_composited():
 
87
            logger.debug("Compositing window manager detected.")
 
88
            self.window.set_visual(self.visual)
 
89
            self.compositing = True
 
90
        else:
 
91
            self.compositing = False
 
92
 
 
93
        (scr, x, y) = self.pntr_device.get_position()
 
94
        cur = scr.get_monitor_at_point(x, y)
 
95
        self.window.move(HW.screens[cur]['x'],
 
96
                         HW.screens[cur]['y'])
 
97
        self.window.fullscreen()
 
98
 
 
99
        crosshair_cursor = Gdk.Cursor(Gdk.CursorType.CROSSHAIR)
 
100
        self.last_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)
 
101
        self.gdk_win = self.window.get_root_window()
 
102
        self.gdk_win.set_cursor(crosshair_cursor)
 
103
 
 
104
    def cb_draw_motion_notify_event(self, widget, event):
 
105
        (state, x, y, mask) = event.window.get_device_position(self.pntr_device)
 
106
        if mask & Gdk.ModifierType.BUTTON1_MASK:
 
107
            self.endx = int(event.x)
 
108
            self.endy = int(event.y)
 
109
            self.width  = self.endx - self.startx
 
110
            self.height = self.endy - self.starty
 
111
        widget.queue_draw()
 
112
        return True
 
113
 
 
114
    def cb_draw_button_press_event(self, widget, event):
 
115
        self.startx = int(event.x)
 
116
        self.starty = int(event.y)
 
117
        self.endx = 0
 
118
        self.endy = 0
 
119
        self.width  = 0
 
120
        self.height = 0
 
121
 
 
122
    def cb_leave_notify_event(self, widget, event):
 
123
        (scr, x, y) = self.pntr_device.get_position()
 
124
        cur = scr.get_monitor_at_point(x, y)
 
125
        self.window.unfullscreen()
 
126
        self.window.move(HW.screens[cur]['x'],
 
127
                         HW.screens[cur]['y'])
 
128
        self.window.fullscreen()
 
129
        logger.debug("Move to X: {0} Y: {1}".format(HW.screens[cur]['x'], HW.screens[cur]['y']))
 
130
        return True
 
131
 
 
132
    def cb_keypress_event(self, widget, event):
 
133
        (op, keycode) = event.get_keycode()
 
134
        self.gdk_win.set_cursor(self.last_cursor)
 
135
        if keycode == 36 or keycode == 104: # Enter
 
136
            self.window.hide()
 
137
            self.width = abs(self.width)
 
138
            self.height = abs(self.height)
 
139
            self.emit("area-selected")
 
140
        elif keycode == 9: # ESC
 
141
            self.window.hide()
 
142
            self.emit("area-canceled")
 
143
 
 
144
    def cb_draw(self, widget, cr):
 
145
        (w, h) = self.window.get_size()
 
146
 
 
147
        if self.compositing:
 
148
            cr.set_source_rgba(0.0, 0.0, 0.0, 0.45)
 
149
        else:
 
150
            cr.set_source_rgb(0.5, 0.5, 0.5)
 
151
 
 
152
        cr.set_operator(cairo.OPERATOR_SOURCE)
 
153
        cr.paint()
 
154
 
 
155
        cr.set_operator(cairo.OPERATOR_SOURCE)
 
156
 
 
157
        # Draw the selection area
 
158
        cr.move_to(self.startx, self.starty)
 
159
        cr.set_source_rgb(1.0, 0.0, 0.0)
 
160
        cr.rectangle(self.startx, self.starty, self.width, self.height)
 
161
        cr.stroke()
 
162
 
 
163
        if self.compositing:
 
164
            cr.set_source_rgba(0.0, 0.0, 0.0, 0.0)
 
165
        else:
 
166
            cr.set_source_rgb(0.0, 0.0, 0.0)
 
167
 
 
168
        cr.rectangle(self.startx, self.starty, self.width, self.height)
 
169
        cr.fill()
 
170
 
 
171
        cr.set_operator(cairo.OPERATOR_OVER)
 
172
 
 
173
        self._outline_text(cr, w, h, 30, _("Select an area by clicking and dragging."))
 
174
        self._outline_text(cr, w, h + 50, 26, _("Press ENTER to confirm or ESC to cancel"))
 
175
 
 
176
        self._outline_text(cr, w, h + 100, 20, "({0} x {1})".format(abs(self.height), abs(self.height)))
 
177
        cr.set_operator(cairo.OPERATOR_SOURCE)
 
178
 
 
179
    def _outline_text(self, cr, w, h, size, text):
 
180
        cr.set_font_size(size)
 
181
        try:
 
182
            cr.select_font_face("Ubuntu", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
 
183
        except:
 
184
            pass
 
185
        te = cr.text_extents(text)
 
186
        cr.set_line_width(2.0)
 
187
        cx = w/2 - te[2]/2
 
188
        cy = h/2 - te[3]/2
 
189
        if self.compositing:
 
190
            cr.set_source_rgba(0.4, 0.4, 0.4, 1.0)
 
191
        else:
 
192
            cr.set_source_rgb(0.4, 0.4, 0.4)
 
193
 
 
194
        cr.move_to(cx, cy)
 
195
        cr.text_path(text)
 
196
        cr.stroke()
 
197
        if self.compositing:
 
198
            cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
 
199
        else:
 
200
            cr.set_source_rgb(1.0, 1.0, 1.0)
 
201
        cr.move_to(cx, cy)
 
202
        cr.show_text(text)