summaryrefslogtreecommitdiff
path: root/libdecor/build/fl_libdecor.c
blob: ab6cee5c213e3f2e193639cec885b0553e3e74f1 (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
//
// Interface with the libdecor library for the Fast Light Tool Kit (FLTK).
//
// Copyright 2022-2023 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file.  If this
// file is missing or damaged, see the license at:
//
//     https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
//     https://www.fltk.org/bugs.php
//

/* Improvements to libdecor.c without modifying libdecor.c itself */

#include "xdg-shell-client-protocol.h"
#ifdef XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION
#  define HAVE_XDG_SHELL_V6 1
#endif

#define libdecor_frame_set_minimized libdecor_frame_set_minimized_orig
#define libdecor_new libdecor_new_orig
#include <dlfcn.h>
static void *dlopen_corrected(const char *, int);
#define dlopen(A, B) dlopen_corrected(A, B)
#include "../src/libdecor.c"
#undef dlopen
#undef libdecor_frame_set_minimized
#undef libdecor_new

extern bool fl_libdecor_using_weston(void);
extern const struct libdecor_plugin_description *fl_libdecor_plugin_description;
//#include <stdio.h>

// we have a built-in plugin so don't need a fallback one
struct libdecor_plugin *libdecor_fallback_plugin_new(struct libdecor *context) {
  return NULL;
}

// see get_libdecor_plugin_description() explaining why this is useful
static void *dlopen_corrected(const char *filename, int flags) {
  static int best_priority = -1;
  void *retval = dlopen(filename, flags);
  if (retval) {
    const struct libdecor_plugin_description *description =
        (const struct libdecor_plugin_description*)dlsym(retval, "libdecor_plugin_description");
    if (description && description->priorities->priority > best_priority) {
        fl_libdecor_plugin_description = description;
        best_priority = description->priorities->priority;
    }
  }
  return retval;
}


LIBDECOR_EXPORT void libdecor_frame_set_minimized(struct libdecor_frame *frame)
{
  static bool done = false;
  static bool using_weston = false;
  if (!done) {
    typedef bool (*ext_f)(void);
    volatile ext_f ext = fl_libdecor_using_weston;
    done = true;
    if (ext) using_weston = fl_libdecor_using_weston();
//fprintf(stderr, "fl_libdecor_using_weston=%p using_weston=%d\n", fl_libdecor_using_weston, using_weston);
    if (using_weston) { // determine the version of the running Weston compositor
      FILE *pipe = popen("weston --version", "r");
      if (pipe) {
        char line[50], *p;
        int version = 0;
        p = fgets(line, sizeof(line), pipe);
        pclose(pipe);
        if (p) p = strchr(line, ' ');
        if (p) {
          sscanf(p, "%d", &version);
          // Weston version 10 has fixed the bug handled here
          if (version >= 10) using_weston = false;
        }
      }
    }
  }
  if (using_weston) libdecor_frame_set_visibility(frame, false);
  libdecor_frame_set_minimized_orig(frame);
}


/*
 By default, FLTK modifies libdecor's libdecor_new() function to determine the plugin as follows :
 1) the directory pointed by environment variable LIBDECOR_PLUGIN_DIR or, in absence of this variable,
    by -DLIBDECOR_PLUGIN_DIR=xxx at build time is searched for a libdecor plugin;
 2) if this directory does not exist or contains no plugin, the built-in plugin is used.
    * if FLTK was built with package libgtk-3-dev, the GTK plugin is used
    * if FLTK was built without package libgtk-3-dev, the Cairo plugin is used
 
 If FLTK was built with OPTION_USE_SYSTEM_LIBDECOR turned ON, the present modification
 isn't compiled, so the plugin-searching algorithm of libdecor_new() in libdecor-0.so is used.
 This corresponds to step 1) above and to use no titlebar is no plugin is found.
 
 N.B.: only the system package is built with a meaningful value of -DLIBDECOR_PLUGIN_DIR=
 so a plugin may be loaded that way only if FLTK was built with OPTION_USE_SYSTEM_LIBDECOR turned ON.
 
 */
LIBDECOR_EXPORT struct libdecor *libdecor_new(struct wl_display *wl_display, struct libdecor_interface *iface)
{
  struct libdecor *context;
  context = zalloc(sizeof *context);
  context->ref_count = 1;
  context->iface = iface;
  context->wl_display = wl_display;
  context->wl_registry = wl_display_get_registry(wl_display);
  wl_registry_add_listener(context->wl_registry, &registry_listener, context);
  context->init_callback = wl_display_sync(context->wl_display);
  wl_callback_add_listener(context->init_callback, &init_wl_display_callback_listener, context);
  wl_list_init(&context->frames);
  // attempt to dynamically load a libdecor plugin with dlopen()
  if (init_plugins(context) != 0) { // attempt to load plugin by dlopen()
    // no plug-in was found by dlopen(), use built-in plugin instead
    // defined in the source code of the built-in plugin:  libdecor-cairo.c or libdecor-gtk.c
    extern const struct libdecor_plugin_description libdecor_plugin_description;
    context->plugin = libdecor_plugin_description.constructor(context);
  }

  wl_display_flush(wl_display);
  return context;
}