summaryrefslogtreecommitdiffstats
path: root/client/red_window.h
blob: dbd0c79719837bab6ca0d77e2c367ddd02b2caf4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
   Copyright (C) 2009 Red Hat, Inc.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _H_RED_WINDOW
#define _H_RED_WINDOW

#include "red_drawable.h"
#include <spice/protocol.h>
#include "red_key.h"
#include "red_window_p.h"
#include "cursor.h"

class Menu;
class Icon;

class RedWindow: public RedDrawable, private RedWindow_p {
public:
    class Listener;

    enum {
        DEFAULT_SCREEN = -1,
    };

    RedWindow(RedWindow::Listener& listener, int screen_id = DEFAULT_SCREEN);
    virtual ~RedWindow();

    void move_and_resize(int x, int y, int width, int height);
    void resize(int width, int height);
    void move(int x, int y);
    void position_after(RedWindow *after);
    void raise();
    void show(int screen_id);
    void external_show();
    void hide();
    void minimize();
    void activate();
    void set_title(std::string& title);
    void set_icon(Icon *icon);
    virtual RedDrawable::Format get_format();

    enum Type {
        TYPE_INVALID,
        TYPE_NORMAL,
        TYPE_FULLSCREEN,
    };
    void set_type(Type type) { _type = type;}
    SpicePoint get_position();
    virtual SpicePoint get_size();
    bool get_mouse_anchor_point(SpicePoint& pt);

    void set_mouse_position(int x, int y);
    void set_cursor(LocalCursor* local_cursor);
    void hide_cursor();
    void show_cursor();
    void capture_mouse();
    void release_mouse();
    void start_key_interception();
    void stop_key_interception();
    int set_menu(Menu* menu);

#ifdef USE_OPENGL
    void untouch_context();
    RedGlContext create_context_gl();
    RedPbuffer create_pbuff(int width, int height);
    void set_render_pbuff(RedPbuffer pbuff);
    void set_render_fbo(GLuint fbo);
    void set_gl_context(RedGlContext context);

    void set_type_gl();
    void unset_type_gl();
#endif

    int get_screen_num();

    static void init();
    static void cleanup();

    Listener& get_listener() { return _listener;}

private:
    void on_focus_in();
    void on_focus_out();
    void on_pointer_enter(int x, int y, unsigned int buttons_state);
    void on_pointer_leave();

    void do_start_key_interception();
    void do_stop_key_interception();

private:
    Listener& _listener;
    SpicePoint _window_size;
    Type _type;
    LocalCursor* _local_cursor;
    bool _cursor_visible;
    bool _trace_key_interception;
    bool _key_interception_on;
    Menu* _menu;

    friend class RedWindow_p;
};

class RedWindow::Listener {
public:
    virtual ~Listener() {}
    virtual void on_exposed_rect(const SpiceRect& area) = 0;

    virtual void on_pointer_enter(int x, int y, unsigned int buttons_state) = 0;
    virtual void on_pointer_motion(int x, int y, unsigned int buttons_state) = 0;
    virtual void on_pointer_leave() = 0;
    virtual void on_mouse_button_press(SpiceMouseButton button, unsigned int buttons_state) = 0;
    virtual void on_mouse_button_release(SpiceMouseButton button, unsigned int buttons_state) = 0;

    virtual void on_key_press(RedKey key) = 0;
    virtual void on_key_release(RedKey key) = 0;
    virtual void on_char(uint32_t ch) = 0;

    virtual void on_deactivate() = 0;
    virtual void on_activate() = 0;

    virtual void on_start_key_interception() = 0;
    virtual void on_stop_key_interception() = 0;
    virtual void enter_modal_loop() = 0;
    virtual void exit_modal_loop() = 0;

    virtual void pre_migrate() { }
    virtual void post_migrate() { }
};

/*class REGION {
    void get_bbox(SpiceRect& bbox) const;
    bool contains_point(int x, int y) const;

};*/

template <class REGION>
static bool find_anchor_point(const REGION& region, SpicePoint& pt)
{
    static const unsigned int lookup_size = 20;
    unsigned int width;
    unsigned int height;
    SpiceRect bbox;

    region.get_bbox(bbox);
    width = bbox.right - bbox.left;
    height = bbox.bottom - bbox.top;

    int div = 2;

    for (;;) {
        unsigned int h_unit;
        unsigned int v_unit;

        if ((v_unit = height / div) * 2 < lookup_size || (h_unit = width / div) * 2 < lookup_size) {
            return false;
        }

        for (unsigned int y = v_unit; y < v_unit * div; y += v_unit * 2) {
            for (unsigned int x = h_unit; x < h_unit * div; x += h_unit * 2) {
                if (!region.contains_point(bbox.left + x, bbox.top + y)) {
                    continue;
                }

                SpiceRect r;
                r.left = bbox.left + x - lookup_size / 2;
                r.right = r.left + lookup_size;
                r.top = bbox.top + y - lookup_size / 2;
                r.bottom = r.top + lookup_size;

                if (!region.contains_point(r.left, r.top) ||
                    !region.contains_point(r.right, r.top) ||
                    !region.contains_point(r.left, r.bottom) ||
                    !region.contains_point(r.right, r.bottom)) {
                    continue;
                }
                pt.x = bbox.left + x;
                pt.y = bbox.top + y;
                return true;
            }
        }
        div *= 2;
    }
}

#endif